]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #3899 from ton31337/fix/remove_private_as_with_local_as
authorLou Berger <lberger@labn.net>
Thu, 4 Apr 2019 20:08:42 +0000 (16:08 -0400)
committerGitHub <noreply@github.com>
Thu, 4 Apr 2019 20:08:42 +0000 (16:08 -0400)
bgpd: Remove private AS numbers if local-as is defined

393 files changed:
.dockerignore
.github/ISSUE_TEMPLATE.md [deleted file]
.github/ISSUE_TEMPLATE/bug_report.md [new file with mode: 0644]
.github/PULL_REQUEST_TEMPLATE.md [deleted file]
.github/PULL_REQUEST_TEMPLATE/pr.md [new file with mode: 0644]
Makefile.am
README.md
alpine/APKBUILD.in
alpine/docker-start [deleted file]
babeld/babel_interface.c
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfd_packet.c
bfdd/bfdd_vty.c
bfdd/config.c
bfdd/control.c
bfdd/ptm_adapter.c
bgpd/bgp_addpath.c
bgpd/bgp_advertise.c
bgpd/bgp_aspath.c
bgpd/bgp_attr.c
bgpd/bgp_attr_evpn.c
bgpd/bgp_attr_evpn.h
bgpd/bgp_clist.c
bgpd/bgp_community.c
bgpd/bgp_ecommunity.c
bgpd/bgp_encap_tlv.c
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_filter.c
bgpd/bgp_fsm.c
bgpd/bgp_labelpool.c
bgpd/bgp_lcommunity.c
bgpd/bgp_mac.c
bgpd/bgp_mac.h
bgpd/bgp_main.c
bgpd/bgp_mpath.c
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_nht.c
bgpd/bgp_pbr.c
bgpd/bgp_rd.c
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap.c
bgpd/bgp_rpki.c
bgpd/bgp_snmp.c
bgpd/bgp_updgrp.c
bgpd/bgp_updgrp_packet.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c
bgpd/bgpd.h
bgpd/rfapi/bgp_rfapi_cfg.c
bgpd/rfapi/rfapi_import.c
bgpd/rfapi/vnc_debug.c
bgpd/rfapi/vnc_zebra.c
configure.ac
doc/developer/building-frr-for-centos6.rst
doc/developer/building-frr-for-centos7.rst
doc/developer/building-frr-for-debian8.rst
doc/developer/building-frr-for-fedora.rst [new file with mode: 0644]
doc/developer/building-frr-for-fedora24.rst [deleted file]
doc/developer/building-frr-for-freebsd10.rst
doc/developer/building-frr-for-freebsd11.rst
doc/developer/building-frr-for-freebsd9.rst
doc/developer/building-frr-for-netbsd6.rst
doc/developer/building-frr-for-netbsd7.rst
doc/developer/building-frr-for-omnios.rst
doc/developer/building-frr-for-openbsd6.rst
doc/developer/building-frr-for-openwrt.rst
doc/developer/building-frr-for-ubuntu1404.rst
doc/developer/building-frr-for-ubuntu1604.rst
doc/developer/building-frr-for-ubuntu1804.rst
doc/developer/building-libyang.rst
doc/developer/building.rst
doc/developer/conf.py
doc/developer/hooks.rst
doc/developer/include-compile.rst [new file with mode: 0644]
doc/developer/logging.rst
doc/developer/memtypes.rst
doc/developer/ospf-api.rst
doc/developer/ospf-sr.rst
doc/developer/packaging-debian.rst
doc/developer/packaging-redhat.rst [new file with mode: 0644]
doc/developer/packaging.rst
doc/developer/subdir.am
doc/developer/topotests-snippets.rst
doc/developer/topotests.rst
doc/developer/vtysh.rst
doc/developer/workflow.rst
doc/manpages/conf.py
doc/manpages/defines.rst
doc/user/basic.rst
doc/user/bgp.rst
doc/user/flowspec.rst
doc/user/installation.rst
doc/user/ospfd.rst
doc/user/pbr.rst
doc/user/pim.rst
doc/user/sharp.rst
doc/user/zebra.rst
docker/alpine/Dockerfile
docker/alpine/alpine-build.sh [deleted file]
docker/alpine/build.sh
docker/alpine/builder [deleted file]
docker/alpine/docker-start [new file with mode: 0755]
eigrpd/eigrp_fsm.c
eigrpd/eigrp_hello.c
eigrpd/eigrp_vty.c
isisd/dict.c
isisd/isis_adjacency.c
isisd/isis_dlpi.c
isisd/isis_main.c
isisd/isis_pdu.c
isisd/isis_redist.c
isisd/isis_tlvs.c
isisd/isis_zebra.c
lib/bfd.c
lib/command.c
lib/command_graph.c
lib/distribute.c
lib/event_counter.c [deleted file]
lib/event_counter.h [deleted file]
lib/ferr.c
lib/filter.c
lib/frr_pthread.c
lib/frr_zmq.c
lib/frrstr.c
lib/grammar_sandbox.c
lib/hash.c
lib/if.c
lib/if_rmap.c
lib/imsg.c
lib/jhash.c
lib/keychain.c
lib/libfrr.c
lib/log.c
lib/module.c
lib/netns_linux.c
lib/nexthop.c
lib/nexthop.h
lib/nexthop_group.c
lib/nexthop_group.h
lib/northbound.c
lib/northbound_confd.c
lib/plist.c
lib/pqueue.c
lib/prefix.c
lib/prefix.h
lib/privs.c
lib/privs.h
lib/routemap.c
lib/sigevent.c
lib/subdir.am
lib/thread.c
lib/vrf.c
lib/vrf.h
lib/vty.c
lib/vty.h
lib/workqueue.c
lib/yang_wrappers.c
lib/zclient.c
nhrpd/linux.c
nhrpd/netlink_arp.c
nhrpd/nhrp_interface.c
nhrpd/vici.c
ospf6d/ospf6_area.c
ospf6d/ospf6_asbr.c
ospf6d/ospf6_interface.c
ospf6d/ospf6_lsa.c
ospf6d/ospf6_lsdb.c
ospf6d/ospf6_message.c
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_route.c
ospf6d/ospf6_snmp.c
ospf6d/ospf6_spf.c
ospf6d/ospf6_zebra.c
ospfd/ospf_api.c
ospfd/ospf_apiserver.c
ospfd/ospf_asbr.c
ospfd/ospf_ism.c
ospfd/ospf_packet.c
ospfd/ospf_ri.c
ospfd/ospf_snmp.c
ospfd/ospf_spf.c
ospfd/ospf_sr.c
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pbrd/pbr_map.c
pbrd/pbr_nht.c
pbrd/pbr_nht.h
pbrd/pbr_vty.c
pbrd/pbr_zebra.c
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_ifchannel.c
pimd/pim_igmp_mtrace.c
pimd/pim_join.c
pimd/pim_jp_agg.c
pimd/pim_main.c
pimd/pim_mroute.c
pimd/pim_msdp.c
pimd/pim_neighbor.c
pimd/pim_nht.c
pimd/pim_nht.h
pimd/pim_oil.c
pimd/pim_oil.h
pimd/pim_register.c
pimd/pim_rp.c
pimd/pim_rp.h
pimd/pim_rpf.c
pimd/pim_rpf.h
pimd/pim_ssm.c
pimd/pim_upstream.c
pimd/pim_upstream.h
pimd/pim_zebra.c
pimd/pim_zlookup.c
pimd/pimd.c
redhat/README.rpm_build.md [deleted file]
redhat/daemons [deleted file]
redhat/frr.init [deleted file]
redhat/frr.service [deleted file]
redhat/frr.spec.in
ripd/rip_cli.c
ripd/rip_interface.c
ripd/rip_northbound.c
ripngd/ripng_interface.c
ripngd/ripng_zebra.c
sharpd/sharp_globals.h
sharpd/sharp_vty.c
sharpd/sharp_zebra.c
sharpd/sharp_zebra.h
staticd/static_nht.c
staticd/static_vty.c
tests/bgpd/test_bgp_table.c
tests/bgpd/test_mpath.c
tests/lib/cxxcompat.c
tests/lib/test_privs.c
tests/lib/test_srcdest_table.c
tests/lib/test_table.c
tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref
tests/topotests/bfd-topo2/__init__.py [new file with mode: 0644]
tests/topotests/bfd-topo2/r1/bfdd.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r1/ipv4_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r1/ipv6_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r1/peers.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r2/ipv4_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r2/ipv6_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r2/ospf6d.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r2/ospfd.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r2/peers.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r3/ipv4_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r3/ipv6_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r3/ospfd.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r3/peers.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r3/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r4/bfdd.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r4/ipv4_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r4/ipv6_routes.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r4/ospf6d.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/r4/peers.json [new file with mode: 0644]
tests/topotests/bfd-topo2/r4/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-topo2/test_bfd_topo2.dot [new file with mode: 0644]
tests/topotests/bfd-topo2/test_bfd_topo2.jpg [new file with mode: 0644]
tests/topotests/bfd-topo2/test_bfd_topo2.py [new file with mode: 0644]
tests/topotests/docker/build.sh
tests/topotests/docker/frr-topotests.sh
tests/topotests/ldp-vpls-topo1/r1/zebra.conf
tests/topotests/ldp-vpls-topo1/r2/zebra.conf
tests/topotests/ldp-vpls-topo1/r3/zebra.conf
tests/topotests/lib/topogen.py
tests/topotests/lib/topotest.py
tests/topotests/pim-basic/mcast-rx.py [new file with mode: 0755]
tests/topotests/pim-basic/mcast-tx.py [new file with mode: 0755]
tests/topotests/pim-basic/r1/pimd.conf [new file with mode: 0644]
tests/topotests/pim-basic/r1/zebra.conf [new file with mode: 0644]
tests/topotests/pim-basic/r2/pimd.conf [new file with mode: 0644]
tests/topotests/pim-basic/r2/zebra.conf [new file with mode: 0644]
tests/topotests/pim-basic/test_pim.py [new file with mode: 0644]
tools/coccinelle/alloc_cast.cocci [new file with mode: 0644]
tools/coccinelle/array_size.cocci [new file with mode: 0644]
tools/coccinelle/badty.cocci [new file with mode: 0644]
tools/coccinelle/badzero.cocci [new file with mode: 0644]
tools/coccinelle/boolconv.cocci [new file with mode: 0644]
tools/coccinelle/boolinit.cocci [new file with mode: 0644]
tools/coccinelle/boolreturn.cocci [new file with mode: 0644]
tools/coccinelle/cond_no_effect.cocci [new file with mode: 0644]
tools/coccinelle/deref_null.cocci [new file with mode: 0644]
tools/coccinelle/double_lock.cocci [new file with mode: 0644]
tools/coccinelle/doublebitand.cocci [new file with mode: 0644]
tools/coccinelle/doubleinit.cocci [new file with mode: 0644]
tools/coccinelle/doubletest.cocci [new file with mode: 0644]
tools/coccinelle/ifaddr.cocci [new file with mode: 0644]
tools/coccinelle/ifnullxfree.cocci [new file with mode: 0644]
tools/coccinelle/itnull.cocci [new file with mode: 0644]
tools/coccinelle/mini_lock.cocci [new file with mode: 0644]
tools/coccinelle/noderef.cocci [new file with mode: 0644]
tools/coccinelle/replace-strncpy.cocci [new file with mode: 0644]
tools/coccinelle/returnvar.cocci [new file with mode: 0644]
tools/coccinelle/semicolon.cocci [new file with mode: 0644]
tools/coccinelle/strncpy_truncation.cocci [new file with mode: 0644]
tools/coccinelle/unsigned_lesser_than_zero.cocci [new file with mode: 0644]
tools/coccinelle/vty_check.cocci [new file with mode: 0644]
tools/coccinelle/vty_index.cocci [new file with mode: 0644]
tools/coccinelle/xcalloc-simple.cocci [new file with mode: 0644]
tools/coccinelle/xfree.cocci [new file with mode: 0644]
tools/coccinelle/xfreeaddr.cocci [new file with mode: 0644]
tools/coccinelle/xmalloc_returnval.cocci [new file with mode: 0644]
tools/coccinelle/zprivs.cocci [new file with mode: 0644]
tools/etc/frr/daemons
tools/etc/frr/support_bundle_commands.conf [new file with mode: 0644]
tools/frr.in
tools/frrcommon.sh.in
tools/generate_support_bundle.py [new file with mode: 0644]
tools/vty_check.cocci [deleted file]
tools/vty_index.cocci [deleted file]
tools/zprivs.cocci [deleted file]
vtysh/vtysh_config.c
vtysh/vtysh_user.c
zebra/connected.c
zebra/connected.h
zebra/debug.c
zebra/debug.h
zebra/if_netlink.c
zebra/if_netlink.h
zebra/interface.h
zebra/ioctl.h
zebra/ioctl_solaris.h
zebra/ipforward.h
zebra/irdp.h
zebra/irdp_main.c
zebra/irdp_packet.c
zebra/kernel_netlink.c
zebra/kernel_netlink.h
zebra/kernel_socket.c
zebra/kernel_socket.h
zebra/label_manager.h
zebra/main.c
zebra/redistribute.h
zebra/rib.h
zebra/router-id.h
zebra/rt.h
zebra/rt_netlink.c
zebra/rt_netlink.h
zebra/rt_socket.c
zebra/rtadv.h
zebra/rule_netlink.h
zebra/table_manager.h
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_errors.h
zebra/zebra_fpm_private.h
zebra/zebra_l2.h
zebra/zebra_memory.h
zebra/zebra_mlag.h
zebra/zebra_mpls.c
zebra/zebra_mpls.h
zebra/zebra_mpls_openbsd.c
zebra/zebra_mroute.h
zebra/zebra_netns_id.h
zebra/zebra_netns_notify.h
zebra/zebra_ns.h
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zebra_ptm.c
zebra/zebra_ptm.h
zebra/zebra_ptm_redistribute.h
zebra/zebra_pw.h
zebra/zebra_rib.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zebra_routemap.c
zebra/zebra_routemap.h
zebra/zebra_router.c
zebra/zebra_router.h
zebra/zebra_vrf.c
zebra/zebra_vrf.h
zebra/zebra_vty.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h
zebra/zebra_vxlan_private.h
zebra/zserv.c
zebra/zserv.h

index f2fc34583d3e482edd93929b2d7864e41fec56cd..d613e18dfc0ae1e810854a5396fccab3b5c08aa0 100644 (file)
@@ -5,3 +5,4 @@
 **/*.lo
 **/*.so
 **/.libs
+docker/alpine/pkgs
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
deleted file mode 100644 (file)
index 62d3c23..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-# HOW TO GET YOUR ISSUE ADDRESSED FASTER
-
-* When reporting a crash provide a backtrace
-* When pasting configs, logs, shell output, backtraces, and other large chunks
-  of text [use Markdown code blocks](https://github.github.com/gfm/#fenced-code-blocks)
-* Include the FRR version; if you built from Git, please provide the commit
-  hash
-* Write your issue in English
-
-### How to submit an issue
-Please use this text as a template and replace text in the sections or remove
-the entire section if it does not apply to your issue. For example in case of
-a question or feature request, just a description with some example is probably
-fine. Also remember to use GitHub Flavored Markdown properly, especially if
-posting output or code listings.
-
-### Things you may try first
-(put "x" in "[ ]" if you already tried following)
-* [ ] Did you check if this is a duplicate issue?
-* [ ] Did you test it on the latest FRRouting/frr master branch?
-
-**Related Issue:**
-[fill here if applicable]
-
-### Description
-[Description of the bug or feature]
-
-### Steps to Reproduce
-1. [First Step]
-2. [Second Step]
-3. [and so on...]
-
-**Expected behavior:**
-[What you expected to happen]
-
-**Actual behavior:**
-[What actually happened]
-
-### Components
-[bgpd, build, doc, isisd, ospfd, etc.]
-
-### Versions
-* OS: [name] [version]
-* Kernel: [Linux/BSD] [version]
-* FRR: [version]
-
-### Attachments
-[Attach if applicable. For example log-files, log-lines. etc. etc.]
-
-You're also welcomed to provide us with any other data you think may be useful.
-
-Thanks!
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644 (file)
index 0000000..1209f52
--- /dev/null
@@ -0,0 +1,43 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: triage
+assignees: ''
+
+---
+
+- When reporting a crash, provide a backtrace
+- When pasting configs, logs, shell output, backtraces, and other large chunks of text use Markdown code blocks
+- Include the FRR version; if you built from Git, please provide the commit hash
+- Write your issue in English
+
+---------------
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+(put "x" in "[ ]" if you already tried following)
+[ ] Did you check if this is a duplicate issue?
+[ ] Did you test it on the latest FRRouting/frr master branch?
+
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Versions**
+ - OS Kernel: [e.g. Linux, OpenBSD, etc] [version]
+ - FRR Version [version]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644 (file)
index 9f44f71..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-### Summary
-[fill here]
-
-### Related Issue
-[fill here if applicable]
-
-### Components
-[bgpd, build, doc, ripd, ospfd, eigrpd, isisd, etc. etc.]
diff --git a/.github/PULL_REQUEST_TEMPLATE/pr.md b/.github/PULL_REQUEST_TEMPLATE/pr.md
new file mode 100644 (file)
index 0000000..9f44f71
--- /dev/null
@@ -0,0 +1,8 @@
+### Summary
+[fill here]
+
+### Related Issue
+[fill here if applicable]
+
+### Components
+[bgpd, build, doc, ripd, ospfd, eigrpd, isisd, etc. etc.]
index 6e3c2a418169a502119ef95d7b94e9a70cfe5c17..2618029a4bfdc6d674785ea24cfd2d92bc03fffc 100644 (file)
@@ -175,13 +175,9 @@ EXTRA_DIST += \
        python/clidef.py \
        python/clippy/__init__.py \
        \
-       redhat/frr.init \
-       redhat/frr.service \
-       redhat/daemons \
        redhat/frr.logrotate \
        redhat/frr.pam \
        redhat/frr.spec \
-       redhat/README.rpm_build.md \
        \
        snapcraft/snapcraft.yaml \
        snapcraft/README.snap_build.md \
index 995c1b50ba9f26e94536182ad039936e286cd65c..a7725d5e4ed80f1c87f7384a405b40b913f6fd34 100644 (file)
--- a/README.md
+++ b/README.md
@@ -51,8 +51,9 @@ lists:
 | Users & Operators | frog@lists.frrouting.org     |
 | Announcements     | announce@lists.frrouting.org |
 
-For chat, we currently use [Slack](https://frrouting.slack.com). Please email
-the mailing list to request an invite as we do not issue automatic invites.
+For chat, we currently use [Slack](https://frrouting.slack.com). You can join
+by clicking the "Slack" link under the
+[Participate](https://frrouting.org/#participate) section of our website.
 
 
 Contributing
index 969b85f5240d52c6e14146a346dbed8ed7f6e184..0f56a427dd772990795911734ef1d891c6e13ea5 100644 (file)
@@ -9,13 +9,13 @@ license="GPL-2.0"
 depends="json-c c-ares ipsec-tools iproute2 python py-ipaddr bash"
 makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
     acct autoconf automake bash
-    binutils binutils-libs bison bsd-compat-headers build-base
+    binutils bison bsd-compat-headers build-base
     c-ares c-ares-dev ca-certificates cryptsetup-libs curl
     device-mapper-libs expat fakeroot flex fortify-headers gdbm
     git gmp isl json-c-dev kmod lddtree libacl libatomic libattr
     libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc
     libgomp libisoburn libisofs libltdl libressl libssh2
-    libstdc++ libtool libuuid linux-headers lzip lzo m4 make mkinitfs mpc1
+    libstdc++ libtool libuuid libyang-dev linux-headers lzip lzo m4 make mkinitfs mpc1
     mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base
     patch pax-utils pcre perl pkgconf python2 python2-dev readline
     readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs
@@ -23,7 +23,7 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
 checkdepends="pytest py-setuptools"
 install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall"
 subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
-source="$pkgname-$pkgver.tar.gz docker-start daemons"
+source="$pkgname-$pkgver.tar.gz"
 
 builddir="$srcdir"/$pkgname-$pkgver
 
@@ -60,8 +60,7 @@ package() {
        cd "$builddir"
        make DESTDIR="$pkgdir" install
 
-       install -Dm755 "$srcdir"/docker-start "$pkgdir"$_sbindir
-       install -Dm644 "$srcdir"/daemons "$pkgdir"$_sysconfdir
+       install -Dm644 "$builddir"/tools/etc/frr/daemons "$pkgdir"$_sysconfdir
        install -d "$pkgdir"/etc/init.d
        ln -s ${_sbindir}/frr "$pkgdir"/etc/init.d/frr
 }
diff --git a/alpine/docker-start b/alpine/docker-start
deleted file mode 100755 (executable)
index 43854ab..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-set -e
-
-##
-# For volume mounts...
-##
-chown -R frr:frr /etc/frr
-/etc/init.d/frr start
-exec sleep 10000d
index 79242f5b85c5910c8da1a259051ace4aadd1731f..0ff89abc495ab38fc1867c6619e1beb393d836d0 100644 (file)
@@ -1414,12 +1414,7 @@ static babel_interface_nfo *
 babel_interface_allocate (void)
 {
     babel_interface_nfo *babel_ifp;
-    babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
-    if(babel_ifp == NULL)
-        return NULL;
-
-    /* Here are set the default values for an interface. */
-    memset(babel_ifp, 0, sizeof(babel_interface_nfo));
+    babel_ifp = XCALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
     /* All flags are unset */
     babel_ifp->bucket_time = babel_now.tv_sec;
     babel_ifp->bucket = BUCKET_TOKENS_MAX;
index afd5d814a0bbd64a3ff3688e90df868662c6b908..e9645824f283d406de816b9d113388e50a7cabf9 100644 (file)
@@ -36,7 +36,9 @@ DEFINE_QOBJ_TYPE(bfd_session);
 /*
  * Prototypes
  */
-static struct bfd_session *bs_peer_waiting_find(struct bfd_peer_cfg *bpc);
+void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
+                struct sockaddr_any *local, bool mhop, const char *ifname,
+                const char *vrfname);
 
 static uint32_t ptm_bfd_gen_ID(void);
 static void ptm_bfd_echo_xmt_TO(struct bfd_session *bfd);
@@ -52,66 +54,47 @@ static void bs_down_handler(struct bfd_session *bs, int nstate);
 static void bs_init_handler(struct bfd_session *bs, int nstate);
 static void bs_up_handler(struct bfd_session *bs, int nstate);
 
+/* Zeroed array with the size of an IPv6 address. */
+struct in6_addr zero_addr;
 
 /*
  * Functions
  */
-static struct bfd_session *bs_peer_waiting_find(struct bfd_peer_cfg *bpc)
+void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
+                struct sockaddr_any *local, bool mhop, const char *ifname,
+                const char *vrfname)
 {
-       struct bfd_session_observer *bso;
-       struct bfd_session *bs = NULL;
-       bool is_shop, is_ipv4;
-
-       TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
-               bs = bso->bso_bs;
-
-               is_shop = !BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH);
-               is_ipv4 = !BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
-               /* Quick checks first. */
-               if (is_shop != (!bpc->bpc_mhop))
-                       continue;
-               if (is_ipv4 != bpc->bpc_ipv4)
-                       continue;
-
-               /*
-                * Slow lookup without hash because we don't have all
-                * information yet.
-                */
-               if (is_shop) {
-                       if (strcmp(bs->ifname, bpc->bpc_localif))
-                               continue;
-                       if (memcmp(&bs->shop.peer, &bpc->bpc_peer,
-                                  sizeof(bs->shop.peer)))
-                               continue;
-
-                       break;
-               }
-
-               if (strcmp(bs->vrfname, bpc->bpc_vrfname))
-                       continue;
-               if (memcmp(&bs->mhop.peer, &bpc->bpc_peer,
-                          sizeof(bs->mhop.peer)))
-                       continue;
-               if (memcmp(&bs->mhop.local, &bpc->bpc_local,
-                          sizeof(bs->mhop.local)))
-                       continue;
+       memset(key, 0, sizeof(*key));
 
+       switch (peer->sa_sin.sin_family) {
+       case AF_INET:
+               key->family = AF_INET;
+               memcpy(&key->peer, &peer->sa_sin.sin_addr,
+                      sizeof(peer->sa_sin.sin_addr));
+               memcpy(&key->local, &local->sa_sin.sin_addr,
+                      sizeof(local->sa_sin.sin_addr));
+               break;
+       case AF_INET6:
+               key->family = AF_INET6;
+               memcpy(&key->peer, &peer->sa_sin6.sin6_addr,
+                      sizeof(peer->sa_sin6.sin6_addr));
+               memcpy(&key->local, &local->sa_sin6.sin6_addr,
+                      sizeof(local->sa_sin6.sin6_addr));
                break;
        }
-       if (bso == NULL)
-               bs = NULL;
 
-       return bs;
+       key->mhop = mhop;
+       if (ifname && ifname[0])
+               strlcpy(key->ifname, ifname, sizeof(key->ifname));
+       if (vrfname && vrfname[0])
+               strlcpy(key->vrfname, vrfname, sizeof(key->vrfname));
 }
 
 struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
 {
        struct bfd_session *bs;
        struct peer_label *pl;
-       struct interface *ifp;
-       struct vrf *vrf;
-       struct bfd_mhop_key mhop;
-       struct bfd_shop_key shop;
+       struct bfd_key key;
 
        /* Try to find label first. */
        if (bpc->bpc_has_label) {
@@ -123,38 +106,10 @@ struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
        }
 
        /* Otherwise fallback to peer/local hash lookup. */
-       if (bpc->bpc_mhop) {
-               memset(&mhop, 0, sizeof(mhop));
-               mhop.peer = bpc->bpc_peer;
-               mhop.local = bpc->bpc_local;
-               if (bpc->bpc_has_vrfname) {
-                       vrf = vrf_lookup_by_name(bpc->bpc_vrfname);
-                       if (vrf == NULL)
-                               return NULL;
-
-                       mhop.vrfid = vrf->vrf_id;
-               }
+       gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop,
+                   bpc->bpc_localif, bpc->bpc_vrfname);
 
-               bs = bfd_mhop_lookup(mhop);
-       } else {
-               memset(&shop, 0, sizeof(shop));
-               shop.peer = bpc->bpc_peer;
-               if (bpc->bpc_has_localif) {
-                       ifp = if_lookup_by_name_all_vrf(bpc->bpc_localif);
-                       if (ifp == NULL)
-                               return NULL;
-
-                       shop.ifindex = ifp->ifindex;
-               }
-
-               bs = bfd_shop_lookup(shop);
-       }
-
-       if (bs != NULL)
-               return bs;
-
-       /* Search for entries that are incomplete. */
-       return bs_peer_waiting_find(bpc);
+       return bfd_key_lookup(key);
 }
 
 /*
@@ -165,7 +120,6 @@ struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
  */
 int bfd_session_enable(struct bfd_session *bs)
 {
-       struct sockaddr_in6 *sin6;
        struct interface *ifp = NULL;
        struct vrf *vrf = NULL;
        int psock;
@@ -174,8 +128,8 @@ int bfd_session_enable(struct bfd_session *bs)
         * If the interface or VRF doesn't exist, then we must register
         * the session but delay its start.
         */
-       if (bs->ifname[0] != 0) {
-               ifp = if_lookup_by_name_all_vrf(bs->ifname);
+       if (bs->key.ifname[0]) {
+               ifp = if_lookup_by_name_all_vrf(bs->key.ifname);
                if (ifp == NULL) {
                        log_error(
                                "session-enable: specified interface doesn't exists.");
@@ -184,15 +138,17 @@ int bfd_session_enable(struct bfd_session *bs)
 
                vrf = vrf_lookup_by_id(ifp->vrf_id);
                if (vrf == NULL) {
-                       log_error("session-enable: specified VRF doesn't exists.");
+                       log_error(
+                               "session-enable: specified VRF doesn't exists.");
                        return 0;
                }
        }
 
-       if (bs->vrfname[0] != 0) {
-               vrf = vrf_lookup_by_name(bs->vrfname);
+       if (bs->key.vrfname[0]) {
+               vrf = vrf_lookup_by_name(bs->key.vrfname);
                if (vrf == NULL) {
-                       log_error("session-enable: specified VRF doesn't exists.");
+                       log_error(
+                               "session-enable: specified VRF doesn't exists.");
                        return 0;
                }
        }
@@ -202,26 +158,15 @@ int bfd_session_enable(struct bfd_session *bs)
        if (bs->vrf == NULL)
                bs->vrf = vrf_lookup_by_id(VRF_DEFAULT);
 
-       if (bs->ifname[0] != 0 &&
-           BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
+       if (bs->key.ifname[0]
+           && BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
                bs->ifp = ifp;
 
-       /* Set the IPv6 scope id for link-local addresses. */
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) {
-               sin6 = &bs->mhop.peer.sa_sin6;
-               if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
-                       sin6->sin6_scope_id = bs->ifp != NULL
-                                                     ? bs->ifp->ifindex
-                                                     : IFINDEX_INTERNAL;
-
-               sin6 = &bs->mhop.local.sa_sin6;
-               if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
-                       sin6->sin6_scope_id = bs->ifp != NULL
-                                                     ? bs->ifp->ifindex
-                                                     : IFINDEX_INTERNAL;
-
-               bs->local_ip.sa_sin6 = *sin6;
-               bs->local_address.sa_sin6 = *sin6;
+       /* Sanity check: don't leak open sockets. */
+       if (bs->sock != -1) {
+               zlog_debug("session-enable: previous socket open");
+               close(bs->sock);
+               bs->sock = -1;
        }
 
        /*
@@ -232,11 +177,11 @@ int bfd_session_enable(struct bfd_session *bs)
        if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6) == 0) {
                psock = bp_peer_socket(bs);
                if (psock == -1)
-                       return -1;
+                       return 0;
        } else {
                psock = bp_peer_socketv6(bs);
                if (psock == -1)
-                       return -1;
+                       return 0;
        }
 
        /*
@@ -247,25 +192,6 @@ int bfd_session_enable(struct bfd_session *bs)
        bfd_recvtimer_update(bs);
        ptm_bfd_start_xmt_timer(bs, false);
 
-       /* Registrate session into data structures. */
-       bs->discrs.my_discr = ptm_bfd_gen_ID();
-       bfd_id_insert(bs);
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
-               if (vrf != NULL)
-                       bs->mhop.vrfid = vrf->vrf_id;
-               else
-                       bs->mhop.vrfid = VRF_DEFAULT;
-
-               bfd_mhop_insert(bs);
-       } else {
-               if (ifp != NULL)
-                       bs->shop.ifindex = ifp->ifindex;
-               else
-                       bs->shop.ifindex = IFINDEX_INTERNAL;
-
-               bfd_shop_insert(bs);
-       }
-
        return 0;
 }
 
@@ -288,13 +214,6 @@ void bfd_session_disable(struct bfd_session *bs)
        bfd_echo_recvtimer_delete(bs);
        bfd_xmttimer_delete(bs);
        bfd_echo_xmttimer_delete(bs);
-
-       /* Unregister session from hashes to avoid unwanted activation. */
-       bfd_id_delete(bs->discrs.my_discr);
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
-               bfd_mhop_delete(bs->mhop);
-       else
-               bfd_shop_delete(bs->shop);
 }
 
 static uint32_t ptm_bfd_gen_ID(void)
@@ -438,21 +357,20 @@ static struct bfd_session *bfd_find_disc(struct sockaddr_any *sa,
        if (bs == NULL)
                return NULL;
 
-       /* Remove unused fields. */
-       switch (sa->sa_sin.sin_family) {
+       switch (bs->key.family) {
        case AF_INET:
-               sa->sa_sin.sin_port = 0;
-               if (memcmp(sa, &bs->shop.peer, sizeof(sa->sa_sin)) == 0)
-                       return bs;
+               if (memcmp(&sa->sa_sin.sin_addr, &bs->key.peer,
+                          sizeof(sa->sa_sin.sin_addr)))
+                       return NULL;
                break;
        case AF_INET6:
-               sa->sa_sin6.sin6_port = 0;
-               if (memcmp(sa, &bs->shop.peer, sizeof(sa->sa_sin6)) == 0)
-                       return bs;
+               if (memcmp(&sa->sa_sin6.sin6_addr, &bs->key.peer,
+                          sizeof(sa->sa_sin6.sin6_addr)))
+                       return NULL;
                break;
        }
 
-       return NULL;
+       return bs;
 }
 
 struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
@@ -461,32 +379,30 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
                                      ifindex_t ifindex, vrf_id_t vrfid,
                                      bool is_mhop)
 {
-       struct bfd_session *l_bfd = NULL;
-       struct bfd_mhop_key mhop;
-       struct bfd_shop_key shop;
+       struct interface *ifp;
+       struct vrf *vrf;
+       struct bfd_key key;
 
        /* Find our session using the ID signaled by the remote end. */
        if (cp->discrs.remote_discr)
                return bfd_find_disc(peer, ntohl(cp->discrs.remote_discr));
 
        /* Search for session without using discriminator. */
-       if (is_mhop) {
-               memset(&mhop, 0, sizeof(mhop));
-               mhop.peer = *peer;
-               mhop.local = *local;
-               mhop.vrfid = vrfid;
-
-               l_bfd = bfd_mhop_lookup(mhop);
-       } else {
-               memset(&shop, 0, sizeof(shop));
-               shop.peer = *peer;
-               shop.ifindex = ifindex;
+       ifp = if_lookup_by_index(ifindex, vrfid);
+       if (vrfid == VRF_DEFAULT) {
+               /*
+                * Don't use the default vrf, otherwise we won't find
+                * sessions that doesn't specify it.
+                */
+               vrf = NULL;
+       } else
+               vrf = vrf_lookup_by_id(vrfid);
 
-               l_bfd = bfd_shop_lookup(shop);
-       }
+       gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL,
+                   vrf ? vrf->name : NULL);
 
        /* XXX maybe remoteDiscr should be checked for remoteHeard cases. */
-       return l_bfd;
+       return bfd_key_lookup(key);
 }
 
 int bfd_xmt_cb(struct thread *t)
@@ -551,8 +467,6 @@ static struct bfd_session *bfd_session_new(void)
        struct bfd_session *bs;
 
        bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(*bs));
-       if (bs == NULL)
-               return NULL;
 
        QOBJ_REG(bs, bfd_session);
 
@@ -703,6 +617,9 @@ static void bfd_session_free(struct bfd_session *bs)
 
        bfd_session_disable(bs);
 
+       bfd_key_delete(bs->key);
+       bfd_id_delete(bs->discrs.my_discr);
+
        /* Remove observer if any. */
        TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
                if (bso->bso_bs != bs)
@@ -745,29 +662,47 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
         * start. See `bfd_session_enable` for more information.
         */
        if (bpc->bpc_has_localif)
-               strlcpy(bfd->ifname, bpc->bpc_localif, sizeof(bfd->ifname));
+               strlcpy(bfd->key.ifname, bpc->bpc_localif,
+                       sizeof(bfd->key.ifname));
 
        if (bpc->bpc_has_vrfname)
-               strlcpy(bfd->vrfname, bpc->bpc_vrfname, sizeof(bfd->vrfname));
-
-       /* Add observer if we have moving parts. */
-       if (bfd->ifname[0] || bfd->vrfname[0])
-               bs_observer_add(bfd);
+               strlcpy(bfd->key.vrfname, bpc->bpc_vrfname,
+                       sizeof(bfd->key.vrfname));
 
        /* Copy remaining data. */
        if (bpc->bpc_ipv4 == false)
                BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6);
 
-       if (bpc->bpc_mhop) {
-               BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_MH);
-               bfd->mhop.peer = bpc->bpc_peer;
-               bfd->mhop.local = bpc->bpc_local;
-       } else {
-               bfd->shop.peer = bpc->bpc_peer;
+       bfd->key.family = (bpc->bpc_ipv4) ? AF_INET : AF_INET6;
+       switch (bfd->key.family) {
+       case AF_INET:
+               memcpy(&bfd->key.peer, &bpc->bpc_peer.sa_sin.sin_addr,
+                      sizeof(bpc->bpc_peer.sa_sin.sin_addr));
+               memcpy(&bfd->key.local, &bpc->bpc_local.sa_sin.sin_addr,
+                      sizeof(bpc->bpc_local.sa_sin.sin_addr));
+               break;
+
+       case AF_INET6:
+               memcpy(&bfd->key.peer, &bpc->bpc_peer.sa_sin6.sin6_addr,
+                      sizeof(bpc->bpc_peer.sa_sin6.sin6_addr));
+               memcpy(&bfd->key.local, &bpc->bpc_local.sa_sin6.sin6_addr,
+                      sizeof(bpc->bpc_local.sa_sin6.sin6_addr));
+               break;
+
+       default:
+               assert(1);
+               break;
        }
 
-       bfd->local_ip = bpc->bpc_local;
-       bfd->local_address = bpc->bpc_local;
+       if (bpc->bpc_mhop)
+               BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_MH);
+
+       bfd->key.mhop = bpc->bpc_mhop;
+
+       /* Registrate session into data structures. */
+       bfd_key_insert(bfd);
+       bfd->discrs.my_discr = ptm_bfd_gen_ID();
+       bfd_id_insert(bfd);
 
        /* Try to enable session and schedule for packet receive/send. */
        if (bfd_session_enable(bfd) == -1) {
@@ -776,6 +711,10 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
                return NULL;
        }
 
+       /* Add observer if we have moving parts. */
+       if (bfd->key.ifname[0] || bfd->key.vrfname[0] || bfd->sock == -1)
+               bs_observer_add(bfd);
+
        /* Apply other configurations. */
        _bfd_session_update(bfd, bpc);
 
@@ -1221,34 +1160,28 @@ void integer2timestr(uint64_t time, char *buf, size_t buflen)
        snprintf(buf, buflen, "%u second(s)", second);
 }
 
-const char *bs_to_string(struct bfd_session *bs)
+const char *bs_to_string(const struct bfd_session *bs)
 {
        static char buf[256];
+       char addr_buf[INET6_ADDRSTRLEN];
        int pos;
        bool is_mhop = BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH);
 
        pos = snprintf(buf, sizeof(buf), "mhop:%s", is_mhop ? "yes" : "no");
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
-               pos += snprintf(buf + pos, sizeof(buf) - pos,
-                               " peer:%s local:%s", satostr(&bs->mhop.peer),
-                               satostr(&bs->mhop.local));
-
-               if (bs->mhop.vrfid != VRF_DEFAULT)
-                       snprintf(buf + pos, sizeof(buf) - pos, " vrf:%u",
-                                bs->mhop.vrfid);
-       } else {
-               pos += snprintf(buf + pos, sizeof(buf) - pos, " peer:%s",
-                               satostr(&bs->shop.peer));
-
-               if (bs->local_address.sa_sin.sin_family)
-                       pos += snprintf(buf + pos, sizeof(buf) - pos,
-                                       " local:%s",
-                                       satostr(&bs->local_address));
-
-               if (bs->shop.ifindex)
-                       snprintf(buf + pos, sizeof(buf) - pos, " ifindex:%u",
-                                bs->shop.ifindex);
-       }
+       pos += snprintf(buf + pos, sizeof(buf) - pos, " peer:%s",
+                       inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
+                                 sizeof(addr_buf)));
+       pos += snprintf(buf + pos, sizeof(buf) - pos, " local:%s",
+                       inet_ntop(bs->key.family, &bs->key.local, addr_buf,
+                                 sizeof(addr_buf)));
+       if (bs->key.vrfname[0])
+               pos += snprintf(buf + pos, sizeof(buf) - pos, " vrf:%s",
+                               bs->key.vrfname);
+       if (bs->key.ifname[0])
+               pos += snprintf(buf + pos, sizeof(buf) - pos, " ifname:%s",
+                               bs->key.ifname);
+
+       (void)pos;
 
        return buf;
 }
@@ -1257,16 +1190,25 @@ int bs_observer_add(struct bfd_session *bs)
 {
        struct bfd_session_observer *bso;
 
-       bso = XMALLOC(MTYPE_BFDD_SESSION_OBSERVER, sizeof(*bso));
+       bso = XCALLOC(MTYPE_BFDD_SESSION_OBSERVER, sizeof(*bso));
+       bso->bso_isaddress = false;
        bso->bso_bs = bs;
        bso->bso_isinterface = !BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH);
        if (bso->bso_isinterface)
-               strlcpy(bso->bso_entryname, bs->ifname,
+               strlcpy(bso->bso_entryname, bs->key.ifname,
                        sizeof(bso->bso_entryname));
        else
-               strlcpy(bso->bso_entryname, bs->vrfname,
+               strlcpy(bso->bso_entryname, bs->key.vrfname,
                        sizeof(bso->bso_entryname));
 
+       /* Handle socket binding failures caused by missing local addresses. */
+       if (bs->sock == -1) {
+               bso->bso_isaddress = true;
+               bso->bso_addr.family = bs->key.family;
+               memcpy(&bso->bso_addr.u.prefix, &bs->key.local,
+                      sizeof(bs->key.local));
+       }
+
        TAILQ_INSERT_TAIL(&bglobal.bg_obslist, bso, bso_entry);
 
        return 0;
@@ -1278,21 +1220,59 @@ void bs_observer_del(struct bfd_session_observer *bso)
        XFREE(MTYPE_BFDD_SESSION_OBSERVER, bso);
 }
 
+void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc)
+{
+       memset(bpc, 0, sizeof(*bpc));
+
+       bpc->bpc_ipv4 = (bs->key.family == AF_INET);
+       bpc->bpc_mhop = bs->key.mhop;
+
+       switch (bs->key.family) {
+       case AF_INET:
+               bpc->bpc_peer.sa_sin.sin_family = AF_INET;
+               memcpy(&bpc->bpc_peer.sa_sin.sin_addr, &bs->key.peer,
+                      sizeof(bpc->bpc_peer.sa_sin.sin_addr));
+
+               if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local))) {
+                       bpc->bpc_local.sa_sin.sin_family = AF_INET6;
+                       memcpy(&bpc->bpc_local.sa_sin.sin_addr, &bs->key.local,
+                              sizeof(bpc->bpc_local.sa_sin.sin_addr));
+               }
+               break;
+
+       case AF_INET6:
+               bpc->bpc_peer.sa_sin.sin_family = AF_INET6;
+               memcpy(&bpc->bpc_peer.sa_sin6.sin6_addr, &bs->key.peer,
+                      sizeof(bpc->bpc_peer.sa_sin6.sin6_addr));
+
+               bpc->bpc_local.sa_sin6.sin6_family = AF_INET6;
+               memcpy(&bpc->bpc_local.sa_sin6.sin6_addr, &bs->key.local,
+                      sizeof(bpc->bpc_local.sa_sin6.sin6_addr));
+               break;
+       }
+
+       if (bs->key.ifname[0]) {
+               bpc->bpc_has_localif = true;
+               strlcpy(bpc->bpc_localif, bs->key.ifname,
+                       sizeof(bpc->bpc_localif));
+       }
+
+       if (bs->key.vrfname[0]) {
+               bpc->bpc_has_vrfname = true;
+               strlcpy(bpc->bpc_vrfname, bs->key.vrfname,
+                       sizeof(bpc->bpc_vrfname));
+       }
+}
+
 
 /*
  * BFD hash data structures to find sessions.
  */
 static struct hash *bfd_id_hash;
-static struct hash *bfd_shop_hash;
-static struct hash *bfd_mhop_hash;
+static struct hash *bfd_key_hash;
 
 static unsigned int bfd_id_hash_do(void *p);
-static unsigned int bfd_shop_hash_do(void *p);
-static unsigned int bfd_mhop_hash_do(void *p);
-
-static void _shop_key(struct bfd_session *bs, const struct bfd_shop_key *shop);
-static void _shop_key2(struct bfd_session *bs, const struct bfd_shop_key *shop);
-static void _mhop_key(struct bfd_session *bs, const struct bfd_mhop_key *mhop);
+static unsigned int bfd_key_hash_do(void *p);
 
 static void _bfd_free(struct hash_bucket *hb,
                      void *arg __attribute__((__unused__)));
@@ -1313,73 +1293,20 @@ static bool bfd_id_hash_cmp(const void *n1, const void *n2)
 }
 
 /* BFD hash for single hop. */
-static unsigned int bfd_shop_hash_do(void *p)
-{
-       struct bfd_session *bs = p;
-
-       return jhash(&bs->shop, sizeof(bs->shop), 0);
-}
-
-static bool bfd_shop_hash_cmp(const void *n1, const void *n2)
-{
-       const struct bfd_session *bs1 = n1, *bs2 = n2;
-
-       return memcmp(&bs1->shop, &bs2->shop, sizeof(bs1->shop)) == 0;
-}
-
-/* BFD hash for multi hop. */
-static unsigned int bfd_mhop_hash_do(void *p)
+static unsigned int bfd_key_hash_do(void *p)
 {
        struct bfd_session *bs = p;
 
-       return jhash(&bs->mhop, sizeof(bs->mhop), 0);
+       return jhash(&bs->key, sizeof(bs->key), 0);
 }
 
-static bool bfd_mhop_hash_cmp(const void *n1, const void *n2)
+static bool bfd_key_hash_cmp(const void *n1, const void *n2)
 {
        const struct bfd_session *bs1 = n1, *bs2 = n2;
 
-       return memcmp(&bs1->mhop, &bs2->mhop, sizeof(bs1->mhop)) == 0;
+       return memcmp(&bs1->key, &bs2->key, sizeof(bs1->key)) == 0;
 }
 
-/* Helper functions */
-static void _shop_key(struct bfd_session *bs, const struct bfd_shop_key *shop)
-{
-       bs->shop = *shop;
-
-       /* Remove unused fields. */
-       switch (bs->shop.peer.sa_sin.sin_family) {
-       case AF_INET:
-               bs->shop.peer.sa_sin.sin_port = 0;
-               break;
-       case AF_INET6:
-               bs->shop.peer.sa_sin6.sin6_port = 0;
-               break;
-       }
-}
-
-static void _shop_key2(struct bfd_session *bs, const struct bfd_shop_key *shop)
-{
-       _shop_key(bs, shop);
-       bs->shop.ifindex = IFINDEX_INTERNAL;
-}
-
-static void _mhop_key(struct bfd_session *bs, const struct bfd_mhop_key *mhop)
-{
-       bs->mhop = *mhop;
-
-       /* Remove unused fields. */
-       switch (bs->mhop.peer.sa_sin.sin_family) {
-       case AF_INET:
-               bs->mhop.peer.sa_sin.sin_port = 0;
-               bs->mhop.local.sa_sin.sin_port = 0;
-               break;
-       case AF_INET6:
-               bs->mhop.peer.sa_sin6.sin6_port = 0;
-               bs->mhop.local.sa_sin6.sin6_port = 0;
-               break;
-       }
-}
 
 /*
  * Hash public interface / exported functions.
@@ -1395,32 +1322,33 @@ struct bfd_session *bfd_id_lookup(uint32_t id)
        return hash_lookup(bfd_id_hash, &bs);
 }
 
-struct bfd_session *bfd_shop_lookup(struct bfd_shop_key shop)
+struct bfd_session *bfd_key_lookup(struct bfd_key key)
 {
        struct bfd_session bs, *bsp;
 
-       _shop_key(&bs, &shop);
+       bs.key = key;
+       bsp = hash_lookup(bfd_key_hash, &bs);
 
-       bsp = hash_lookup(bfd_shop_hash, &bs);
-       if (bsp == NULL && bs.shop.ifindex != 0) {
-               /*
-                * Since the local interface spec is optional, try
-                * searching the key without it as well.
-                */
-               _shop_key2(&bs, &shop);
-               bsp = hash_lookup(bfd_shop_hash, &bs);
+       /* Handle cases where local-address is optional. */
+       if (bsp == NULL && bs.key.family == AF_INET) {
+               memset(&bs.key.local, 0, sizeof(bs.key.local));
+               bsp = hash_lookup(bfd_key_hash, &bs);
        }
 
-       return bsp;
-}
-
-struct bfd_session *bfd_mhop_lookup(struct bfd_mhop_key mhop)
-{
-       struct bfd_session bs;
+       /* Handle cases where ifname is optional. */
+       bs.key = key;
+       if (bsp == NULL && bs.key.ifname[0]) {
+               memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
+               bsp = hash_lookup(bfd_key_hash, &bs);
 
-       _mhop_key(&bs, &mhop);
+               /* Handle cases where local-address and ifname are optional. */
+               if (bsp == NULL && bs.key.family == AF_INET) {
+                       memset(&bs.key.local, 0, sizeof(bs.key.local));
+                       bsp = hash_lookup(bfd_key_hash, &bs);
+               }
+       }
 
-       return hash_lookup(bfd_mhop_hash, &bs);
+       return bsp;
 }
 
 /*
@@ -1442,31 +1370,18 @@ struct bfd_session *bfd_id_delete(uint32_t id)
        return hash_release(bfd_id_hash, &bs);
 }
 
-struct bfd_session *bfd_shop_delete(struct bfd_shop_key shop)
+struct bfd_session *bfd_key_delete(struct bfd_key key)
 {
        struct bfd_session bs, *bsp;
 
-       _shop_key(&bs, &shop);
-       bsp = hash_release(bfd_shop_hash, &bs);
-       if (bsp == NULL && shop.ifindex != 0) {
-               /*
-                * Since the local interface spec is optional, try
-                * searching the key without it as well.
-                */
-               _shop_key2(&bs, &shop);
-               bsp = hash_release(bfd_shop_hash, &bs);
+       bs.key = key;
+       bsp = hash_lookup(bfd_key_hash, &bs);
+       if (bsp == NULL && key.ifname[0]) {
+               memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
+               bsp = hash_lookup(bfd_key_hash, &bs);
        }
 
-       return bsp;
-}
-
-struct bfd_session *bfd_mhop_delete(struct bfd_mhop_key mhop)
-{
-       struct bfd_session bs;
-
-       _mhop_key(&bs, &mhop);
-
-       return hash_release(bfd_mhop_hash, &bs);
+       return hash_release(bfd_key_hash, bsp);
 }
 
 /* Iteration functions. */
@@ -1475,14 +1390,9 @@ void bfd_id_iterate(hash_iter_func hif, void *arg)
        hash_iterate(bfd_id_hash, hif, arg);
 }
 
-void bfd_shop_iterate(hash_iter_func hif, void *arg)
-{
-       hash_iterate(bfd_shop_hash, hif, arg);
-}
-
-void bfd_mhop_iterate(hash_iter_func hif, void *arg)
+void bfd_key_iterate(hash_iter_func hif, void *arg)
 {
-       hash_iterate(bfd_mhop_hash, hif, arg);
+       hash_iterate(bfd_key_hash, hif, arg);
 }
 
 /*
@@ -1496,24 +1406,17 @@ bool bfd_id_insert(struct bfd_session *bs)
        return (hash_get(bfd_id_hash, bs, hash_alloc_intern) == bs);
 }
 
-bool bfd_shop_insert(struct bfd_session *bs)
-{
-       return (hash_get(bfd_shop_hash, bs, hash_alloc_intern) == bs);
-}
-
-bool bfd_mhop_insert(struct bfd_session *bs)
+bool bfd_key_insert(struct bfd_session *bs)
 {
-       return (hash_get(bfd_mhop_hash, bs, hash_alloc_intern) == bs);
+       return (hash_get(bfd_key_hash, bs, hash_alloc_intern) == bs);
 }
 
 void bfd_initialize(void)
 {
        bfd_id_hash = hash_create(bfd_id_hash_do, bfd_id_hash_cmp,
-                                 "BFD discriminator hash");
-       bfd_shop_hash = hash_create(bfd_shop_hash_do, bfd_shop_hash_cmp,
-                                   "BFD single hop hash");
-       bfd_mhop_hash = hash_create(bfd_mhop_hash_do, bfd_mhop_hash_cmp,
-                                   "BFD multihop hop hash");
+                                 "BFD session discriminator hash");
+       bfd_key_hash = hash_create(bfd_key_hash_do, bfd_key_hash_cmp,
+                                  "BFD session hash");
 }
 
 static void _bfd_free(struct hash_bucket *hb,
@@ -1534,11 +1437,9 @@ void bfd_shutdown(void)
         * assert() here to make sure it really happened.
         */
        bfd_id_iterate(_bfd_free, NULL);
-       assert(bfd_shop_hash->count == 0);
-       assert(bfd_mhop_hash->count == 0);
+       assert(bfd_key_hash->count == 0);
 
        /* Now free the hashes themselves. */
        hash_free(bfd_id_hash);
-       hash_free(bfd_shop_hash);
-       hash_free(bfd_mhop_hash);
+       hash_free(bfd_key_hash);
 }
index 7451ca82a387e4753591c3ec070c039fa696088c..a69ff9a1a7b9a33b7756d6ef6305a125904220d2 100644 (file)
@@ -173,15 +173,13 @@ enum bfd_session_flags {
 #define BFD_CHECK_FLAG(field, flag) (field & flag)
 
 /* BFD session hash keys */
-struct bfd_shop_key {
-       struct sockaddr_any peer;
-       ifindex_t ifindex;
-};
-
-struct bfd_mhop_key {
-       struct sockaddr_any peer;
-       struct sockaddr_any local;
-       vrf_id_t vrfid;
+struct bfd_key {
+       uint16_t family;
+       uint8_t mhop;
+       struct in6_addr peer;
+       struct in6_addr local;
+       char ifname[MAXNAMELEN];
+       char vrfname[MAXNAMELEN];
 };
 
 struct bfd_session_stats {
@@ -227,19 +225,14 @@ struct bfd_session {
        uint8_t polling;
 
        /* This and the localDiscr are the keys to state info */
+       struct bfd_key key;
        struct peer_label *pl;
-       union {
-               struct bfd_shop_key shop;
-               struct bfd_mhop_key mhop;
-       };
-       int sock;
 
        struct sockaddr_any local_address;
-       struct sockaddr_any local_ip;
        struct interface *ifp;
        struct vrf *vrf;
-       char ifname[MAXNAMELEN];
-       char vrfname[MAXNAMELEN];
+
+       int sock;
 
        /* BFD session flags */
        enum bfd_session_flags flags;
@@ -281,7 +274,11 @@ struct bfd_state_str_list {
 struct bfd_session_observer {
        struct bfd_session *bso_bs;
        bool bso_isinterface;
-       char bso_entryname[MAXNAMELEN];
+       bool bso_isaddress;
+       union {
+               char bso_entryname[MAXNAMELEN];
+               struct prefix bso_addr;
+       };
 
        TAILQ_ENTRY(bfd_session_observer) bso_entry;
 };
@@ -531,38 +528,28 @@ const char *satostr(struct sockaddr_any *sa);
 const char *diag2str(uint8_t diag);
 int strtosa(const char *addr, struct sockaddr_any *sa);
 void integer2timestr(uint64_t time, char *buf, size_t buflen);
-const char *bs_to_string(struct bfd_session *bs);
+const char *bs_to_string(const struct bfd_session *bs);
 
 int bs_observer_add(struct bfd_session *bs);
 void bs_observer_del(struct bfd_session_observer *bso);
 
+void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc);
+
 /* BFD hash data structures interface */
 void bfd_initialize(void);
 void bfd_shutdown(void);
 struct bfd_session *bfd_id_lookup(uint32_t id);
-struct bfd_session *bfd_shop_lookup(struct bfd_shop_key shop);
-struct bfd_session *bfd_mhop_lookup(struct bfd_mhop_key mhop);
-struct bfd_vrf *bfd_vrf_lookup(int vrf_id);
-struct bfd_iface *bfd_iface_lookup(const char *ifname);
+struct bfd_session *bfd_key_lookup(struct bfd_key key);
 
 struct bfd_session *bfd_id_delete(uint32_t id);
-struct bfd_session *bfd_shop_delete(struct bfd_shop_key shop);
-struct bfd_session *bfd_mhop_delete(struct bfd_mhop_key mhop);
-struct bfd_vrf *bfd_vrf_delete(int vrf_id);
-struct bfd_iface *bfd_iface_delete(const char *ifname);
+struct bfd_session *bfd_key_delete(struct bfd_key key);
 
 bool bfd_id_insert(struct bfd_session *bs);
-bool bfd_shop_insert(struct bfd_session *bs);
-bool bfd_mhop_insert(struct bfd_session *bs);
-bool bfd_vrf_insert(struct bfd_vrf *vrf);
-bool bfd_iface_insert(struct bfd_iface *iface);
+bool bfd_key_insert(struct bfd_session *bs);
 
 typedef void (*hash_iter_func)(struct hash_bucket *hb, void *arg);
 void bfd_id_iterate(hash_iter_func hif, void *arg);
-void bfd_shop_iterate(hash_iter_func hif, void *arg);
-void bfd_mhop_iterate(hash_iter_func hif, void *arg);
-void bfd_vrf_iterate(hash_iter_func hif, void *arg);
-void bfd_iface_iterate(hash_iter_func hif, void *arg);
+void bfd_key_iterate(hash_iter_func hif, void *arg);
 
 /* Export callback functions for `event.c`. */
 extern struct thread_master *master;
@@ -572,6 +559,8 @@ int bfd_echo_recvtimer_cb(struct thread *t);
 int bfd_xmt_cb(struct thread *t);
 int bfd_echo_xmt_cb(struct thread *t);
 
+extern struct in6_addr zero_addr;
+
 
 /*
  * bfdd_vty.c
index 45c5f5dbdc415a1143d900ad5f5a15d0dd94e364..93677ec85aceeb7709385a07c652682b843d73aa 100644 (file)
@@ -79,7 +79,10 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
        if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) {
                memset(&sin6, 0, sizeof(sin6));
                sin6.sin6_family = AF_INET6;
-               sin6.sin6_addr = bs->shop.peer.sa_sin6.sin6_addr;
+               memcpy(&sin6.sin6_addr, &bs->key.peer, sizeof(sin6.sin6_addr));
+               if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+                       sin6.sin6_scope_id = bs->ifp->ifindex;
+
                sin6.sin6_port =
                        (port) ? *port
                               : (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
@@ -92,7 +95,7 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
        } else {
                memset(&sin, 0, sizeof(sin));
                sin.sin_family = AF_INET;
-               sin.sin_addr = bs->shop.peer.sa_sin.sin_addr;
+               memcpy(&sin.sin_addr, &bs->key.peer, sizeof(sin.sin_addr));
                sin.sin_port =
                        (port) ? *port
                               : (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
@@ -120,7 +123,7 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
 
 void ptm_bfd_echo_snd(struct bfd_session *bfd)
 {
-       struct sockaddr_any *sa;
+       struct sockaddr *sa;
        socklen_t salen;
        int sd;
        struct bfd_echo_pkt bep;
@@ -135,31 +138,36 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
        bep.len = BFD_ECHO_PKT_LEN;
        bep.my_discr = htonl(bfd->discrs.my_discr);
 
-       sa = BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_MH) ? &bfd->mhop.peer
-                                                         : &bfd->shop.peer;
        if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6)) {
                sd = bglobal.bg_echov6;
-               sin6 = sa->sa_sin6;
+               memset(&sin6, 0, sizeof(sin6));
+               sin6.sin6_family = AF_INET6;
+               memcpy(&sin6.sin6_addr, &bfd->key.peer, sizeof(sin6.sin6_addr));
+               if (bfd->ifp && IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+                       sin6.sin6_scope_id = bfd->ifp->ifindex;
+
                sin6.sin6_port = htons(BFD_DEF_ECHO_PORT);
 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
                sin6.sin6_len = sizeof(sin6);
 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
 
-               sa = (struct sockaddr_any *)&sin6;
+               sa = (struct sockaddr *)&sin6;
                salen = sizeof(sin6);
        } else {
                sd = bglobal.bg_echo;
-               sin = sa->sa_sin;
+               memset(&sin6, 0, sizeof(sin6));
+               sin.sin_family = AF_INET;
+               memcpy(&sin.sin_addr, &bfd->key.peer, sizeof(sin.sin_addr));
                sin.sin_port = htons(BFD_DEF_ECHO_PORT);
 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
                sin.sin_len = sizeof(sin);
 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
 
-               sa = (struct sockaddr_any *)&sin;
+               sa = (struct sockaddr *)&sin;
                salen = sizeof(sin);
        }
-       if (bp_udp_send(sd, BFD_TTL_VAL, (uint8_t *)&bep, sizeof(bep),
-                       (struct sockaddr *)sa, salen)
+       if (bp_udp_send(sd, BFD_TTL_VAL, (uint8_t *)&bep, sizeof(bep), sa,
+                       salen)
            == -1)
                return;
 
@@ -544,7 +552,7 @@ int bfd_recv_cb(struct thread *t)
        }
 
        /* Validate packet TTL. */
-       if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
+       if ((!is_mhop) && (ttl != BFD_TTL_VAL)) {
                cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
                         "invalid TTL: %d expected %d", ttl, BFD_TTL_VAL);
                return 0;
@@ -602,8 +610,8 @@ int bfd_recv_cb(struct thread *t)
                                 bfd->mh_ttl, BFD_TTL_VAL);
                        return 0;
                }
-       } else if (bfd->local_ip.sa_sin.sin_family == AF_UNSPEC) {
-               bfd->local_ip = local;
+       } else if (bfd->local_address.sa_sin.sin_family == AF_UNSPEC) {
+               bfd->local_address = local;
        }
 
        /*
@@ -917,25 +925,26 @@ int bp_peer_socket(const struct bfd_session *bs)
                return -1;
        }
 
-       if (bs->shop.ifindex != IFINDEX_INTERNAL) {
-               if (bp_bind_dev(sd, bs->ifp->name) != 0) {
+       if (bs->key.ifname[0]) {
+               if (bp_bind_dev(sd, bs->key.ifname) != 0) {
                        close(sd);
                        return -1;
                }
-       } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) &&
-                  bs->mhop.vrfid != VRF_DEFAULT) {
-               if (bp_bind_dev(sd, bs->vrf->name) != 0) {
+       } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+                  && bs->key.vrfname[0]) {
+               if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
                        close(sd);
                        return -1;
                }
        }
 
        /* Find an available source port in the proper range */
-       sin = bs->local_ip.sa_sin;
+       memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
        sin.sin_len = sizeof(sin);
 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+       memcpy(&sin.sin_addr, &bs->key.local, sizeof(sin.sin_addr));
        if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
                sin.sin_addr.s_addr = INADDR_ANY;
 
@@ -987,20 +996,23 @@ int bp_peer_socketv6(const struct bfd_session *bs)
        }
 
        /* Find an available source port in the proper range */
-       sin6 = bs->local_ip.sa_sin6;
+       memset(&sin6, 0, sizeof(sin6));
        sin6.sin6_family = AF_INET6;
 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
        sin6.sin6_len = sizeof(sin6);
 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+       memcpy(&sin6.sin6_addr, &bs->key.local, sizeof(sin6.sin6_addr));
+       if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+               sin6.sin6_scope_id = bs->ifp->ifindex;
 
-       if (bs->shop.ifindex != IFINDEX_INTERNAL) {
-               if (bp_bind_dev(sd, bs->ifp->name) != 0) {
+       if (bs->key.ifname[0]) {
+               if (bp_bind_dev(sd, bs->key.ifname) != 0) {
                        close(sd);
                        return -1;
                }
-       } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) &&
-                  bs->mhop.vrfid != VRF_DEFAULT) {
-               if (bp_bind_dev(sd, bs->vrf->name) != 0) {
+       } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+                  && bs->key.vrfname[0]) {
+               if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
                        close(sd);
                        return -1;
                }
index 0041f9cc2e968ea4b1df4fb4a1d41f4c74e2c814..c13949207642fe1e81673269291b48a957afda2f 100644 (file)
@@ -79,7 +79,6 @@ _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
                    const char *local_str, const char *ifname,
                    const char *vrfname);
 
-
 /*
  * Commands definition.
  */
@@ -369,22 +368,25 @@ DEFPY(bfd_no_peer, bfd_no_peer_cmd,
  */
 static void _display_peer_header(struct vty *vty, struct bfd_session *bs)
 {
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
-               vty_out(vty, "\tpeer %s", satostr(&bs->mhop.peer));
+       char addr_buf[INET6_ADDRSTRLEN];
+
+       vty_out(vty, "\tpeer %s",
+               inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
+                         sizeof(addr_buf)));
+
+       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
                vty_out(vty, " multihop");
-               vty_out(vty, " local-address %s", satostr(&bs->mhop.local));
-               if (bs->vrfname[0])
-                       vty_out(vty, " vrf %s", bs->vrfname);
-               vty_out(vty, "\n");
-       } else {
-               vty_out(vty, "\tpeer %s", satostr(&bs->shop.peer));
-               if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
-                       vty_out(vty, " local-address %s",
-                               satostr(&bs->local_address));
-               if (bs->ifname[0])
-                       vty_out(vty, " interface %s", bs->ifname);
-               vty_out(vty, "\n");
-       }
+
+       if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+               vty_out(vty, " local-address %s",
+                       inet_ntop(bs->key.family, &bs->key.local, addr_buf,
+                                 sizeof(addr_buf)));
+
+       if (bs->key.vrfname[0])
+               vty_out(vty, " vrf %s", bs->key.vrfname);
+       if (bs->key.ifname[0])
+               vty_out(vty, " interface %s", bs->key.ifname);
+       vty_out(vty, "\n");
 
        if (bs->pl)
                vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label);
@@ -453,22 +455,25 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
 static struct json_object *_peer_json_header(struct bfd_session *bs)
 {
        struct json_object *jo = json_object_new_object();
+       char addr_buf[INET6_ADDRSTRLEN];
 
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
+       if (bs->key.mhop)
                json_object_boolean_true_add(jo, "multihop");
-               json_object_string_add(jo, "peer", satostr(&bs->mhop.peer));
-               json_object_string_add(jo, "local", satostr(&bs->mhop.local));
-               if (bs->vrfname[0])
-                       json_object_string_add(jo, "vrf", bs->vrfname);
-       } else {
+       else
                json_object_boolean_false_add(jo, "multihop");
-               json_object_string_add(jo, "peer", satostr(&bs->shop.peer));
-               if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
-                       json_object_string_add(jo, "local",
-                                              satostr(&bs->local_address));
-               if (bs->ifname[0])
-                       json_object_string_add(jo, "interface", bs->ifname);
-       }
+
+       json_object_string_add(jo, "peer",
+                              inet_ntop(bs->key.family, &bs->key.peer,
+                                        addr_buf, sizeof(addr_buf)));
+       if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+               json_object_string_add(jo, "local",
+                                      inet_ntop(bs->key.family, &bs->key.local,
+                                                addr_buf, sizeof(addr_buf)));
+
+       if (bs->key.vrfname[0])
+               json_object_string_add(jo, "vrf", bs->key.vrfname);
+       if (bs->key.ifname[0])
+               json_object_string_add(jo, "interface", bs->key.ifname);
 
        if (bs->pl)
                json_object_string_add(jo, "label", bs->pl->pl_label);
@@ -564,7 +569,7 @@ static void _display_all_peers(struct vty *vty, bool use_json)
 {
        struct json_object *jo;
 
-       if (use_json == false) {
+       if (!use_json) {
                vty_out(vty, "BFD Peers:\n");
                bfd_id_iterate(_display_peer_iter, vty);
                return;
@@ -647,7 +652,7 @@ static void _display_peers_counter(struct vty *vty, bool use_json)
 {
        struct json_object *jo;
 
-       if (use_json == false) {
+       if (!use_json) {
                vty_out(vty, "BFD Peers:\n");
                bfd_id_iterate(_display_peer_counter_iter, vty);
                return;
@@ -916,25 +921,29 @@ static int bfdd_write_config(struct vty *vty)
 
 static void _bfdd_peer_write_config(struct vty *vty, struct bfd_session *bs)
 {
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
-               vty_out(vty, " peer %s", satostr(&bs->mhop.peer));
+       char addr_buf[INET6_ADDRSTRLEN];
+
+       vty_out(vty, " peer %s",
+               inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
+                         sizeof(addr_buf)));
+
+       if (bs->key.mhop)
                vty_out(vty, " multihop");
-               vty_out(vty, " local-address %s", satostr(&bs->mhop.local));
-               if (bs->vrfname[0])
-                       vty_out(vty, " vrf %s", bs->vrfname);
-               vty_out(vty, "\n");
-       } else {
-               vty_out(vty, " peer %s", satostr(&bs->shop.peer));
-               if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
-                       vty_out(vty, " local-address %s",
-                               satostr(&bs->local_address));
-               if (bs->ifname[0])
-                       vty_out(vty, " interface %s", bs->ifname);
-               vty_out(vty, "\n");
-       }
+
+       if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+               vty_out(vty, " local-address %s",
+                       inet_ntop(bs->key.family, &bs->key.local, addr_buf,
+                                 sizeof(addr_buf)));
+
+       if (bs->key.vrfname[0])
+               vty_out(vty, " vrf %s", bs->key.vrfname);
+       if (bs->key.ifname[0])
+               vty_out(vty, " interface %s", bs->key.ifname);
+       vty_out(vty, "\n");
 
        if (bs->sock == -1)
-               vty_out(vty, "  ! vrf or interface doesn't exist\n");
+               vty_out(vty,
+                       "  ! vrf, interface or local-address doesn't exist\n");
 
        if (bs->detect_mult != BPC_DEF_DETECTMULTIPLIER)
                vty_out(vty, "  detect-multiplier %d\n", bs->detect_mult);
@@ -980,16 +989,7 @@ static void _bfdd_peer_write_config_iter(struct hash_bucket *hb, void *arg)
 
 static int bfdd_peer_write_config(struct vty *vty)
 {
-       struct bfd_session_observer *bso;
-
        bfd_id_iterate(_bfdd_peer_write_config_iter, vty);
-       TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
-               /* Only print disabled sessions here. */
-               if (bso->bso_bs->sock != -1)
-                       continue;
-
-               _bfdd_peer_write_config(vty, bso->bso_bs);
-       }
 
        return 1;
 }
index d1342eff1ec22fb58efa982b226c7731128da976..cd57ea9fe38b03ecd01aeb7dfe1cf4744b7299d9 100644 (file)
@@ -309,24 +309,7 @@ static int parse_peer_label_config(struct json_object *jo,
        log_debug("\tpeer-label: %s", sval);
 
        /* Translate the label into BFD address keys. */
-       bpc->bpc_ipv4 = !BFD_CHECK_FLAG(pl->pl_bs->flags, BFD_SESS_FLAG_IPV6);
-       bpc->bpc_mhop = BFD_CHECK_FLAG(pl->pl_bs->flags, BFD_SESS_FLAG_MH);
-       if (bpc->bpc_mhop) {
-               bpc->bpc_peer = pl->pl_bs->mhop.peer;
-               bpc->bpc_local = pl->pl_bs->mhop.local;
-               if (pl->pl_bs->mhop.vrfid != VRF_DEFAULT) {
-                       bpc->bpc_has_vrfname = true;
-                       strlcpy(bpc->bpc_vrfname, pl->pl_bs->vrf->name,
-                               sizeof(bpc->bpc_vrfname));
-               }
-       } else {
-               bpc->bpc_peer = pl->pl_bs->shop.peer;
-               if (pl->pl_bs->ifname[0]) {
-                       bpc->bpc_has_localif = true;
-                       strlcpy(bpc->bpc_localif, pl->pl_bs->ifname,
-                               sizeof(bpc->bpc_localif));
-               }
-       }
+       bs_to_bpc(pl->pl_bs, bpc);
 
        return 0;
 }
@@ -519,6 +502,8 @@ int config_notify_request(struct bfd_control_socket *bcs, const char *jsonstr,
 
 static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs)
 {
+       char addr_buf[INET6_ADDRSTRLEN];
+
        /* Add peer 'key' information. */
        if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6))
                json_object_boolean_true_add(jo, "ipv6");
@@ -528,21 +513,26 @@ static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs)
        if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
                json_object_boolean_true_add(jo, "multihop");
                json_object_string_add(jo, "peer-address",
-                                      satostr(&bs->mhop.peer));
+                                      inet_ntop(bs->key.family, &bs->key.peer,
+                                                addr_buf, sizeof(addr_buf)));
                json_object_string_add(jo, "local-address",
-                                      satostr(&bs->mhop.local));
-               if (bs->vrfname[0])
-                       json_object_string_add(jo, "vrf-name", bs->vrfname);
+                                      inet_ntop(bs->key.family, &bs->key.local,
+                                                addr_buf, sizeof(addr_buf)));
+               if (bs->key.vrfname[0])
+                       json_object_string_add(jo, "vrf-name", bs->key.vrfname);
        } else {
                json_object_boolean_false_add(jo, "multihop");
                json_object_string_add(jo, "peer-address",
-                                      satostr(&bs->shop.peer));
-               if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
-                       json_object_string_add(jo, "local-address",
-                                              satostr(&bs->local_address));
-               if (bs->ifname[0])
+                                      inet_ntop(bs->key.family, &bs->key.peer,
+                                                addr_buf, sizeof(addr_buf)));
+               if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+                       json_object_string_add(
+                               jo, "local-address",
+                               inet_ntop(bs->key.family, &bs->key.local,
+                                         addr_buf, sizeof(addr_buf)));
+               if (bs->key.ifname[0])
                        json_object_string_add(jo, "local-interface",
-                                              bs->ifname);
+                                              bs->key.ifname);
        }
 
        if (bs->pl)
@@ -574,8 +564,6 @@ struct peer_label *pl_new(const char *label, struct bfd_session *bs)
        struct peer_label *pl;
 
        pl = XCALLOC(MTYPE_BFDD_LABEL, sizeof(*pl));
-       if (pl == NULL)
-               return NULL;
 
        if (strlcpy(pl->pl_label, label, sizeof(pl->pl_label))
            > sizeof(pl->pl_label))
index 40f4f4d3be482af8282dd84469383ce1aef209fc..c308d647d83e36c5084babc7e362dd6de02d4c7c 100644 (file)
@@ -186,8 +186,6 @@ struct bfd_control_socket *control_new(int sd)
        struct bfd_control_socket *bcs;
 
        bcs = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*bcs));
-       if (bcs == NULL)
-               return NULL;
 
        /* Disable notifications by default. */
        bcs->bcs_notify = 0;
@@ -247,10 +245,6 @@ struct bfd_notify_peer *control_notifypeer_new(struct bfd_control_socket *bcs,
                return bnp;
 
        bnp = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*bnp));
-       if (bnp == NULL) {
-               log_warning("%s: calloc: %s", __func__, strerror(errno));
-               return NULL;
-       }
 
        TAILQ_INSERT_TAIL(&bcs->bcs_bnplist, bnp, bnp_entry);
        bnp->bnp_bs = bs;
@@ -285,10 +279,6 @@ struct bfd_control_queue *control_queue_new(struct bfd_control_socket *bcs)
        struct bfd_control_queue *bcq;
 
        bcq = XCALLOC(MTYPE_BFDD_NOTIFICATION, sizeof(*bcq));
-       if (bcq == NULL) {
-               log_warning("%s: calloc: %s", __func__, strerror(errno));
-               return NULL;
-       }
 
        control_reset_buf(&bcq->bcq_bcb);
        TAILQ_INSERT_TAIL(&bcs->bcs_bcqueue, bcq, bcq_entry);
@@ -743,11 +733,6 @@ static void control_response(struct bfd_control_socket *bcs, uint16_t id,
        jsonstrlen = strlen(jsonstr);
        bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION,
                      sizeof(struct bfd_control_msg) + jsonstrlen);
-       if (bcm == NULL) {
-               log_warning("%s: malloc: %s", __func__, strerror(errno));
-               XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr);
-               return;
-       }
 
        bcm->bcm_length = htonl(jsonstrlen);
        bcm->bcm_ver = BMV_VERSION_1;
@@ -778,11 +763,6 @@ static void _control_notify(struct bfd_control_socket *bcs,
        jsonstrlen = strlen(jsonstr);
        bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION,
                      sizeof(struct bfd_control_msg) + jsonstrlen);
-       if (bcm == NULL) {
-               log_warning("%s: malloc: %s", __func__, strerror(errno));
-               XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr);
-               return;
-       }
 
        bcm->bcm_length = htonl(jsonstrlen);
        bcm->bcm_ver = BMV_VERSION_1;
@@ -846,11 +826,6 @@ static void _control_notify_config(struct bfd_control_socket *bcs,
        jsonstrlen = strlen(jsonstr);
        bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION,
                      sizeof(struct bfd_control_msg) + jsonstrlen);
-       if (bcm == NULL) {
-               log_warning("%s: malloc: %s", __func__, strerror(errno));
-               XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr);
-               return;
-       }
 
        bcm->bcm_length = htonl(jsonstrlen);
        bcm->bcm_ver = BMV_VERSION_1;
index 3f1512d8e715de38b86304c3b90a2e3e2cf20682..8d80b9468db5374af1dbdeda8af84b00b05f9ff2 100644 (file)
@@ -55,7 +55,7 @@ static struct zclient *zclient;
 /*
  * Prototypes
  */
-static int _ptm_msg_address(struct stream *msg, struct sockaddr_any *sa);
+static int _ptm_msg_address(struct stream *msg, int family, const void *addr);
 
 static void _ptm_msg_read_address(struct stream *msg, struct sockaddr_any *sa);
 static int _ptm_msg_read(struct stream *msg, int command,
@@ -127,24 +127,24 @@ static void debug_printbpc(const char *func, unsigned int line,
 #define DEBUG_PRINTBPC(bpc)
 #endif /* BFD_DEBUG */
 
-static int _ptm_msg_address(struct stream *msg, struct sockaddr_any *sa)
+static int _ptm_msg_address(struct stream *msg, int family, const void *addr)
 {
-       switch (sa->sa_sin.sin_family) {
+       stream_putc(msg, family);
+
+       switch (family) {
        case AF_INET:
-               stream_putc(msg, sa->sa_sin.sin_family);
-               stream_put_in_addr(msg, &sa->sa_sin.sin_addr);
+               stream_put(msg, addr, sizeof(struct in_addr));
                stream_putc(msg, 32);
                break;
 
        case AF_INET6:
-               stream_putc(msg, sa->sa_sin6.sin6_family);
-               stream_put(msg, &sa->sa_sin6.sin6_addr,
-                          sizeof(sa->sa_sin6.sin6_addr));
+               stream_put(msg, addr, sizeof(struct in6_addr));
                stream_putc(msg, 128);
                break;
 
        default:
-               return -1;
+               assert(0);
+               break;
        }
 
        return 0;
@@ -153,7 +153,6 @@ static int _ptm_msg_address(struct stream *msg, struct sockaddr_any *sa)
 int ptm_bfd_notify(struct bfd_session *bs)
 {
        struct stream *msg;
-       struct sockaddr_any sac;
 
        bs->stats.znotification++;
 
@@ -195,10 +194,7 @@ int ptm_bfd_notify(struct bfd_session *bs)
                stream_putl(msg, IFINDEX_INTERNAL);
 
        /* BFD destination prefix information. */
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
-               _ptm_msg_address(msg, &bs->mhop.peer);
-       else
-               _ptm_msg_address(msg, &bs->shop.peer);
+       _ptm_msg_address(msg, bs->key.family, &bs->key.peer);
 
        /* BFD status */
        switch (bs->ses_state) {
@@ -218,34 +214,7 @@ int ptm_bfd_notify(struct bfd_session *bs)
        }
 
        /* BFD source prefix information. */
-       if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
-               _ptm_msg_address(msg, &bs->mhop.local);
-       } else {
-               if (bs->local_address.sa_sin.sin_family)
-                       _ptm_msg_address(msg, &bs->local_address);
-               else if (bs->local_address.sa_sin.sin_family)
-                       _ptm_msg_address(msg, &bs->local_ip);
-               else {
-                       sac = bs->shop.peer;
-                       switch (sac.sa_sin.sin_family) {
-                       case AF_INET:
-                               memset(&sac.sa_sin.sin_addr, 0,
-                                      sizeof(sac.sa_sin.sin_family));
-                               break;
-                       case AF_INET6:
-                               memset(&sac.sa_sin6.sin6_addr, 0,
-                                      sizeof(sac.sa_sin6.sin6_family));
-                               break;
-
-                       default:
-                               assert(false);
-                               break;
-                       }
-
-                       /* No local address found yet, so send zeroes. */
-                       _ptm_msg_address(msg, &sac);
-               }
-       }
+       _ptm_msg_address(msg, bs->key.family, &bs->key.local);
 
        /* Write packet size. */
        stream_putw_at(msg, 0, stream_get_endp(msg));
@@ -290,7 +259,6 @@ stream_failure:
 static int _ptm_msg_read(struct stream *msg, int command,
                         struct bfd_peer_cfg *bpc, struct ptm_client **pc)
 {
-       struct interface *ifp;
        uint32_t pid;
        uint8_t ttl __attribute__((unused));
        size_t ifnamelen;
@@ -385,31 +353,6 @@ static int _ptm_msg_read(struct stream *msg, int command,
                if (bpc->bpc_has_localif) {
                        STREAM_GET(bpc->bpc_localif, msg, ifnamelen);
                        bpc->bpc_localif[ifnamelen] = 0;
-
-                       /*
-                        * IPv6 link-local addresses must use scope id,
-                        * otherwise the session lookup will always fail
-                        * and we'll have multiple sessions showing up.
-                        *
-                        * This problem only happens with single hop
-                        * since it is not possible to have link-local
-                        * address for multi hop sessions.
-                        */
-                       if (bpc->bpc_ipv4 == false
-                           && IN6_IS_ADDR_LINKLOCAL(
-                                      &bpc->bpc_peer.sa_sin6.sin6_addr)) {
-                               ifp = if_lookup_by_name_all_vrf(
-                                       bpc->bpc_localif);
-                               if (ifp == NULL) {
-                                       log_error(
-                                               "ptm-read: interface %s doesn't exists",
-                                               bpc->bpc_localif);
-                                       return -1;
-                               }
-
-                               bpc->bpc_peer.sa_sin6.sin6_scope_id =
-                                       ifp->ifindex;
-                       }
                }
        }
 
@@ -608,7 +551,7 @@ static void bfdd_sessions_enable_interface(struct interface *ifp)
 
                /* Interface name mismatch. */
                bs = bso->bso_bs;
-               if (strcmp(ifp->name, bs->ifname))
+               if (strcmp(ifp->name, bs->key.ifname))
                        continue;
                /* Skip enabled sessions. */
                if (bs->sock != -1)
@@ -630,7 +573,7 @@ static void bfdd_sessions_disable_interface(struct interface *ifp)
 
                /* Interface name mismatch. */
                bs = bso->bso_bs;
-               if (strcmp(ifp->name, bs->ifname))
+               if (strcmp(ifp->name, bs->key.ifname))
                        continue;
                /* Skip disabled sessions. */
                if (bs->sock == -1)
@@ -670,6 +613,8 @@ static int bfdd_interface_update(int cmd, struct zclient *zc,
 
        bfdd_sessions_disable_interface(ifp);
 
+       if_set_index(ifp, IFINDEX_INTERNAL);
+
        return 0;
 }
 
@@ -691,6 +636,48 @@ static int bfdd_interface_vrf_update(int command __attribute__((__unused__)),
        return 0;
 }
 
+static void bfdd_sessions_enable_address(struct connected *ifc)
+{
+       struct bfd_session_observer *bso;
+       struct bfd_session *bs;
+       struct prefix prefix;
+
+       TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
+               if (bso->bso_isaddress == false)
+                       continue;
+
+               /* Skip enabled sessions. */
+               bs = bso->bso_bs;
+               if (bs->sock != -1)
+                       continue;
+
+               /* Check address. */
+               prefix = bso->bso_addr;
+               prefix.prefixlen = ifc->address->prefixlen;
+               if (prefix_cmp(&prefix, ifc->address))
+                       continue;
+
+               /* Try to enable it. */
+               bfd_session_enable(bs);
+       }
+}
+
+static int bfdd_interface_address_update(int cmd, struct zclient *zc,
+                                        zebra_size_t len
+                                        __attribute__((__unused__)),
+                                        vrf_id_t vrfid)
+{
+       struct connected *ifc;
+
+       ifc = zebra_interface_address_read(cmd, zc->ibuf, vrfid);
+       if (ifc == NULL)
+               return 0;
+
+       bfdd_sessions_enable_address(ifc);
+
+       return 0;
+}
+
 void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
 {
        zclient = zclient_new(master, &zclient_options_default);
@@ -713,6 +700,10 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
 
        /* Learn about interface VRF. */
        zclient->interface_vrf_update = bfdd_interface_vrf_update;
+
+       /* Learn about new addresses being registered. */
+       zclient->interface_address_add = bfdd_interface_address_update;
+       zclient->interface_address_delete = bfdd_interface_address_update;
 }
 
 void bfdd_zclient_stop(void)
@@ -752,8 +743,6 @@ static struct ptm_client *pc_new(uint32_t pid)
 
        /* Allocate the client data and save it. */
        pc = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*pc));
-       if (pc == NULL)
-               return NULL;
 
        pc->pc_pid = pid;
        TAILQ_INSERT_HEAD(&pcqueue, pc, pc_entry);
@@ -799,8 +788,6 @@ static struct ptm_client_notification *pcn_new(struct ptm_client *pc,
 
        /* Save the client notification data. */
        pcn = XCALLOC(MTYPE_BFDD_NOTIFICATION, sizeof(*pcn));
-       if (pcn == NULL)
-               return NULL;
 
        TAILQ_INSERT_HEAD(&pc->pc_pcnqueue, pcn, pcn_entry);
        pcn->pcn_pc = pc;
index c7fd1ba0e23e51d7d5707003ba6291102cb3646c..63373cb9a73f5d1e5014711a83daaf86254dee3d 100644 (file)
@@ -384,7 +384,7 @@ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
                }
        }
 
-       zlog_info("Resetting peer %s%s due to change in addpath config\n",
+       zlog_info("Resetting peer %s%s due to change in addpath config",
                  CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) ? "group " : "",
                  peer->host);
 
index 208a2947ef1ca5cf14bc41ac4a57f5fb579d9743..05eeeca1564ba7459f29fe39fca42a191b37d5ce 100644 (file)
@@ -45,8 +45,8 @@
    peer.  */
 struct bgp_advertise_attr *baa_new(void)
 {
-       return (struct bgp_advertise_attr *)XCALLOC(
-               MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr));
+       return XCALLOC(MTYPE_BGP_ADVERTISE_ATTR,
+                      sizeof(struct bgp_advertise_attr));
 }
 
 static void baa_free(struct bgp_advertise_attr *baa)
@@ -84,8 +84,7 @@ bool baa_hash_cmp(const void *p1, const void *p2)
    information.  */
 struct bgp_advertise *bgp_advertise_new(void)
 {
-       return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE,
-                                              sizeof(struct bgp_advertise));
+       return XCALLOC(MTYPE_BGP_ADVERTISE, sizeof(struct bgp_advertise));
 }
 
 void bgp_advertise_free(struct bgp_advertise *adv)
@@ -255,8 +254,7 @@ void bgp_sync_delete(struct peer *peer)
        safi_t safi;
 
        FOREACH_AFI_SAFI (afi, safi) {
-               if (peer->sync[afi][safi])
-                       XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
+               XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
                peer->sync[afi][safi] = NULL;
        }
 }
index 3bd3de031ccf4f6b62e270c30c4566abca4b5f2c..92c37fabd23483274b1e47adf9616aab38eda2f1 100644 (file)
@@ -312,8 +312,7 @@ void aspath_free(struct aspath *aspath)
                return;
        if (aspath->segments)
                assegment_free_all(aspath->segments);
-       if (aspath->str)
-               XFREE(MTYPE_AS_STR, aspath->str);
+       XFREE(MTYPE_AS_STR, aspath->str);
 
        if (aspath->json) {
                json_object_free(aspath->json);
@@ -623,8 +622,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
 
 void aspath_str_update(struct aspath *as, bool make_json)
 {
-       if (as->str)
-               XFREE(MTYPE_AS_STR, as->str);
+       XFREE(MTYPE_AS_STR, as->str);
 
        if (as->json) {
                json_object_free(as->json);
index 3f2161f62b95b2770a4f744db02da9d5ec072b11..167ad89a5988f026f4424db02b90505601e26c6f 100644 (file)
@@ -54,6 +54,7 @@
 #include "bgp_encap_types.h"
 #include "bgp_evpn.h"
 #include "bgp_flowspec_private.h"
+#include "bgp_mac.h"
 
 /* Attribute strings for logging. */
 static const struct message attr_str[] = {
@@ -158,8 +159,7 @@ static bool cluster_hash_cmp(const void *p1, const void *p2)
 
 static void cluster_free(struct cluster_list *cluster)
 {
-       if (cluster->list)
-               XFREE(MTYPE_CLUSTER_VAL, cluster->list);
+       XFREE(MTYPE_CLUSTER_VAL, cluster->list);
        XFREE(MTYPE_CLUSTER, cluster);
 }
 
@@ -400,8 +400,7 @@ static struct hash *transit_hash;
 
 static void transit_free(struct transit *transit)
 {
-       if (transit->val)
-               XFREE(MTYPE_TRANSIT_VAL, transit->val);
+       XFREE(MTYPE_TRANSIT_VAL, transit->val);
        XFREE(MTYPE_TRANSIT, transit);
 }
 
@@ -1716,7 +1715,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
                if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
                        if (!peer->nexthop.ifp) {
-                               zlog_warn("%s: interface not set appropriately to handle some attributes",
+                               zlog_warn("%s: Received a V6/VPNV6 Global attribute but address is a V6 LL and we have no peer interface information, withdrawing",
                                          peer->host);
                                return BGP_ATTR_PARSE_WITHDRAW;
                        }
@@ -1733,7 +1732,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
                if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
                        if (!peer->nexthop.ifp) {
-                               zlog_warn("%s: interface not set appropriately to handle some attributes",
+                               zlog_warn("%s: Received V6/VPNV6 Global and LL attribute but global address is a V6 LL and we have no peer interface information, withdrawing",
                                          peer->host);
                                return BGP_ATTR_PARSE_WITHDRAW;
                        }
@@ -1763,7 +1762,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                        attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
                }
                if (!peer->nexthop.ifp) {
-                       zlog_warn("%s: Interface not set appropriately to handle this some attributes",
+                       zlog_warn("%s: Received a V6 LL nexthop and we have no peer interface information, withdrawing",
                                  peer->host);
                        return BGP_ATTR_PARSE_WITHDRAW;
                }
@@ -1944,7 +1943,18 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
        bgp_attr_evpn_na_flag(attr, &attr->router_flag);
 
        /* Extract the Rmac, if any */
-       bgp_attr_rmac(attr, &attr->rmac);
+       if (bgp_attr_rmac(attr, &attr->rmac)) {
+               if (bgp_debug_update(peer, NULL, NULL, 1) &&
+                   bgp_mac_exist(&attr->rmac)) {
+                       char buf1[ETHER_ADDR_STRLEN];
+
+                       zlog_debug("%s: router mac %s is self mac",
+                                  __func__,
+                                  prefix_mac2str(&attr->rmac, buf1,
+                                                 sizeof(buf1)));
+               }
+
+       }
 
        return BGP_ATTR_PARSE_PROCEED;
 }
index 3e9d05ad978c905a4d14005890530500e698b0eb..15fa32215972c819cd6d31b0d07fa861cf3fbf5c 100644 (file)
@@ -84,8 +84,8 @@ char *esi2str(struct eth_segment_id *id)
                return NULL;
 
        val = id->val;
-       ptr = (char *)XMALLOC(MTYPE_TMP,
-                             (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
+       ptr = XMALLOC(MTYPE_TMP,
+                     (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
 
        snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
                 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val[0],
@@ -106,14 +106,14 @@ char *ecom_mac2str(char *ecom_mac)
 }
 
 /* Fetch router-mac from extended community */
-void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
+bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
 {
        int i = 0;
        struct ecommunity *ecom;
 
        ecom = attr->ecommunity;
        if (!ecom || !ecom->size)
-               return;
+               return false;
 
        /* If there is a router mac extended community, set RMAC in attr */
        for (i = 0; i < ecom->size; i++) {
@@ -130,7 +130,9 @@ void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
                        continue;
 
                memcpy(rmac, pnt, ETH_ALEN);
+               return true;
        }
+       return false;
 }
 
 /*
index b036702151d0e01957bec7d693bd765a1374dd6d..5b0ce1da2886ec290a752f1d87de634ba7682f92 100644 (file)
@@ -60,7 +60,7 @@ extern void bgp_add_routermac_ecom(struct attr *attr,
                                   struct ethaddr *routermac);
 extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
                                 struct prefix *dst);
-extern void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
+extern bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
 extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
                                             uint8_t *sticky);
 extern uint8_t bgp_attr_default_gw(struct attr *attr);
index 84a00488c19565383dd81fc6c2fe646389a37897..7b64f349d2330d3a2f0396a4c5d8daf6c9d3d5bd 100644 (file)
@@ -100,16 +100,14 @@ static void community_entry_free(struct community_entry *entry)
        case EXTCOMMUNITY_LIST_STANDARD:
                /* In case of standard extcommunity-list, configuration string
                   is made by ecommunity_ecom2str().  */
-               if (entry->config)
-                       XFREE(MTYPE_ECOMMUNITY_STR, entry->config);
+               XFREE(MTYPE_ECOMMUNITY_STR, entry->config);
                if (entry->u.ecom)
                        ecommunity_free(&entry->u.ecom);
                break;
        case COMMUNITY_LIST_EXPANDED:
        case EXTCOMMUNITY_LIST_EXPANDED:
        case LARGE_COMMUNITY_LIST_EXPANDED:
-               if (entry->config)
-                       XFREE(MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
+               XFREE(MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
                if (entry->reg)
                        bgp_regex_free(entry->reg);
        default:
@@ -127,8 +125,7 @@ static struct community_list *community_list_new(void)
 /* Free community-list.  */
 static void community_list_free(struct community_list *list)
 {
-       if (list->name)
-               XFREE(MTYPE_COMMUNITY_LIST_NAME, list->name);
+       XFREE(MTYPE_COMMUNITY_LIST_NAME, list->name);
        XFREE(MTYPE_COMMUNITY_LIST, list);
 }
 
index 2e28c30950b91ac96c36e3d882a42f4260aafee7..67cd2be214897036c6d713d84ade54c0ba547445 100644 (file)
@@ -34,17 +34,14 @@ static struct hash *comhash;
 /* Allocate a new communities value.  */
 static struct community *community_new(void)
 {
-       return (struct community *)XCALLOC(MTYPE_COMMUNITY,
-                                          sizeof(struct community));
+       return XCALLOC(MTYPE_COMMUNITY, sizeof(struct community));
 }
 
 /* Free communities value.  */
 void community_free(struct community **com)
 {
-       if ((*com)->val)
-               XFREE(MTYPE_COMMUNITY_VAL, (*com)->val);
-       if ((*com)->str)
-               XFREE(MTYPE_COMMUNITY_STR, (*com)->str);
+       XFREE(MTYPE_COMMUNITY_VAL, (*com)->val);
+       XFREE(MTYPE_COMMUNITY_STR, (*com)->str);
 
        if ((*com)->json) {
                json_object_free((*com)->json);
index fcfaa388d91d031c7b3bd47fdb721f75dd93f4db..8ef398952d3a59217006ad37fea9aa17f6fc8c1d 100644 (file)
@@ -48,8 +48,7 @@ static struct hash *ecomhash;
 /* Allocate a new ecommunities.  */
 struct ecommunity *ecommunity_new(void)
 {
-       return (struct ecommunity *)XCALLOC(MTYPE_ECOMMUNITY,
-                                           sizeof(struct ecommunity));
+       return XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity));
 }
 
 void ecommunity_strfree(char **s)
@@ -60,10 +59,8 @@ void ecommunity_strfree(char **s)
 /* Allocate ecommunities.  */
 void ecommunity_free(struct ecommunity **ecom)
 {
-       if ((*ecom)->val)
-               XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
-       if ((*ecom)->str)
-               XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str);
+       XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
+       XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str);
        XFREE(MTYPE_ECOMMUNITY, *ecom);
 }
 
index 30a08098e87d75a7b2fd366728ca45dd435b41d7..964adec9b64a257e5dae978ac7c136e6362a8a31 100644 (file)
@@ -401,8 +401,7 @@ void bgp_encap_type_vxlan_to_tlv(
 
        if (bet == NULL || !bet->vnid)
                return;
-       if (attr->encap_subtlvs)
-               XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs);
+       XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs);
        tlv = XCALLOC(MTYPE_ENCAP_TLV,
                      sizeof(struct bgp_attr_encap_subtlv) + 12);
        tlv->type = 1; /* encapsulation type */
index 4a8fe111be6eaed86b02b646abe847981f0fc4ed..732cc6d2bb4c044c1d1ee8c4e789b1145bd3e231 100644 (file)
@@ -48,6 +48,7 @@
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_nexthop.h"
 #include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
 
 /*
  * Definitions and external declarations.
@@ -168,30 +169,28 @@ static bool vrf_import_rt_hash_cmp(const void *p1, const void *p2)
 }
 
 /*
- * Create a new vrf import_rt in default instance
+ * Create a new vrf import_rt in evpn instance
  */
 static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt)
 {
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
        struct vrf_irt_node *irt;
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def) {
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn) {
                flog_err(EC_BGP_NO_DFLT,
-                        "vrf import rt new - def instance not created yet");
+                        "vrf import rt new - evpn instance not created yet");
                return NULL;
        }
 
        irt = XCALLOC(MTYPE_BGP_EVPN_VRF_IMPORT_RT,
                      sizeof(struct vrf_irt_node));
-       if (!irt)
-               return NULL;
 
        irt->rt = *rt;
        irt->vrfs = list_new();
 
        /* Add to hash */
-       if (!hash_get(bgp_def->vrf_import_rt_hash, irt, hash_alloc_intern)) {
+       if (!hash_get(bgp_evpn->vrf_import_rt_hash, irt, hash_alloc_intern)) {
                XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt);
                return NULL;
        }
@@ -204,16 +203,16 @@ static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt)
  */
 static void vrf_import_rt_free(struct vrf_irt_node *irt)
 {
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def) {
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn) {
                flog_err(EC_BGP_NO_DFLT,
-                        "vrf import rt free - def instance not created yet");
+                        "vrf import rt free - evpn instance not created yet");
                return;
        }
 
-       hash_release(bgp_def->vrf_import_rt_hash, irt);
+       hash_release(bgp_evpn->vrf_import_rt_hash, irt);
        list_delete(&irt->vrfs);
        XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt);
 }
@@ -224,20 +223,21 @@ static void vrf_import_rt_free(struct vrf_irt_node *irt)
  */
 static struct vrf_irt_node *lookup_vrf_import_rt(struct ecommunity_val *rt)
 {
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
        struct vrf_irt_node *irt;
        struct vrf_irt_node tmp;
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def) {
-               flog_err(EC_BGP_NO_DFLT,
-                        "vrf import rt lookup - def instance not created yet");
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn) {
+               flog_err(
+                       EC_BGP_NO_DFLT,
+                       "vrf import rt lookup - evpn instance not created yet");
                return NULL;
        }
 
        memset(&tmp, 0, sizeof(struct vrf_irt_node));
        memcpy(&tmp.rt, rt, ECOMMUNITY_SIZE);
-       irt = hash_lookup(bgp_def->vrf_import_rt_hash, &tmp);
+       irt = hash_lookup(bgp_evpn->vrf_import_rt_hash, &tmp);
        return irt;
 }
 
@@ -296,8 +296,6 @@ static struct irt_node *import_rt_new(struct bgp *bgp,
                return NULL;
 
        irt = XCALLOC(MTYPE_BGP_EVPN_IMPORT_RT, sizeof(struct irt_node));
-       if (!irt)
-               return NULL;
 
        irt->rt = *rt;
        irt->vnis = list_new();
@@ -968,8 +966,6 @@ static struct in_addr *es_vtep_new(struct in_addr vtep)
        struct in_addr *ip;
 
        ip = XCALLOC(MTYPE_BGP_EVPN_ES_VTEP, sizeof(struct in_addr));
-       if (!ip)
-               return NULL;
 
        ip->s_addr = vtep.s_addr;
        return ip;
@@ -1426,7 +1422,7 @@ static int update_evpn_type4_route(struct bgp *bgp,
        return 0;
 }
 
-static int update_evpn_type5_route_entry(struct bgp *bgp_def,
+static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
                                         struct bgp *bgp_vrf, afi_t afi,
                                         safi_t safi, struct bgp_node *rn,
                                         struct attr *attr, int *route_changed)
@@ -1441,7 +1437,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def,
        /* locate the local route entry if any */
        for (tmp_pi = bgp_node_get_bgp_path_info(rn); tmp_pi;
             tmp_pi = tmp_pi->next) {
-               if (tmp_pi->peer == bgp_def->peer_self
+               if (tmp_pi->peer == bgp_evpn->peer_self
                    && tmp_pi->type == ZEBRA_ROUTE_BGP
                    && tmp_pi->sub_type == BGP_ROUTE_STATIC)
                        local_pi = tmp_pi;
@@ -1461,7 +1457,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def,
 
                /* create the route info from attribute */
                pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
-                              bgp_def->peer_self, attr_new, rn);
+                              bgp_evpn->peer_self, attr_new, rn);
                SET_FLAG(pi->flags, BGP_PATH_VALID);
 
                /* Type-5 routes advertise the L3-VNI */
@@ -1507,11 +1503,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
        safi_t safi = SAFI_EVPN;
        struct attr attr;
        struct bgp_node *rn = NULL;
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
        int route_changed = 0;
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def)
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn)
                return 0;
 
        /* Build path attribute for this route - use the source attr, if
@@ -1533,17 +1529,17 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
        build_evpn_type5_route_extcomm(bgp_vrf, &attr);
 
        /* get the route node in global table */
-       rn = bgp_afi_node_get(bgp_def->rib[afi][safi], afi, safi,
+       rn = bgp_afi_node_get(bgp_evpn->rib[afi][safi], afi, safi,
                              (struct prefix *)evp, &bgp_vrf->vrf_prd);
        assert(rn);
 
        /* create or update the route entry within the route node */
-       update_evpn_type5_route_entry(bgp_def, bgp_vrf, afi, safi, rn, &attr,
+       update_evpn_type5_route_entry(bgp_evpn, bgp_vrf, afi, safi, rn, &attr,
                                      &route_changed);
 
        /* schedule for processing and unlock node */
        if (route_changed) {
-               bgp_process(bgp_def, rn, afi, safi);
+               bgp_process(bgp_evpn, rn, afi, safi);
                bgp_unlock_node(rn);
        }
 
@@ -1930,21 +1926,21 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
        safi_t safi = SAFI_EVPN;
        struct bgp_node *rn = NULL;
        struct bgp_path_info *pi = NULL;
-       struct bgp *bgp_def = NULL; /* default bgp instance */
+       struct bgp *bgp_evpn = NULL; /* evpn bgp instance */
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def)
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn)
                return 0;
 
        /* locate the global route entry for this type-5 prefix */
-       rn = bgp_afi_node_lookup(bgp_def->rib[afi][safi], afi, safi,
+       rn = bgp_afi_node_lookup(bgp_evpn->rib[afi][safi], afi, safi,
                                 (struct prefix *)evp, &bgp_vrf->vrf_prd);
        if (!rn)
                return 0;
 
-       delete_evpn_route_entry(bgp_def, afi, safi, rn, &pi);
+       delete_evpn_route_entry(bgp_evpn, afi, safi, rn, &pi);
        if (pi)
-               bgp_process(bgp_def, rn, afi, safi);
+               bgp_process(bgp_evpn, rn, afi, safi);
        bgp_unlock_node(rn);
        return 0;
 }
@@ -2508,6 +2504,9 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
        /* Perform route selection and update zebra, if required. */
        bgp_process(bgp_vrf, rn, afi, safi);
 
+       /* Process for route leaking. */
+       vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi);
+
        return ret;
 }
 
@@ -2673,6 +2672,9 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
        if (!pi)
                return 0;
 
+       /* Process for route leaking. */
+       vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp_vrf, pi);
+
        bgp_aggregate_decrement(bgp_vrf, &rn->p, pi, afi, safi);
 
        /* Mark entry for deletion */
@@ -2945,6 +2947,41 @@ static int install_uninstall_routes_for_es(struct bgp *bgp,
        return 0;
 }
 
+/* This API will scan evpn routes for checking attribute's rmac
+ * macthes with bgp instance router mac. It avoid installing
+ * route into bgp vrf table and remote rmac in bridge table.
+ */
+static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf,
+                                         struct prefix_evpn *evp,
+                                         struct bgp_path_info *pi)
+{
+       /* evpn route could have learnt prior to L3vni has come up,
+        * perform rmac check before installing route and
+        * remote router mac.
+        * The route will be removed from global bgp table once
+        * SVI comes up with MAC and stored in hash, triggers
+        * bgp_mac_rescan_all_evpn_tables.
+        */
+       if (pi->attr &&
+           memcmp(&bgp_vrf->rmac, &pi->attr->rmac, ETH_ALEN) == 0) {
+               if (bgp_debug_update(pi->peer, NULL, NULL, 1)) {
+                       char buf1[PREFIX_STRLEN];
+                       char attr_str[BUFSIZ] = {0};
+
+                       bgp_dump_attr(pi->attr, attr_str, BUFSIZ);
+
+                       zlog_debug("%s: bgp %u prefix %s with attr %s - DENIED due to self mac",
+                               __func__, bgp_vrf->vrf_id,
+                               prefix2str(evp, buf1, sizeof(buf1)),
+                               attr_str);
+               }
+
+               return 1;
+       }
+
+       return 0;
+}
+
 /*
  * Install or uninstall mac-ip routes are appropriate for this
  * particular VRF.
@@ -2958,19 +2995,19 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
        struct bgp_path_info *pi;
        int ret;
        char buf[PREFIX_STRLEN];
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
-       bgp_def = bgp_get_default();
-       if (!bgp_def)
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn)
                return -1;
 
        /* Walk entire global routing table and evaluate routes which could be
         * imported into this VRF. Note that we need to loop through all global
         * routes to determine which route matches the import rt on vrf
         */
-       for (rd_rn = bgp_table_top(bgp_def->rib[afi][safi]); rd_rn;
+       for (rd_rn = bgp_table_top(bgp_evpn->rib[afi][safi]); rd_rn;
             rd_rn = bgp_route_next(rd_rn)) {
                table = bgp_node_get_bgp_table_info(rd_rn);
                if (!table)
@@ -3001,6 +3038,10 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
                                        continue;
 
                                if (is_route_matching_for_vrf(bgp_vrf, pi)) {
+                                       if (bgp_evpn_route_rmac_self_check(
+                                                               bgp_vrf, evp, pi))
+                                               continue;
+
                                        if (install)
                                                ret = install_evpn_route_entry_in_vrf(
                                                        bgp_vrf, evp, pi);
@@ -3935,7 +3976,7 @@ static int process_type4_route(struct peer *peer, afi_t afi, safi_t safi,
  */
 static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
                               struct attr *attr, uint8_t *pfx, int psize,
-                              uint32_t addpath_id, int withdraw)
+                              uint32_t addpath_id)
 {
        struct prefix_rd prd;
        struct prefix_evpn p;
@@ -4021,7 +4062,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
         */
 
        /* Process the route. */
-       if (!withdraw)
+       if (attr)
                ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
                                 afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
                                 &prd, &label, 1, 0, &evpn);
@@ -4117,14 +4158,14 @@ static void free_vni_entry(struct hash_bucket *bucket, struct bgp *bgp)
  */
 static void evpn_auto_rt_import_add_for_vrf(struct bgp *bgp_vrf)
 {
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
 
        form_auto_rt(bgp_vrf, bgp_vrf->l3vni, bgp_vrf->vrf_import_rtl);
        UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_IMPORT_RT_CFGD);
 
        /* Map RT to VRF */
-       bgp_def = bgp_get_default();
-       if (!bgp_def)
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn)
                return;
        bgp_evpn_map_vrf_to_its_rts(bgp_vrf);
 }
@@ -4156,12 +4197,12 @@ static void evpn_auto_rt_export_delete_for_vrf(struct bgp *bgp_vrf)
 
 static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf)
 {
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
        struct listnode *node = NULL;
        struct bgpevpn *vpn = NULL;
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def)
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn)
                return;
 
        /* update all type-5 routes */
@@ -4169,7 +4210,7 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf)
 
        /* update all type-2 routes */
        for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn))
-               update_routes_for_vni(bgp_def, vpn);
+               update_routes_for_vni(bgp_evpn, vpn);
 }
 
 /*
@@ -4228,11 +4269,13 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi)
 
        table = bgp_vrf->rib[afi][safi];
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
-               /* Only care about "selected" routes - non-imported. */
+               /* Only care about "selected" routes. Also ensure that
+                * these are routes that are injectable into EVPN.
+                */
                /* TODO: Support for AddPath for EVPN. */
                for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
                        if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
-                           && (!pi->extra || !pi->extra->parent)) {
+                           && is_route_injectable_into_evpn(pi)) {
                                bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p,
                                                              afi, safi);
                                break;
@@ -4299,12 +4342,13 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
        table = bgp_vrf->rib[afi][safi];
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
                /* Need to identify the "selected" route entry to use its
-                * attribute. Also, we only consider "non-imported" routes.
+                * attribute. Also, ensure that the route is injectable
+                * into EVPN.
                 * TODO: Support for AddPath for EVPN.
                 */
                for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
                        if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
-                           && (!pi->extra || !pi->extra->parent)) {
+                           && is_route_injectable_into_evpn(pi)) {
 
                                /* apply the route-map */
                                if (bgp_vrf->adv_cmd_rmap[afi][safi].map) {
@@ -4873,8 +4917,9 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
                        break;
 
                case BGP_EVPN_IP_PREFIX_ROUTE:
-                       if (process_type5_route(peer, afi, safi, attr, pnt,
-                                               psize, addpath_id, withdraw)) {
+                       if (process_type5_route(peer, afi, safi,
+                                               withdraw ? NULL : attr, pnt,
+                                               psize, addpath_id)) {
                                flog_err(
                                        EC_BGP_PKT_PROCESS,
                                        "%u:%s - Error in processing EVPN type-5 NLRI size %d",
@@ -5037,6 +5082,9 @@ void bgp_evpn_derive_auto_rt_export(struct bgp *bgp, struct bgpevpn *vpn)
  */
 void bgp_evpn_derive_auto_rd_for_vrf(struct bgp *bgp)
 {
+       if (is_vrf_rd_configured(bgp))
+               return;
+
        form_auto_rd(bgp->router_id, bgp->vrf_rd_id, &bgp->vrf_prd);
 }
 
@@ -5099,8 +5147,6 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
                return NULL;
 
        vpn = XCALLOC(MTYPE_BGP_EVPN, sizeof(struct bgpevpn));
-       if (!vpn)
-               return NULL;
 
        /* Set values - RD and RT set to defaults. */
        vpn->vni = vni;
@@ -5180,8 +5226,6 @@ struct evpnes *bgp_evpn_es_new(struct bgp *bgp,
                return NULL;
 
        es = XCALLOC(MTYPE_BGP_EVPN_ES, sizeof(struct evpnes));
-       if (!es)
-               return NULL;
 
        /* set the ESI and originator_ip */
        memcpy(&es->esi, esi, sizeof(esi_t));
@@ -5386,10 +5430,10 @@ static void link_l2vni_hash_to_l3vni(struct hash_bucket *bucket,
                                     struct bgp *bgp_vrf)
 {
        struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
 
-       bgp_def = bgp_get_default();
-       assert(bgp_def);
+       bgp_evpn = bgp_get_evpn();
+       assert(bgp_evpn);
 
        if (vpn->tenant_vrf_id == bgp_vrf->vrf_id)
                bgpevpn_link_to_l3vni(vpn);
@@ -5400,32 +5444,33 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
                             ifindex_t svi_ifindex)
 {
        struct bgp *bgp_vrf = NULL; /* bgp VRF instance */
-       struct bgp *bgp_def = NULL; /* default bgp instance */
+       struct bgp *bgp_evpn = NULL; /* EVPN bgp instance */
        struct listnode *node = NULL;
        struct bgpevpn *vpn = NULL;
        as_t as = 0;
 
-       /* get the default instance - required to get the AS number for VRF
+       /* get the EVPN instance - required to get the AS number for VRF
         * auto-creatio
         */
-       bgp_def = bgp_get_default();
-       if (!bgp_def) {
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn) {
                flog_err(
                        EC_BGP_NO_DFLT,
-                       "Cannot process L3VNI  %u ADD - default BGP instance not yet created",
+                       "Cannot process L3VNI  %u ADD - EVPN BGP instance not yet created",
                        l3vni);
                return -1;
        }
-       as = bgp_def->as;
+       as = bgp_evpn->as;
 
        /* if the BGP vrf instance doesn't exist - create one */
-       bgp_vrf = bgp_lookup_by_name(vrf_id_to_name(vrf_id));
+       bgp_vrf = bgp_lookup_by_vrf_id(vrf_id);
        if (!bgp_vrf) {
 
                int ret = 0;
 
                ret = bgp_get(&bgp_vrf, &as, vrf_id_to_name(vrf_id),
-                             BGP_INSTANCE_TYPE_VRF);
+                             vrf_id == VRF_DEFAULT ? BGP_INSTANCE_TYPE_DEFAULT
+                                                   : BGP_INSTANCE_TYPE_VRF);
                switch (ret) {
                case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET:
                        flog_err(EC_BGP_MULTI_INSTANCE,
@@ -5468,7 +5513,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
        bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
 
        /* link all corresponding l2vnis */
-       hash_iterate(bgp_def->vnihash,
+       hash_iterate(bgp_evpn->vnihash,
                     (void (*)(struct hash_bucket *,
                               void *))link_l2vni_hash_to_l3vni,
                     bgp_vrf);
@@ -5478,7 +5523,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
         */
        if (!filter)
                for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn))
-                       update_routes_for_vni(bgp_def, vpn);
+                       update_routes_for_vni(bgp_evpn, vpn);
 
        /* advertise type-5 routes if needed */
        update_advertise_vrf_routes(bgp_vrf);
@@ -5493,7 +5538,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
 int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id)
 {
        struct bgp *bgp_vrf = NULL; /* bgp vrf instance */
-       struct bgp *bgp_def = NULL; /* default bgp instance */
+       struct bgp *bgp_evpn = NULL; /* EVPN bgp instance */
        struct listnode *node = NULL;
        struct listnode *next = NULL;
        struct bgpevpn *vpn = NULL;
@@ -5507,11 +5552,11 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id)
                return -1;
        }
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def) {
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn) {
                flog_err(
                        EC_BGP_NO_DFLT,
-                       "Cannot process L3VNI %u Del - Could not find default BGP instance",
+                       "Cannot process L3VNI %u Del - Could not find EVPN BGP instance",
                        l3vni);
                return -1;
        }
@@ -5549,7 +5594,7 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id)
        if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)) {
                for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
                        UNSET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS);
-                       update_routes_for_vni(bgp_def, vpn);
+                       update_routes_for_vni(bgp_evpn, vpn);
                }
        }
 
index fbf30083e178f92cd7b95dfb07b06e24beea1f93..f5802fa894002162a8d6efde0c21fe6d6bb6ca52 100644 (file)
 #define EVPN_ROUTE_STRLEN 200 /* Must be >> MAC + IPv6 strings. */
 #define EVPN_AUTORT_VXLAN 0x10000000
 
+#define EVPN_ENABLED(bgp)  (bgp)->advertise_all_vni
 static inline int is_evpn_enabled(void)
 {
        struct bgp *bgp = NULL;
 
-       bgp = bgp_get_default();
-       return bgp ? bgp->advertise_all_vni : 0;
+       bgp = bgp_get_evpn();
+       return bgp ? EVPN_ENABLED(bgp) : 0;
 }
 
 static inline void vni2label(vni_t vni, mpls_label_t *label)
@@ -88,8 +89,13 @@ static inline int is_route_parent_evpn(struct bgp_path_info *ri)
            !ri->extra->parent)
                return 0;
 
-       /* See if the parent is of family L2VPN/EVPN */
-       parent_ri = (struct bgp_path_info *)ri->extra->parent;
+       /* Determine parent recursively */
+       for (parent_ri = ri->extra->parent;
+            parent_ri->extra && parent_ri->extra->parent;
+            parent_ri = parent_ri->extra->parent)
+               ;
+
+       /* See if of family L2VPN/EVPN */
        rn = parent_ri->net;
        if (!rn)
                return 0;
@@ -101,6 +107,38 @@ static inline int is_route_parent_evpn(struct bgp_path_info *ri)
        return 0;
 }
 
+/* Flag if the route path's family is EVPN. */
+static inline bool is_pi_family_evpn(struct bgp_path_info *pi)
+{
+       return is_pi_family_matching(pi, AFI_L2VPN, SAFI_EVPN);
+}
+
+/* Flag if the route is injectable into EVPN. This would be either a
+ * non-imported route or a non-EVPN imported route.
+ */
+static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi)
+{
+       struct bgp_path_info *parent_pi;
+       struct bgp_table *table;
+       struct bgp_node *rn;
+
+       if (pi->sub_type != BGP_ROUTE_IMPORTED ||
+           !pi->extra ||
+           !pi->extra->parent)
+               return true;
+
+       parent_pi = (struct bgp_path_info *)pi->extra->parent;
+       rn = parent_pi->net;
+       if (!rn)
+               return true;
+       table = bgp_node_table(rn);
+       if (table &&
+           table->afi == AFI_L2VPN &&
+           table->safi == SAFI_EVPN)
+               return false;
+       return true;
+}
+
 extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
                                           struct prefix *p,
                                           struct attr *src_attr, afi_t afi,
index c7f2671b78377ca2e9c4446044f4a9976f52cbd0..785139865e40f0813310a37028c9278aa99f46d9 100644 (file)
@@ -30,8 +30,9 @@
 
 #define RT_ADDRSTRLEN 28
 
-/* EVPN prefix lengths. This reprsent the sizeof struct prefix_evpn  */
-#define EVPN_ROUTE_PREFIXLEN     224
+/* EVPN prefix lengths. This represents the sizeof struct evpn_addr
+ * in bits  */
+#define EVPN_ROUTE_PREFIXLEN (sizeof(struct evpn_addr) * 8)
 
 /* EVPN route types. */
 typedef enum {
index 8437c4024eb31791933f0c701193426ebe119caa..0454fc2212674acc844c5d6e246a0b6c173df163 100644 (file)
@@ -1006,7 +1006,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
        json_object *json_scode = NULL;
        json_object *json_ocode = NULL;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (bgp == NULL) {
                if (!use_json)
                        vty_out(vty, "No BGP process is configured\n");
@@ -1958,9 +1958,9 @@ static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
 
 /*
  * Display import RT mapping to VRFs (vty handler)
- * bgp_def: default bgp instance
+ * bgp_evpn: evpn bgp instance
  */
-static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_def,
+static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
                                     json_object *json)
 {
        void *args[2];
@@ -1968,7 +1968,7 @@ static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_def,
        args[0] = vty;
        args[1] = json;
 
-       hash_iterate(bgp_def->vrf_import_rt_hash,
+       hash_iterate(bgp_evpn->vrf_import_rt_hash,
                     (void (*)(struct hash_bucket *,
                               void *))show_vrf_import_rt_entry,
                     args);
@@ -2757,6 +2757,7 @@ static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
 static void evpn_set_advertise_all_vni(struct bgp *bgp)
 {
        bgp->advertise_all_vni = 1;
+       bgp_set_evpn(bgp);
        bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
 }
 
@@ -2767,6 +2768,7 @@ static void evpn_set_advertise_all_vni(struct bgp *bgp)
 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
 {
        bgp->advertise_all_vni = 0;
+       bgp_set_evpn(bgp_get_default());
        bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
        bgp_evpn_cleanup_on_disable(bgp);
 }
@@ -2915,9 +2917,9 @@ DEFUN (bgp_evpn_advertise_default_gw,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under the EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -2937,9 +2939,9 @@ DEFUN (no_bgp_evpn_advertise_default_gw,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under the EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -2954,9 +2956,18 @@ DEFUN (bgp_evpn_advertise_all_vni,
        "Advertise All local VNIs\n")
 {
        struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       struct bgp *bgp_evpn = NULL;
 
        if (!bgp)
                return CMD_WARNING;
+
+       bgp_evpn = bgp_get_evpn();
+       if (bgp_evpn && bgp_evpn != bgp) {
+               vty_out(vty, "%% Please unconfigure EVPN in VRF %s\n",
+                       bgp_evpn->name);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
        evpn_set_advertise_all_vni(bgp);
        return CMD_SUCCESS;
 }
@@ -3055,9 +3066,9 @@ DEFPY (dup_addr_detection,
        if (!bgp_vrf)
                return CMD_WARNING;
 
-       if (bgp_vrf->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp_vrf)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under the EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -3087,9 +3098,9 @@ DEFPY (dup_addr_detection_auto_recovery,
        if (!bgp_vrf)
                return CMD_WARNING;
 
-       if (bgp_vrf->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp_vrf)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under the EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -3122,9 +3133,9 @@ DEFPY (no_dup_addr_detection,
        if (!bgp_vrf)
                return CMD_WARNING;
 
-       if (bgp_vrf->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp_vrf)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under the EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -3194,9 +3205,9 @@ DEFPY(bgp_evpn_advertise_svi_ip,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -3358,7 +3369,8 @@ DEFUN (bgp_evpn_advertise_type5,
        }
 
        /* advertise type-5 routes */
-       bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
+       if (advertise_type5_routes(bgp_vrf, afi))
+               bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
        return CMD_SUCCESS;
 }
 
@@ -3440,7 +3452,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
       "VNI number\n"
       JSON_STR)
 {
-       struct bgp *bgp_def;
+       struct bgp *bgp_evpn;
        vni_t vni;
        int idx = 0;
        bool uj = false;
@@ -3453,8 +3465,8 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
 
        uj = use_json(argc, argv);
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def)
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn)
                return CMD_WARNING;
 
        if (!argv_find(argv, argc, "evpn", &idx))
@@ -3465,7 +3477,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
 
        if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
 
-               num_l2vnis = hashcount(bgp_def->vnihash);
+               num_l2vnis = hashcount(bgp_evpn->vnihash);
 
                for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
                        if (bgp_temp->l3vni)
@@ -3474,7 +3486,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
                num_vnis = num_l2vnis + num_l3vnis;
                if (uj) {
                        json_object_string_add(json, "advertiseGatewayMacip",
-                                              bgp_def->advertise_gw_macip
+                                              bgp_evpn->advertise_gw_macip
                                                       ? "Enabled"
                                                       : "Disabled");
                        json_object_string_add(json, "advertiseAllVnis",
@@ -3482,7 +3494,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
                                                                 : "Disabled");
                        json_object_string_add(
                                json, "flooding",
-                               bgp_def->vxlan_flood_ctrl
+                               bgp_evpn->vxlan_flood_ctrl
                                                == VXLAN_FLOOD_HEAD_END_REPL
                                        ? "Head-end replication"
                                        : "Disabled");
@@ -3491,22 +3503,22 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
                        json_object_int_add(json, "numL3Vnis", num_l3vnis);
                } else {
                        vty_out(vty, "Advertise Gateway Macip: %s\n",
-                               bgp_def->advertise_gw_macip ? "Enabled"
+                               bgp_evpn->advertise_gw_macip ? "Enabled"
                                                            : "Disabled");
                        vty_out(vty, "Advertise SVI Macip: %s\n",
-                               bgp_def->evpn_info->advertise_svi_macip ? "Enabled"
+                               bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
                                                        : "Disabled");
                        vty_out(vty, "Advertise All VNI flag: %s\n",
                                is_evpn_enabled() ? "Enabled" : "Disabled");
                        vty_out(vty, "BUM flooding: %s\n",
-                               bgp_def->vxlan_flood_ctrl
+                               bgp_evpn->vxlan_flood_ctrl
                                                == VXLAN_FLOOD_HEAD_END_REPL
                                        ? "Head-end replication"
                                        : "Disabled");
                        vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
                        vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
                }
-               evpn_show_all_vnis(vty, bgp_def, json);
+               evpn_show_all_vnis(vty, bgp_evpn, json);
        } else {
                int vni_idx = 0;
 
@@ -3515,7 +3527,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
 
                /* Display specific VNI */
                vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
-               evpn_show_vni(vty, bgp_def, vni, json);
+               evpn_show_vni(vty, bgp_evpn, vni, json);
        }
 
        if (uj) {
@@ -3548,7 +3560,7 @@ DEFUN(show_bgp_l2vpn_evpn_es,
        memset(&esi, 0, sizeof(esi));
        uj = use_json(argc, argv);
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -3631,7 +3643,7 @@ DEFUN(show_bgp_l2vpn_evpn_route,
 
        uj = use_json(argc, argv);
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -3692,7 +3704,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd,
        bool uj = false;
        json_object *json = NULL;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -3768,7 +3780,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
        memset(&mac, 0, sizeof(struct ethaddr));
        memset(&ip, 0, sizeof(struct ipaddr));
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -3832,7 +3844,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_esi,
        json_object *json = NULL;
 
        memset(&esi, 0, sizeof(esi));
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -3885,7 +3897,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
        bool uj = false;
        json_object *json = NULL;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -3957,7 +3969,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
        bool uj = false;
        json_object *json = NULL;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -4025,7 +4037,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
        bool uj = false;
        json_object *json = NULL;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -4081,7 +4093,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
        bool uj = false;
        json_object *json = NULL;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -4127,18 +4139,18 @@ DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
       JSON_STR)
 {
        bool uj = false;
-       struct bgp *bgp_def = NULL;
+       struct bgp *bgp_evpn = NULL;
        json_object *json = NULL;
 
-       bgp_def = bgp_get_default();
-       if (!bgp_def)
+       bgp_evpn = bgp_get_evpn();
+       if (!bgp_evpn)
                return CMD_WARNING;
 
        uj = use_json(argc, argv);
        if (uj)
                json = json_object_new_object();
 
-       evpn_show_vrf_import_rts(vty, bgp_def, json);
+       evpn_show_vrf_import_rts(vty, bgp_evpn, json);
 
        if (uj) {
                vty_out(vty, "%s\n", json_object_to_json_string_ext(
@@ -4166,7 +4178,7 @@ DEFUN(show_bgp_l2vpn_evpn_import_rt,
        bool uj = false;
        json_object *json = NULL;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp)
                return CMD_WARNING;
 
@@ -4197,9 +4209,9 @@ DEFUN(test_adv_evpn_type4_route,
        struct bgp *bgp;
        struct ipaddr vtep_ip;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp) {
-               vty_out(vty, "%%Default BGP instance not yet created\n");
+               vty_out(vty, "%%EVPN BGP instance not yet created\n");
                return CMD_WARNING;
        }
 
@@ -4231,9 +4243,9 @@ DEFUN(test_withdraw_evpn_type4_route,
        struct bgp *bgp;
        struct ipaddr vtep_ip;
 
-       bgp = bgp_get_default();
+       bgp = bgp_get_evpn();
        if (!bgp) {
-               vty_out(vty, "%%Default BGP instance not yet created\n");
+               vty_out(vty, "%%EVPN BGP instance not yet created\n");
                return CMD_WARNING;
        }
 
@@ -4511,9 +4523,9 @@ DEFUN (bgp_evpn_vni_rd,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -4547,9 +4559,9 @@ DEFUN (no_bgp_evpn_vni_rd,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -4587,9 +4599,9 @@ DEFUN (no_bgp_evpn_vni_rd_without_val,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -4916,9 +4928,9 @@ DEFUN (bgp_evpn_vni_rt,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -4984,9 +4996,9 @@ DEFUN (no_bgp_evpn_vni_rt,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -5083,9 +5095,9 @@ DEFUN (no_bgp_evpn_vni_rt_without_val,
        if (!bgp)
                return CMD_WARNING;
 
-       if (bgp->vrf_id != VRF_DEFAULT) {
+       if (!EVPN_ENABLED(bgp)) {
                vty_out(vty,
-                       "This command is only supported under Default VRF\n");
+                       "This command is only supported under EVPN VRF\n");
                return CMD_WARNING;
        }
 
@@ -5211,7 +5223,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
                vty_out(vty, "  default-originate ipv6\n");
 
        if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
-               vty_out(vty, "   rd %s\n",
+               vty_out(vty, "  rd %s\n",
                        prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
 
        /* import route-target */
index 1ccb8fb245191b77699da7f8d38590a0bbc98639..80cfb97436e2402176802de305790739d633bd7b 100644 (file)
@@ -95,8 +95,7 @@ static void as_filter_free(struct as_filter *asfilter)
 {
        if (asfilter->reg)
                bgp_regex_free(asfilter->reg);
-       if (asfilter->reg_str)
-               XFREE(MTYPE_AS_FILTER_STR, asfilter->reg_str);
+       XFREE(MTYPE_AS_FILTER_STR, asfilter->reg_str);
        XFREE(MTYPE_AS_FILTER, asfilter);
 }
 
@@ -338,8 +337,7 @@ static void as_list_filter_delete(struct as_list *aslist,
        /* Run hook function. */
        if (as_list_master.delete_hook)
                (*as_list_master.delete_hook)(name);
-       if (name)
-               XFREE(MTYPE_AS_STR, name);
+       XFREE(MTYPE_AS_STR, name);
 }
 
 static int as_filter_match(struct as_filter *asfilter, struct aspath *aspath)
index b70c8bbd631cb88b2cf55b12838185ade095d858..447d8da613722bd17eb00d61694b61707f6c7fb3 100644 (file)
@@ -310,7 +310,8 @@ void bgp_timer_set(struct peer *peer)
                   status start timer is on unless peer is shutdown or peer is
                   inactive.  All other timer must be turned off */
                if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)
-                   || peer->bgp->vrf_id == VRF_UNKNOWN) {
+                   || (peer->bgp->inst_type != BGP_INSTANCE_TYPE_VIEW &&
+                       peer->bgp->vrf_id == VRF_UNKNOWN)) {
                        BGP_TIMER_OFF(peer->t_start);
                } else {
                        BGP_TIMER_ON(peer->t_start, bgp_start_timer,
@@ -1422,7 +1423,8 @@ int bgp_start(struct peer *peer)
                return 0;
        }
 
-       if (peer->bgp->vrf_id == VRF_UNKNOWN) {
+       if (peer->bgp->inst_type != BGP_INSTANCE_TYPE_VIEW &&
+           peer->bgp->vrf_id == VRF_UNKNOWN) {
                if (bgp_debug_neighbor_events(peer))
                        flog_err(
                                EC_BGP_FSM,
index 181f864575a6916ee66f689ff85df43e20d9658f..69dd0f9daca6214d3302853e9415e93d4d6b264b 100644 (file)
@@ -180,14 +180,12 @@ static void lp_cbq_item_free(struct work_queue *wq, void *data)
 
 static void lp_lcb_free(void *goner)
 {
-       if (goner)
-               XFREE(MTYPE_BGP_LABEL_CB, goner);
+       XFREE(MTYPE_BGP_LABEL_CB, goner);
 }
 
 static void lp_chunk_free(void *goner)
 {
-       if (goner)
-               XFREE(MTYPE_BGP_LABEL_CHUNK, goner);
+       XFREE(MTYPE_BGP_LABEL_CHUNK, goner);
 }
 
 void bgp_lp_init(struct thread_master *master, struct labelpool *pool)
index 1e458971926080e27238ffcc6dfd97bc3694ca40..44766c9b6e30700bf4718ea9860b6202ce16fb02 100644 (file)
@@ -38,17 +38,14 @@ static struct hash *lcomhash;
 /* Allocate a new lcommunities.  */
 static struct lcommunity *lcommunity_new(void)
 {
-       return (struct lcommunity *)XCALLOC(MTYPE_LCOMMUNITY,
-                                           sizeof(struct lcommunity));
+       return XCALLOC(MTYPE_LCOMMUNITY, sizeof(struct lcommunity));
 }
 
 /* Allocate lcommunities.  */
 void lcommunity_free(struct lcommunity **lcom)
 {
-       if ((*lcom)->val)
-               XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
-       if ((*lcom)->str)
-               XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
+       XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
+       XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
        XFREE(MTYPE_LCOMMUNITY, *lcom);
 }
 
@@ -180,7 +177,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
 {
        int i;
        int len;
-       bool first = 1;
+       bool first = true;
        char *str_buf;
        char *str_pnt;
        uint8_t *pnt;
@@ -218,7 +215,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
 
        for (i = 0; i < lcom->size; i++) {
                if (first)
-                       first = 0;
+                       first = false;
                else
                        *str_pnt++ = ' ';
 
@@ -319,10 +316,10 @@ bool lcommunity_cmp(const void *arg1, const void *arg2)
        const struct lcommunity *lcom2 = arg2;
 
        if (lcom1 == NULL && lcom2 == NULL)
-               return 1;
+               return true;
 
        if (lcom1 == NULL || lcom2 == NULL)
-               return 0;
+               return false;
 
        return (lcom1->size == lcom2->size
                && memcmp(lcom1->val, lcom2->val, lcom_length(lcom1)) == 0);
index 4a408df858052be4a26fb8b21c444267559d9828..49b585402090352723efee25f32948c72f0a6a10 100644 (file)
@@ -311,11 +311,35 @@ void bgp_mac_del_mac_entry(struct interface *ifp)
        bgp_mac_remove_ifp_internal(bsm, ifp->name);
 }
 
-bool bgp_mac_entry_exists(struct prefix *p)
+/* This API checks MAC address against any of local
+ * assigned (SVIs) MAC address.
+ * An example: router-mac attribute in any of evpn update
+ * requires to compare against local mac.
+ */
+bool bgp_mac_exist(struct ethaddr *mac)
 {
-       struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
        struct bgp_self_mac lookup;
        struct bgp_self_mac *bsm;
+       static uint8_t tmp [ETHER_ADDR_STRLEN] = {0};
+
+       if (memcmp(mac, &tmp, ETH_ALEN) == 0)
+               return false;
+
+       memcpy(&lookup.macaddr, mac, ETH_ALEN);
+       bsm = hash_lookup(bm->self_mac_hash, &lookup);
+       if (!bsm)
+               return false;
+
+       return true;
+}
+
+/* This API checks EVPN type-2 prefix and comapares
+ * mac against any of local assigned (SVIs) MAC
+ * address.
+ */
+bool bgp_mac_entry_exists(struct prefix *p)
+{
+       struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
 
        if (pevpn->family != AF_EVPN)
                return false;
@@ -323,10 +347,7 @@ bool bgp_mac_entry_exists(struct prefix *p)
        if (pevpn->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
                return false;
 
-       memcpy(&lookup.macaddr, &p->u.prefix_evpn.macip_addr.mac, ETH_ALEN);
-       bsm = hash_lookup(bm->self_mac_hash, &lookup);
-       if (!bsm)
-               return false;
+       return bgp_mac_exist(&p->u.prefix_evpn.macip_addr.mac);
 
        return true;
 }
index 1dd987ef12c78fd5be929adadf5880144bdd57d3..68449b574ab3062e8cf84b5c2dd9b26617467fb4 100644 (file)
@@ -37,5 +37,6 @@ void bgp_mac_dump_table(struct vty *vty);
  * Function to lookup the prefix and see if we have a matching mac
  */
 bool bgp_mac_entry_exists(struct prefix *p);
+bool bgp_mac_exist(struct ethaddr *mac);
 
 #endif
index 47e7c1686fab5e97a7c4fd378de0799224d9b825..e42bc441154b935dd426b5e507c6e8c52995ce43 100644 (file)
@@ -171,7 +171,7 @@ void sigusr1(void)
 */
 static __attribute__((__noreturn__)) void bgp_exit(int status)
 {
-       struct bgp *bgp, *bgp_default;
+       struct bgp *bgp, *bgp_default, *bgp_evpn;
        struct listnode *node, *nnode;
 
        /* it only makes sense for this to be called on a clean exit */
@@ -184,13 +184,16 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
        bgp_close();
 
        bgp_default = bgp_get_default();
+       bgp_evpn = bgp_get_evpn();
 
        /* reverse bgp_master_init */
        for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
-               if (bgp_default == bgp)
+               if (bgp_default == bgp || bgp_evpn == bgp)
                        continue;
                bgp_delete(bgp);
        }
+       if (bgp_evpn && bgp_evpn != bgp_default)
+               bgp_delete(bgp_evpn);
        if (bgp_default)
                bgp_delete(bgp_default);
 
@@ -281,9 +284,9 @@ static int bgp_vrf_enable(struct vrf *vrf)
                bgp_vrf_link(bgp, vrf);
 
                bgp_handle_socket(bgp, vrf, old_vrf_id, true);
-               /* Update any redistribute vrf bitmaps if the vrf_id changed */
+               /* Update any redistribution if vrf_id changed */
                if (old_vrf_id != bgp->vrf_id)
-                       bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
+                       bgp_redistribute_redo(bgp);
                bgp_instance_up(bgp);
                vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
                vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
@@ -330,9 +333,9 @@ static int bgp_vrf_disable(struct vrf *vrf)
                /* We have instance configured, unlink from VRF and make it
                 * "down". */
                bgp_vrf_unlink(bgp, vrf);
-               /* Update any redistribute vrf bitmaps if the vrf_id changed */
+               /* Delete any redistribute vrf bitmaps if the vrf_id changed */
                if (old_vrf_id != bgp->vrf_id)
-                       bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
+                       bgp_unset_redist_vrf_bitmaps(bgp, old_vrf_id);
                bgp_instance_down(bgp);
        }
 
index 241146e4519f3b489b0fa0e1d29df40d74b84795..d5b3d6b1974da26a2da084f64d8680db03d223d4 100644 (file)
@@ -671,7 +671,7 @@ void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best)
 
        bgp_path_info_mpath_count_set(dmed_best, 0);
        UNSET_FLAG(dmed_best->flags, BGP_PATH_MULTIPATH_CHG);
-       assert(bgp_path_info_mpath_first(dmed_best) == 0);
+       assert(bgp_path_info_mpath_first(dmed_best) == NULL);
 }
 
 /*
index 765170d1a5f2e222a19541c85593bbfad1734756..4c4659ad543959f989200bedb8c757b68c99d140 100644 (file)
@@ -46,6 +46,7 @@
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_nexthop.h"
 #include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_evpn.h"
 
 #if ENABLE_BGP_VNC
 #include "bgpd/rfapi/rfapi_backend.h"
@@ -552,8 +553,12 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
                if (bpi->extra && bpi->extra->bgp_orig)
                        bgp_nexthop = bpi->extra->bgp_orig;
 
-               /* No nexthop tracking for redistributed routes */
-               if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
+               /*
+                * No nexthop tracking for redistributed routes or for
+                * EVPN-imported routes that get leaked.
+                */
+               if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE ||
+                   is_pi_family_evpn(bpi_ultimate))
                        nh_valid = 1;
                else
                        /*
@@ -614,8 +619,11 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
         * No nexthop tracking for redistributed routes because
         * their originating protocols will do the tracking and
         * withdraw those routes if the nexthops become unreachable
+        * This also holds good for EVPN-imported routes that get
+        * leaked.
         */
-       if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE)
+       if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE ||
+           is_pi_family_evpn(bpi_ultimate))
                nh_valid = 1;
        else
                /*
@@ -683,11 +691,10 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn,            /* to */
                return;
        }
 
-       /* loop check - should not be an imported route. */
-       if (path_vrf->extra && path_vrf->extra->bgp_orig)
+       /* Is this route exportable into the VPN table? */
+       if (!is_route_injectable_into_vpn(path_vrf))
                return;
 
-
        if (!vpn_leak_to_vpn_active(bgp_vrf, afi, &debugmsg)) {
                if (debug)
                        zlog_debug("%s: %s skipping: %s", __func__,
@@ -894,15 +901,6 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn,               /* to */
                        path_vrf->type, path_vrf->sub_type);
        }
 
-       if (path_vrf->sub_type != BGP_ROUTE_NORMAL
-           && path_vrf->sub_type != BGP_ROUTE_STATIC
-           && path_vrf->sub_type != BGP_ROUTE_REDISTRIBUTE) {
-
-               if (debug)
-                       zlog_debug("%s: wrong sub_type %d", __func__,
-                                  path_vrf->sub_type);
-               return;
-       }
        if (!bgp_vpn)
                return;
 
@@ -912,6 +910,10 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn,               /* to */
                return;
        }
 
+       /* Is this route exportable into the VPN table? */
+       if (!is_route_injectable_into_vpn(path_vrf))
+               return;
+
        if (!vpn_leak_to_vpn_active(bgp_vrf, afi, &debugmsg)) {
                if (debug)
                        zlog_debug("%s: skipping: %s", __func__, debugmsg);
@@ -995,7 +997,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
                                    == bgp_vrf) {
                                        /* delete route */
                                        if (debug)
-                                               zlog_debug("%s: deleting it\n",
+                                               zlog_debug("%s: deleting it",
                                                           __func__);
                                        bgp_aggregate_decrement(bgp_vpn, &bn->p,
                                                                bpi, afi, safi);
@@ -1352,7 +1354,10 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, /* to */
 
                for (bpi = bgp_node_get_bgp_path_info(bn); bpi;
                     bpi = bpi->next) {
-                       if (bpi->extra && bpi->extra->bgp_orig != bgp_vrf) {
+                       if (bpi->extra
+                           && bpi->extra->bgp_orig != bgp_vrf
+                           && bpi->extra->parent
+                           && is_pi_family_vpn(bpi->extra->parent)) {
 
                                /* delete route */
                                bgp_aggregate_decrement(bgp_vrf, &bn->p, bpi,
@@ -1483,6 +1488,97 @@ static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name)
        }
 }
 
+/* This API is used during router-id change, reflect VPNs
+ * auto RD and RT values and readvertise routes to VPN table.
+ */
+void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw)
+{
+       afi_t afi;
+       int debug;
+       char *vname;
+       const char *export_name;
+       char buf[RD_ADDRSTRLEN];
+       struct bgp *bgp_import;
+       struct listnode *node;
+       struct ecommunity *ecom;
+       vpn_policy_direction_t idir, edir;
+
+       if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
+           && bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+               return;
+
+       export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
+       debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
+                    BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
+
+       idir = BGP_VPN_POLICY_DIR_FROMVPN;
+       edir = BGP_VPN_POLICY_DIR_TOVPN;
+
+       for (afi = 0; afi < AFI_MAX; ++afi) {
+               if (!vpn_leak_to_vpn_active(bgp, afi, NULL))
+                       continue;
+
+               if (withdraw) {
+                       vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
+                                          afi, bgp_get_default(), bgp);
+                       if (debug)
+                               zlog_debug("%s: %s after to_vpn vpn_leak_prechange",
+                                          __func__, export_name);
+
+                       /* Remove import RT from VRFs */
+                       ecom = bgp->vpn_policy[afi].rtlist[edir];
+                       for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].
+                                                 export_vrf, node, vname)) {
+                               bgp_import = bgp_lookup_by_name(vname);
+                               if (!bgp_import)
+                                       continue;
+
+                               ecommunity_del_val(bgp_import->vpn_policy[afi].
+                                                  rtlist[idir],
+                                       (struct ecommunity_val *)ecom->val);
+
+                       }
+               } else {
+                       /* New router-id derive auto RD and RT and export
+                        * to VPN
+                        */
+                       form_auto_rd(bgp->router_id, bgp->vrf_rd_id,
+                                    &bgp->vrf_prd_auto);
+                       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);
+
+                       /* Update import_vrf rt_list */
+                       ecom = bgp->vpn_policy[afi].rtlist[edir];
+                       for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].
+                                                 export_vrf, node, vname)) {
+                               bgp_import = bgp_lookup_by_name(vname);
+                               if (!bgp_import)
+                                       continue;
+                               if (bgp_import->vpn_policy[afi].rtlist[idir])
+                                       bgp_import->vpn_policy[afi].rtlist[idir]
+                                               = ecommunity_merge(
+                                               bgp_import->vpn_policy[afi]
+                                               .rtlist[idir], ecom);
+                               else
+                                       bgp_import->vpn_policy[afi].rtlist[idir]
+                                               = ecommunity_dup(ecom);
+
+                       }
+                       /* Update routes to VPN */
+                       vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
+                                           afi, bgp_get_default(),
+                                           bgp);
+                       if (debug)
+                               zlog_debug("%s: %s after to_vpn vpn_leak_postchange",
+                                          __func__, export_name);
+               }
+       }
+}
+
 void vpn_policy_routemap_event(const char *rmap_name)
 {
        int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT);
@@ -1508,11 +1604,15 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
        char buf[1000];
        struct ecommunity *ecom;
        bool first_export = false;
+       int debug;
 
        export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
        idir = BGP_VPN_POLICY_DIR_FROMVPN;
        edir = BGP_VPN_POLICY_DIR_TOVPN;
 
+       debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
+                    BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
+
        /*
         * Cross-ref both VRFs. Also, note if this is the first time
         * any VRF is importing from "import_vrf".
@@ -1555,6 +1655,23 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
                to_bgp->vpn_policy[afi].rtlist[idir] = ecommunity_dup(ecom);
        SET_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT);
 
+       if (debug) {
+               const char *from_name;
+
+               from_name = from_bgp->name ? from_bgp->name :
+                       VRF_DEFAULT_NAME;
+               zlog_debug("%s from %s to %s first_export %u import-rt %s export-rt %s",
+                          __func__, from_name, export_name, first_export,
+                          to_bgp->vpn_policy[afi].rtlist[idir] ?
+                          (ecommunity_ecom2str(to_bgp->vpn_policy[afi].
+                                               rtlist[idir],
+                                       ECOMMUNITY_FORMAT_ROUTE_MAP, 0)) : " ",
+                          to_bgp->vpn_policy[afi].rtlist[edir] ?
+                          (ecommunity_ecom2str(to_bgp->vpn_policy[afi].
+                                               rtlist[edir],
+                                       ECOMMUNITY_FORMAT_ROUTE_MAP, 0)) : " ");
+       }
+
        /* Does "import_vrf" first need to export its routes or that
         * is already done and we just need to import those routes
         * from the global table?
@@ -1573,12 +1690,16 @@ void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
        char *vname;
        struct ecommunity *ecom;
        struct listnode *node;
+       int debug;
 
        export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
        tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
        idir = BGP_VPN_POLICY_DIR_FROMVPN;
        edir = BGP_VPN_POLICY_DIR_TOVPN;
 
+       debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
+                    BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
+
        /* Were we importing from "import_vrf"? */
        for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf, node,
                                  vname)) {
@@ -1596,6 +1717,9 @@ void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
        if (!vname)
                return;
 
+       if (debug)
+               zlog_debug("%s from %s to %s", __func__, tmp_name, export_name);
+
        /* Remove "import_vrf" from our import list. */
        listnode_delete(to_bgp->vpn_policy[afi].import_vrf, vname);
        XFREE(MTYPE_TMP, vname);
index 5b989e1853fd81fe1475d35914c40b3e87defd62..1526a8111e27eeffbd23509675e0ab6b921f6115 100644 (file)
@@ -226,10 +226,44 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
        }
 }
 
+/* Flag if the route is injectable into VPN. This would be either a
+ * non-imported route or a non-VPN imported route.
+ */
+static inline bool is_route_injectable_into_vpn(struct bgp_path_info *pi)
+{
+       struct bgp_path_info *parent_pi;
+       struct bgp_table *table;
+       struct bgp_node *rn;
+
+       if (pi->sub_type != BGP_ROUTE_IMPORTED ||
+           !pi->extra ||
+           !pi->extra->parent)
+               return true;
+
+       parent_pi = (struct bgp_path_info *)pi->extra->parent;
+       rn = parent_pi->net;
+       if (!rn)
+               return true;
+       table = bgp_node_table(rn);
+       if (table &&
+           (table->afi == AFI_IP || table->afi == AFI_IP6) &&
+           table->safi == SAFI_MPLS_VPN)
+               return false;
+       return true;
+}
+
+/* Flag if the route path's family is VPN. */
+static inline bool is_pi_family_vpn(struct bgp_path_info *pi)
+{
+       return (is_pi_family_matching(pi, AFI_IP, SAFI_MPLS_VPN) ||
+               is_pi_family_matching(pi, AFI_IP6, SAFI_MPLS_VPN));
+}
+
 extern void vpn_policy_routemap_event(const char *rmap_name);
 
 extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);
 
 extern void vpn_leak_postchange_all(void);
+extern void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw);
 
 #endif /* _QUAGGA_BGP_MPLSVPN_H */
index 2b4ad22b9392441d4b8909c01fb751b85acd99db..6e85abc8dfc8f260f1883b14bba0ecaede288940 100644 (file)
@@ -243,8 +243,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
        if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW) {
                SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
                SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
-       } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
+       } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED) &&
+                  !is_default_host_route(&bnc->node->p))
                register_zebra_rnh(bnc, is_bgp_static_route);
+
        if (pi && pi->nexthop != bnc) {
                /* Unlink from existing nexthop cache, if any. This will also
                 * free
index 4c51db8e143d28fc308a9b4a35198a71c4868880..c0be36ed3f4ad3b9b7d8483bc275dc2ed1cfacbf 100644 (file)
@@ -333,7 +333,7 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
                                                 unary_operator, and_valmask,
                                                 or_valmask, list[i].value,
                                                 type_entry);
-                               if (ret == false)
+                               if (!ret)
                                        return ret;
                                continue;
                        }
@@ -441,7 +441,7 @@ static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
                                range->min_port = list[i].value;
                        exact_match = true;
                }
-               if (exact_match == true && i > 0)
+               if (exact_match && i > 0)
                        return false;
                if (list[i].compare_operator ==
                    (OPERATOR_COMPARE_GREATER_THAN +
@@ -545,7 +545,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
                                           "too complex. ignoring.");
                        return 0;
                } else if (api->match_icmp_type_num > 1 &&
-                          enumerate_icmp == false) {
+                          !enumerate_icmp) {
                        if (BGP_DEBUG(pbr, PBR))
                                zlog_debug("BGP: match icmp code is enumerate"
                                           ", and icmp type is not."
index 77f5aade5f0cad0f300c07549df2a478ff10e435..571139a49aba0224ecdb521db6d82dc7f0120bcf 100644 (file)
@@ -155,8 +155,7 @@ int str2prefix_rd(const char *str, struct prefix_rd *prd)
 out:
        if (s)
                stream_free(s);
-       if (half)
-               XFREE(MTYPE_TMP, half);
+       XFREE(MTYPE_TMP, half);
        return lret;
 }
 
index 666254a62010bed4fef15aa48930844843332caa..ad9d22a7a5d332e281b2cec675c8696410872938 100644 (file)
@@ -2476,8 +2476,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
 
        /* advertise/withdraw type-5 routes */
        if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
-               if (advertise_type5_routes(bgp, afi) && new_select &&
-                   (!new_select->extra || !new_select->extra->parent)) {
+               if (advertise_type5_routes(bgp, afi) &&
+                   new_select &&
+                   is_route_injectable_into_evpn(new_select)) {
 
                        /* apply the route-map */
                        if (bgp->adv_cmd_rmap[afi][safi].map) {
@@ -2500,8 +2501,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                                                               afi, safi);
 
                        }
-               } else if (advertise_type5_routes(bgp, afi) && old_select &&
-                        (!old_select->extra || !old_select->extra->parent))
+               } else if (advertise_type5_routes(bgp, afi) &&
+                          old_select &&
+                          is_route_injectable_into_evpn(old_select))
                        bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
        }
 
@@ -3094,7 +3096,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                goto filtered;
        }
 
-       if (bgp_mac_entry_exists(p)) {
+       if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
                reason = "self mac;";
                goto filtered;
        }
@@ -4468,12 +4470,10 @@ static struct bgp_static *bgp_static_new(void)
 
 static void bgp_static_free(struct bgp_static *bgp_static)
 {
-       if (bgp_static->rmap.name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
        route_map_counter_decrement(bgp_static->rmap.map);
 
-       if (bgp_static->eth_s_id)
-               XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
+       XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
        XFREE(MTYPE_BGP_STATIC, bgp_static);
 }
 
@@ -5033,9 +5033,8 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                        bgp_static->backdoor = backdoor;
 
                        if (rmap) {
-                               if (bgp_static->rmap.name)
-                                       XFREE(MTYPE_ROUTE_MAP_NAME,
-                                             bgp_static->rmap.name);
+                               XFREE(MTYPE_ROUTE_MAP_NAME,
+                                     bgp_static->rmap.name);
                                route_map_counter_decrement(
                                        bgp_static->rmap.map);
                                bgp_static->rmap.name =
@@ -5045,9 +5044,8 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                                route_map_counter_increment(
                                        bgp_static->rmap.map);
                        } else {
-                               if (bgp_static->rmap.name)
-                                       XFREE(MTYPE_ROUTE_MAP_NAME,
-                                             bgp_static->rmap.name);
+                               XFREE(MTYPE_ROUTE_MAP_NAME,
+                                     bgp_static->rmap.name);
                                route_map_counter_decrement(
                                        bgp_static->rmap.map);
                                bgp_static->rmap.name = NULL;
@@ -5065,9 +5063,8 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                        bgp_static->label_index = label_index;
 
                        if (rmap) {
-                               if (bgp_static->rmap.name)
-                                       XFREE(MTYPE_ROUTE_MAP_NAME,
-                                             bgp_static->rmap.name);
+                               XFREE(MTYPE_ROUTE_MAP_NAME,
+                                     bgp_static->rmap.name);
                                route_map_counter_decrement(
                                        bgp_static->rmap.map);
                                bgp_static->rmap.name =
@@ -5351,9 +5348,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                bgp_static->prd = prd;
 
                if (rmap_str) {
-                       if (bgp_static->rmap.name)
-                               XFREE(MTYPE_ROUTE_MAP_NAME,
-                                     bgp_static->rmap.name);
+                       XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
                        route_map_counter_decrement(bgp_static->rmap.map);
                        bgp_static->rmap.name =
                                XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
@@ -5460,15 +5455,13 @@ static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
 
        rmap = &bgp->table_map[afi][safi];
        if (rmap_name) {
-               if (rmap->name)
-                       XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+               XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
                route_map_counter_decrement(rmap->map);
                rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
                rmap->map = route_map_lookup_by_name(rmap_name);
                route_map_counter_increment(rmap->map);
        } else {
-               if (rmap->name)
-                       XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+               XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
                route_map_counter_decrement(rmap->map);
                rmap->name = NULL;
                rmap->map = NULL;
@@ -5487,8 +5480,7 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
        struct bgp_rmap *rmap;
 
        rmap = &bgp->table_map[afi][safi];
-       if (rmap->name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
        route_map_counter_decrement(rmap->map);
        rmap->name = NULL;
        rmap->map = NULL;
@@ -10233,40 +10225,20 @@ ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
 }
 #endif
 
-static int bgp_table_stats_walker(struct thread *t)
+static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
+                              struct bgp_table_stats *ts, unsigned int space)
 {
-       struct bgp_node *rn;
-       struct bgp_node *top;
-       struct bgp_table_stats *ts = THREAD_ARG(t);
-       unsigned int space = 0;
-
-       if (!(top = bgp_table_top(ts->table)))
-               return 0;
-
-       switch (top->p.family) {
-       case AF_INET:
-               space = IPV4_MAX_BITLEN;
-               break;
-       case AF_INET6:
-               space = IPV6_MAX_BITLEN;
-               break;
-       }
-
-       ts->counts[BGP_STATS_MAXBITLEN] = space;
-
-       for (rn = top; rn; rn = bgp_route_next(rn)) {
-               struct bgp_path_info *pi;
-               struct bgp_node *prn = bgp_node_parent_nolock(rn);
-               unsigned int pinum = 0;
+       struct bgp_node *prn = bgp_node_parent_nolock(rn);
+       struct bgp_path_info *pi;
 
-               if (rn == top)
-                       continue;
+       if (rn == top)
+               return;
 
-               if (!bgp_node_has_bgp_path_info_data(rn))
-                       continue;
+       if (!bgp_node_has_bgp_path_info_data(rn))
+               return;
 
-               ts->counts[BGP_STATS_PREFIXES]++;
-               ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
+       ts->counts[BGP_STATS_PREFIXES]++;
+       ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
 
 #if 0
       ts->counts[BGP_STATS_AVGPLEN]
@@ -10275,49 +10247,43 @@ static int bgp_table_stats_walker(struct thread *t)
                       rn->p.prefixlen);
 #endif
 
-               /* check if the prefix is included by any other announcements */
-               while (prn && !bgp_node_has_bgp_path_info_data(prn))
-                       prn = bgp_node_parent_nolock(prn);
+       /* check if the prefix is included by any other announcements */
+       while (prn && !bgp_node_has_bgp_path_info_data(prn))
+               prn = bgp_node_parent_nolock(prn);
 
-               if (prn == NULL || prn == top) {
-                       ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
-                       /* announced address space */
-                       if (space)
-                               ts->total_space +=
-                                       pow(2.0, space - rn->p.prefixlen);
-               } else if (bgp_node_has_bgp_path_info_data(prn))
-                       ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
+       if (prn == NULL || prn == top) {
+               ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
+               /* announced address space */
+               if (space)
+                       ts->total_space += pow(2.0, space - rn->p.prefixlen);
+       } else if (bgp_node_has_bgp_path_info_data(prn))
+               ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
 
-               for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
-                       pinum++;
-                       ts->counts[BGP_STATS_RIB]++;
-
-                       if (pi->attr
-                           && (CHECK_FLAG(pi->attr->flag,
-                                          ATTR_FLAG_BIT(
-                                                  BGP_ATTR_ATOMIC_AGGREGATE))))
-                               ts->counts[BGP_STATS_AGGREGATES]++;
-
-                       /* as-path stats */
-                       if (pi->attr && pi->attr->aspath) {
-                               unsigned int hops =
-                                       aspath_count_hops(pi->attr->aspath);
-                               unsigned int size =
-                                       aspath_size(pi->attr->aspath);
-                               as_t highest = aspath_highest(pi->attr->aspath);
-
-                               ts->counts[BGP_STATS_ASPATH_COUNT]++;
-
-                               if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
-                                       ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
-                                               hops;
-
-                               if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
-                                       ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
-                                               size;
-
-                               ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
-                               ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
+
+       for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
+               ts->counts[BGP_STATS_RIB]++;
+
+               if (pi->attr
+                   && (CHECK_FLAG(pi->attr->flag,
+                                  ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))))
+                       ts->counts[BGP_STATS_AGGREGATES]++;
+
+               /* as-path stats */
+               if (pi->attr && pi->attr->aspath) {
+                       unsigned int hops = aspath_count_hops(pi->attr->aspath);
+                       unsigned int size = aspath_size(pi->attr->aspath);
+                       as_t highest = aspath_highest(pi->attr->aspath);
+
+                       ts->counts[BGP_STATS_ASPATH_COUNT]++;
+
+                       if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
+                               ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
+
+                       if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
+                               ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
+
+                       ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
+                       ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
 #if 0
               ts->counts[BGP_STATS_ASPATH_AVGHOPS]
                 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
@@ -10328,12 +10294,52 @@ static int bgp_table_stats_walker(struct thread *t)
                               ts->counts[BGP_STATS_ASPATH_AVGSIZE],
                               size);
 #endif
-                               if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
-                                       ts->counts[BGP_STATS_ASN_HIGHEST] =
-                                               highest;
-                       }
+                       if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
+                               ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
                }
        }
+}
+
+static int bgp_table_stats_walker(struct thread *t)
+{
+       struct bgp_node *rn, *nrn;
+       struct bgp_node *top;
+       struct bgp_table_stats *ts = THREAD_ARG(t);
+       unsigned int space = 0;
+
+       if (!(top = bgp_table_top(ts->table)))
+               return 0;
+
+       switch (ts->table->afi) {
+       case AFI_IP:
+               space = IPV4_MAX_BITLEN;
+               break;
+       case AFI_IP6:
+               space = IPV6_MAX_BITLEN;
+               break;
+       default:
+               return 0;
+       }
+
+       ts->counts[BGP_STATS_MAXBITLEN] = space;
+
+       for (rn = top; rn; rn = bgp_route_next(rn)) {
+               if (ts->table->safi == SAFI_MPLS_VPN) {
+                       struct bgp_table *table;
+
+                       table = bgp_node_get_bgp_table_info(rn);
+                       if (!table)
+                               continue;
+
+                       top = bgp_table_top(table);
+                       for (nrn = bgp_table_top(table); nrn;
+                            nrn = bgp_route_next(nrn))
+                               bgp_table_stats_rn(nrn, top, ts, space);
+               } else {
+                       bgp_table_stats_rn(rn, top, ts, space);
+               }
+       }
+
        return 0;
 }
 
@@ -10782,7 +10788,11 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
                return;
        }
 
-       table = bgp->rib[afi][safi];
+       /* labeled-unicast routes live in the unicast table */
+       if (safi == SAFI_LABELED_UNICAST)
+               table = bgp->rib[afi][SAFI_UNICAST];
+       else
+               table = bgp->rib[afi][safi];
 
        output_count = filtered_count = 0;
        subgrp = peer_subgroup(peer, afi, safi);
@@ -11036,10 +11046,6 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
        if (use_json)
                json = json_object_new_object();
 
-       /* labeled-unicast routes live in the unicast table */
-       if (safi == SAFI_LABELED_UNICAST)
-               safi = SAFI_UNICAST;
-
        if (!peer || !peer->afc[afi][safi]) {
                if (use_json) {
                        json_object_string_add(
@@ -11461,8 +11467,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       if (bdistance->access_list)
-               XFREE(MTYPE_AS_LIST, bdistance->access_list);
+       XFREE(MTYPE_AS_LIST, bdistance->access_list);
        bgp_distance_free(bdistance);
 
        bgp_node_set_bgp_path_info(rn, NULL);
@@ -12049,10 +12054,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                                decode_label(&bgp_static->label), esi, buf2,
                                macrouter);
 
-                       if (macrouter)
-                               XFREE(MTYPE_TMP, macrouter);
-                       if (esi)
-                               XFREE(MTYPE_TMP, esi);
+                       XFREE(MTYPE_TMP, macrouter);
+                       XFREE(MTYPE_TMP, esi);
                }
        }
 }
index 04a3c85f2c3ca6f7d5d787f879c4170090d17e9c..fc5bf0c7558a03ff1c74af0712d63aca3df4039c 100644 (file)
@@ -409,6 +409,24 @@ static inline int bgp_fibupd_safi(safi_t safi)
        return 0;
 }
 
+/* Flag if the route path's family matches params. */
+static inline bool is_pi_family_matching(struct bgp_path_info *pi,
+                                        afi_t afi, safi_t safi)
+{
+       struct bgp_table *table;
+       struct bgp_node *rn;
+
+       rn = pi->net;
+       if (!rn)
+               return false;
+       table = bgp_node_table(rn);
+       if (table &&
+           table->afi == afi &&
+           table->safi == safi)
+               return true;
+       return false;
+}
+
 /* Prototypes. */
 extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
                           struct peer *peer, afi_t afi, safi_t safi);
index 17109281bc8b36ae61b6880ba40c629d26074126..c276f5ef7b87ba4dbbd31f26f712f7193d3fda3b 100644 (file)
@@ -197,8 +197,6 @@ static void *route_value_compile(const char *arg)
        }
 
        rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
-       if (!rv)
-               return NULL;
 
        rv->action = action;
        rv->variable = var;
@@ -324,8 +322,7 @@ static void route_match_peer_free(void *rule)
 {
        struct bgp_match_peer_compiled *pc = rule;
 
-       if (pc->interface)
-               XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
 
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
 }
@@ -837,8 +834,6 @@ static void *route_match_vni_compile(const char *arg)
        char *end = NULL;
 
        vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
-       if (!vni)
-               return NULL;
 
        *vni = strtoul(arg, &end, 10);
        if (*end != '\0') {
@@ -998,9 +993,6 @@ static void *route_match_local_pref_compile(const char *arg)
 
        local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
 
-       if (!local_pref)
-               return local_pref;
-
        *local_pref = tmpval;
        return local_pref;
 }
@@ -1555,8 +1547,7 @@ static void route_set_ip_nexthop_free(void *rule)
 {
        struct rmap_ip_nexthop_set *rins = rule;
 
-       if (rins->address)
-               XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
 
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
 }
@@ -2046,22 +2037,12 @@ static route_map_result_t route_set_lcommunity_delete(void *rule,
 static void *route_set_lcommunity_delete_compile(const char *arg)
 {
        struct rmap_community *rcom;
-       char *p;
-       char *str;
-       int len;
 
        rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
 
-       p = strchr(arg, ' ');
-       if (p) {
-               len = p - arg;
-               str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
-               memcpy(str, arg, len);
-       } else
-               str = NULL;
-
-       rcom->name = str;
+       rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
        rcom->name_hash = bgp_clist_hash_key(rcom->name);
+
        return rcom;
 }
 
@@ -2141,22 +2122,12 @@ static route_map_result_t route_set_community_delete(
 static void *route_set_community_delete_compile(const char *arg)
 {
        struct rmap_community *rcom;
-       char *p;
-       char *str;
-       int len;
 
        rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
 
-       p = strchr(arg, ' ');
-       if (p) {
-               len = p - arg;
-               str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
-               memcpy(str, arg, len);
-       } else
-               str = NULL;
-
-       rcom->name = str;
+       rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
        rcom->name_hash = bgp_clist_hash_key(rcom->name);
+
        return rcom;
 }
 
@@ -3105,10 +3076,8 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
                break;
        }
 
-       if (dep_name)
-               XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
-       if (rmap_name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+       XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
 
        return retval;
 }
@@ -3399,7 +3368,7 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                                "Processing route_map %s update on advertise type5 route command",
                                rmap_name);
 
-               if (route_update) {
+               if (route_update && advertise_type5_routes(bgp, afi)) {
                        bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
                        bgp_evpn_advertise_type5_routes(bgp, afi, safi);
                }
@@ -4351,17 +4320,10 @@ DEFUN (set_community_delete,
        "Delete matching communities\n")
 {
        int idx_comm_list = 2;
-       char *str;
-
-       str = XCALLOC(MTYPE_TMP,
-                     strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1);
-       strcpy(str, argv[idx_comm_list]->arg);
-       strcpy(str + strlen(argv[idx_comm_list]->arg), " delete");
 
        generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
-                       str);
+                       argv[idx_comm_list]->arg);
 
-       XFREE(MTYPE_TMP, str);
        return CMD_SUCCESS;
 }
 
@@ -4450,16 +4412,9 @@ DEFUN (set_lcommunity_delete,
        "Large Community-list name\n"
        "Delete matching large communities\n")
 {
-       char *str;
-
-       str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1);
-       strcpy(str, argv[2]->arg);
-       strcpy(str + strlen(argv[2]->arg), " delete");
-
        generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
-                       "large-comm-list", str);
+                       "large-comm-list", argv[2]->arg);
 
-       XFREE(MTYPE_TMP, str);
        return CMD_SUCCESS;
 }
 
index a38d78916c1837a7f69fbb40c73afdb670dc4336..c63d4f9ad2fcdc58eccd50aa3c033fc9a54bcdb3 100644 (file)
@@ -125,7 +125,7 @@ static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);
 static struct cache *find_cache(const uint8_t preference);
 static int add_tcp_cache(const char *host, const char *port,
                         const uint8_t preference);
-static void print_record(const struct pfx_record *record, void *data);
+static void print_record(const struct pfx_record *record, struct vty *vty);
 static int is_synchronized(void);
 static int is_running(void);
 static void route_match_free(void *rule);
@@ -271,17 +271,23 @@ static struct cache *find_cache(const uint8_t preference)
        return NULL;
 }
 
-static void print_record(const struct pfx_record *record, void *data)
+static void print_record(const struct pfx_record *record, struct vty *vty)
 {
        char ip[INET6_ADDRSTRLEN];
+
+       lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip));
+       vty_out(vty, "%-40s   %3u - %3u   %10u\n", ip, record->min_len,
+               record->max_len, record->asn);
+}
+
+static void print_record_cb(const struct pfx_record *record, void *data)
+{
        struct rpki_for_each_record_arg *arg = data;
        struct vty *vty = arg->vty;
 
        (*arg->prefix_amount)++;
 
-       lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip));
-       vty_out(vty, "%-40s   %3u - %3u   %10u\n", ip, record->min_len,
-               record->max_len, record->asn);
+       print_record(record, vty);
 }
 
 static struct rtr_mgr_group *get_groups(void)
@@ -663,10 +669,10 @@ static void print_prefix_table(struct vty *vty)
        vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS");
 
        arg.prefix_amount = &number_of_ipv4_prefixes;
-       pfx_table_for_each_ipv4_record(pfx_table, print_record, &arg);
+       pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
 
        arg.prefix_amount = &number_of_ipv6_prefixes;
-       pfx_table_for_each_ipv6_record(pfx_table, print_record, &arg);
+       pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
 
        vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
        vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
@@ -1179,6 +1185,58 @@ DEFUN (show_rpki_prefix_table,
        return CMD_SUCCESS;
 }
 
+DEFPY (show_rpki_prefix,
+       show_rpki_prefix_cmd,
+       "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
+       SHOW_STR
+       RPKI_OUTPUT_STRING
+       "Lookup IP prefix and optionally ASN in prefix table\n"
+       "IPv4 prefix\n"
+       "IPv6 prefix\n"
+       "AS Number\n")
+{
+
+       if (!is_synchronized()) {
+               vty_out(vty, "No Conection to RPKI cache server.\n");
+               return CMD_WARNING;
+       }
+
+       struct lrtr_ip_addr addr;
+       char addr_str[INET6_ADDRSTRLEN];
+       size_t addr_len = strchr(prefix_str, '/') - prefix_str;
+
+       memset(addr_str, 0, sizeof(addr_str));
+       memcpy(addr_str, prefix_str, addr_len);
+
+       if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
+               vty_out(vty, "Invalid IP prefix\n");
+               return CMD_WARNING;
+       }
+
+       struct pfx_record *matches = NULL;
+       unsigned int match_count = 0;
+       enum pfxv_state result;
+
+       if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
+                                asn, &addr, prefix->prefixlen, &result)
+           != PFX_SUCCESS) {
+               vty_out(vty, "Prefix lookup failed");
+               return CMD_WARNING;
+       }
+
+       vty_out(vty, "%-40s %s  %s\n", "Prefix", "Prefix Length", "Origin-AS");
+       for (size_t i = 0; i < match_count; ++i) {
+               const struct pfx_record *record = &matches[i];
+
+               if (record->max_len >= prefix->prefixlen
+                   && ((asn != 0 && asn == record->asn) || asn == 0)) {
+                       print_record(&matches[i], vty);
+               }
+       }
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (show_rpki_cache_server,
        show_rpki_cache_server_cmd,
        "show rpki cache-server",
@@ -1414,7 +1472,7 @@ static void install_cli_commands(void)
        install_default(RPKI_NODE);
        overwrite_exit_commands();
        install_element(CONFIG_NODE, &rpki_cmd);
-       install_element(VIEW_NODE, &rpki_cmd);
+       install_element(ENABLE_NODE, &rpki_cmd);
 
        install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
        install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
@@ -1447,9 +1505,10 @@ static void install_cli_commands(void)
        install_element(RPKI_NODE, &no_rpki_cache_cmd);
 
        /* Install show commands */
-       install_element(ENABLE_NODE, &show_rpki_prefix_table_cmd);
-       install_element(ENABLE_NODE, &show_rpki_cache_connection_cmd);
-       install_element(ENABLE_NODE, &show_rpki_cache_server_cmd);
+       install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
+       install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
+       install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
+       install_element(VIEW_NODE, &show_rpki_prefix_cmd);
 
        /* Install debug commands */
        install_element(CONFIG_NODE, &debug_rpki_cmd);
index c1321dd7dc106d84ec18e45a31d721ba7511cf0e..44cbeabd699003f2752b178521ab8258a7808c50 100644 (file)
@@ -900,11 +900,10 @@ static int bgpTrapEstablished(struct peer *peer)
 
        oid_copy_addr(index, &addr, IN_ADDR_SIZE);
 
-       smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable),
-                 bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid,
+       smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid,
+                 array_size(bgp_trap_oid), bgp_oid,
                  sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE,
-                 bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object),
-                 BGPESTABLISHED);
+                 bgpTrapList, array_size(bgpTrapList), BGPESTABLISHED);
        return 0;
 }
 
@@ -920,11 +919,10 @@ static int bgpTrapBackwardTransition(struct peer *peer)
 
        oid_copy_addr(index, &addr, IN_ADDR_SIZE);
 
-       smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable),
-                 bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid,
+       smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid,
+                 array_size(bgp_trap_oid), bgp_oid,
                  sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE,
-                 bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object),
-                 BGPBACKWARDTRANSITION);
+                 bgpTrapList, array_size(bgpTrapList), BGPBACKWARDTRANSITION);
        return 0;
 }
 
index b74dc33ea4d4e08423c663433c5d266bec7b499f..49a435120d57d9c4ade22b839a2b855432934b80 100644 (file)
@@ -110,8 +110,7 @@ static void sync_init(struct update_subgroup *subgrp)
 
 static void sync_delete(struct update_subgroup *subgrp)
 {
-       if (subgrp->sync)
-               XFREE(MTYPE_BGP_SYNCHRONISE, subgrp->sync);
+       XFREE(MTYPE_BGP_SYNCHRONISE, subgrp->sync);
        subgrp->sync = NULL;
        if (subgrp->hash)
                hash_free(subgrp->hash);
@@ -144,8 +143,7 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
        dst->v_routeadv = src->v_routeadv;
        dst->flags = src->flags;
        dst->af_flags[afi][safi] = src->af_flags[afi][safi];
-       if (dst->host)
-               XFREE(MTYPE_BGP_PEER_HOST, dst->host);
+       XFREE(MTYPE_BGP_PEER_HOST, dst->host);
 
        dst->host = XSTRDUP(MTYPE_BGP_PEER_HOST, src->host);
        dst->cap = src->cap;
@@ -208,27 +206,19 @@ static void conf_release(struct peer *src, afi_t afi, safi_t safi)
 
        srcfilter = &src->filter[afi][safi];
 
-       if (src->default_rmap[afi][safi].name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name);
 
-       if (srcfilter->dlist[FILTER_OUT].name)
-               XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->dlist[FILTER_OUT].name);
+       XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->dlist[FILTER_OUT].name);
 
-       if (srcfilter->plist[FILTER_OUT].name)
-               XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->plist[FILTER_OUT].name);
+       XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->plist[FILTER_OUT].name);
 
-       if (srcfilter->aslist[FILTER_OUT].name)
-               XFREE(MTYPE_BGP_FILTER_NAME,
-                     srcfilter->aslist[FILTER_OUT].name);
+       XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->aslist[FILTER_OUT].name);
 
-       if (srcfilter->map[RMAP_OUT].name)
-               XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->map[RMAP_OUT].name);
+       XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->map[RMAP_OUT].name);
 
-       if (srcfilter->usmap.name)
-               XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);
+       XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);
 
-       if (src->host)
-               XFREE(MTYPE_BGP_PEER_HOST, src->host);
+       XFREE(MTYPE_BGP_PEER_HOST, src->host);
        src->host = NULL;
 }
 
@@ -440,7 +430,7 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
                return false;
 
        if (pe1->addpath_type[afi][safi] != pe2->addpath_type[afi][safi])
-               return 0;
+               return false;
 
        if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS)
            != (pe2->cap & PEER_UPDGRP_CAP_FLAGS))
@@ -741,12 +731,10 @@ static void update_group_delete(struct update_group *updgrp)
        hash_release(updgrp->bgp->update_groups[updgrp->afid], updgrp);
        conf_release(updgrp->conf, updgrp->afi, updgrp->safi);
 
-       if (updgrp->conf->host)
-               XFREE(MTYPE_BGP_PEER_HOST, updgrp->conf->host);
+       XFREE(MTYPE_BGP_PEER_HOST, updgrp->conf->host);
        updgrp->conf->host = NULL;
 
-       if (updgrp->conf->ifname)
-               XFREE(MTYPE_BGP_PEER_IFNAME, updgrp->conf->ifname);
+       XFREE(MTYPE_BGP_PEER_IFNAME, updgrp->conf->ifname);
 
        XFREE(MTYPE_BGP_PEER, updgrp->conf);
        XFREE(MTYPE_BGP_UPDGRP, updgrp);
index cbbf8b230290bfc96baa3ffa95b4599d355f12dd..66e306cba23d4bad8c504066e2df6dc32e7912a7 100644 (file)
@@ -69,8 +69,7 @@ struct bpacket *bpacket_alloc(void)
 {
        struct bpacket *pkt;
 
-       pkt = (struct bpacket *)XCALLOC(MTYPE_BGP_PACKET,
-                                       sizeof(struct bpacket));
+       pkt = XCALLOC(MTYPE_BGP_PACKET, sizeof(struct bpacket));
 
        return pkt;
 }
index 93d22087bbc7009f4d22e14f93c53fb78ce11b8a..9004926dee5edb5dcf9cdd821365b9999cd16fd5 100644 (file)
@@ -771,19 +771,23 @@ static int bgp_clear_vty(struct vty *vty, const char *name, afi_t afi,
 /* clear soft inbound */
 static void bgp_clear_star_soft_in(struct vty *vty, const char *name)
 {
-       bgp_clear_vty(vty, name, AFI_IP, SAFI_UNICAST, clear_all,
-                     BGP_CLEAR_SOFT_IN, NULL);
-       bgp_clear_vty(vty, name, AFI_IP6, SAFI_UNICAST, clear_all,
-                     BGP_CLEAR_SOFT_IN, NULL);
+       afi_t afi;
+       safi_t safi;
+
+       FOREACH_AFI_SAFI (afi, safi)
+               bgp_clear_vty(vty, name, afi, safi, clear_all,
+                             BGP_CLEAR_SOFT_IN, NULL);
 }
 
 /* clear soft outbound */
 static void bgp_clear_star_soft_out(struct vty *vty, const char *name)
 {
-       bgp_clear_vty(vty, name, AFI_IP, SAFI_UNICAST, clear_all,
-                     BGP_CLEAR_SOFT_OUT, NULL);
-       bgp_clear_vty(vty, name, AFI_IP6, SAFI_UNICAST, clear_all,
-                     BGP_CLEAR_SOFT_OUT, NULL);
+       afi_t afi;
+       safi_t safi;
+
+       FOREACH_AFI_SAFI (afi, safi)
+               bgp_clear_vty(vty, name, afi, safi, clear_all,
+                             BGP_CLEAR_SOFT_OUT, NULL);
 }
 
 
@@ -2055,29 +2059,6 @@ DEFUN (no_bgp_graceful_restart_preserve_fw,
        return CMD_SUCCESS;
 }
 
-static void bgp_redistribute_redo(struct bgp *bgp)
-{
-       afi_t afi;
-       int i;
-       struct list *red_list;
-       struct listnode *node;
-       struct bgp_redist *red;
-
-       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
-               for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
-
-                       red_list = bgp->redist[afi][i];
-                       if (!red_list)
-                               continue;
-
-                       for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
-                               bgp_redistribute_resend(bgp, afi, i,
-                                                       red->instance);
-                       }
-               }
-       }
-}
-
 /* "bgp graceful-shutdown" configuration */
 DEFUN (bgp_graceful_shutdown,
        bgp_graceful_shutdown_cmd,
@@ -2841,18 +2822,23 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
                as = strtoul(as_str, NULL, 10);
        }
 
-       /* If peer is peer group, call proper function.  */
+       /* If peer is peer group or interface peer, call proper function. */
        ret = str2sockunion(peer_str, &su);
        if (ret < 0) {
-               /* Check for peer by interface */
+               struct peer *peer;
+
+               /* Check if existing interface peer */
+               peer = peer_lookup_by_conf_if(bgp, peer_str);
+
                ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, afi,
                                     safi);
-               if (ret < 0) {
+
+               /* if not interface peer, check peer-group settings */
+               if (ret < 0 && !peer) {
                        ret = peer_group_remote_as(bgp, peer_str, &as, as_type);
                        if (ret < 0) {
                                vty_out(vty,
-                                       "%% Create the peer-group or interface first or specify \"interface\" keyword\n");
-                               vty_out(vty, "%% if using an unnumbered interface neighbor\n");
+                                       "%% Create the peer-group or interface first\n");
                                return CMD_WARNING_CONFIG_FAILED;
                        }
                        return CMD_SUCCESS;
@@ -3251,7 +3237,7 @@ DEFUN (no_neighbor_interface_peer_group_remote_as,
        /* look up for neighbor by interface name config. */
        peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg);
        if (peer) {
-               peer_as_change(peer, 0, AS_SPECIFIED);
+               peer_as_change(peer, 0, AS_UNSPECIFIED);
                return CMD_SUCCESS;
        }
 
@@ -8031,7 +8017,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
                                        json, "ribMemory",
                                        ents * sizeof(struct bgp_node));
 
-                               ents = listcount(bgp->peer);
+                               ents = bgp->af_peer_count[afi][safi];
                                json_object_int_add(json, "peerCount", ents);
                                json_object_int_add(json, "peerMemory",
                                                    ents * sizeof(struct peer));
@@ -8071,7 +8057,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
                                                                   bgp_node)));
 
                                /* Peer related usage */
-                               ents = listcount(bgp->peer);
+                               ents = bgp->af_peer_count[afi][safi];
                                vty_out(vty, "Peers %ld, using %s of memory\n",
                                        ents,
                                        mtype_memstr(
@@ -8522,7 +8508,7 @@ const char *afi_safi_json(afi_t afi, safi_t safi)
 }
 
 /* Show BGP peer's information. */
-enum show_type { show_all, show_peer };
+enum show_type { show_all, show_peer, show_ipv4_all, show_ipv6_all, show_ipv4_peer, show_ipv6_peer };
 
 static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p,
                                      afi_t afi, safi_t safi,
@@ -10945,6 +10931,14 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
        struct peer *peer;
        int find = 0;
        bool nbr_output = false;
+       afi_t afi = AFI_MAX;
+       safi_t safi = SAFI_MAX;
+
+       if (type == show_ipv4_peer || type == show_ipv4_all) {
+               afi = AFI_IP;
+       } else if (type == show_ipv6_peer || type == show_ipv6_all) {
+               afi = AFI_IP6;
+       }
 
        for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
                if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
@@ -10973,17 +10967,54 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
                                }
                        }
                        break;
+               case show_ipv4_peer:
+               case show_ipv6_peer:
+                       FOREACH_SAFI (safi) {
+                               if (peer->afc[afi][safi]) {
+                                       if (conf_if) {
+                                               if ((peer->conf_if
+                                                    && !strcmp(peer->conf_if, conf_if))
+                                                   || (peer->hostname
+                                                       && !strcmp(peer->hostname, conf_if))) {
+                                                       find = 1;
+                                                       bgp_show_peer(vty, peer, use_json,
+                                                                     json);
+                                                       break;
+                                               }
+                                       } else {
+                                               if (sockunion_same(&peer->su, su)) {
+                                                       find = 1;
+                                                       bgp_show_peer(vty, peer, use_json,
+                                                                     json);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+               case show_ipv4_all:
+               case show_ipv6_all:
+                       FOREACH_SAFI (safi) {
+                               if (peer->afc[afi][safi]) {
+                                       bgp_show_peer(vty, peer, use_json, json);
+                                       nbr_output = true;
+                                       break;
+                               }
+                       }
+                       break;
                }
        }
 
-       if (type == show_peer && !find) {
+       if ((type == show_peer || type == show_ipv4_peer ||
+            type == show_ipv6_peer) && !find) {
                if (use_json)
                        json_object_boolean_true_add(json, "bgpNoSuchNeighbor");
                else
                        vty_out(vty, "%% No such neighbor in this view/vrf\n");
        }
 
-       if (type != show_peer && !nbr_output && !use_json)
+       if (type != show_peer && type != show_ipv4_peer &&
+           type != show_ipv6_peer && !nbr_output && !use_json)
                vty_out(vty, "%% No BGP neighbors found\n");
 
        if (use_json) {
@@ -11049,7 +11080,8 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
                                        : bgp->name);
                }
 
-               if (type == show_peer) {
+               if (type == show_peer || type == show_ipv4_peer ||
+                   type == show_ipv6_peer) {
                        ret = str2sockunion(ip_str, &su);
                        if (ret < 0)
                                bgp_show_neighbor(vty, bgp, type, NULL, ip_str,
@@ -11058,7 +11090,7 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
                                bgp_show_neighbor(vty, bgp, type, &su, NULL,
                                                  use_json, json);
                } else {
-                       bgp_show_neighbor(vty, bgp, show_all, NULL, NULL,
+                       bgp_show_neighbor(vty, bgp, type, NULL, NULL,
                                          use_json, json);
                }
                json_object_free(json);
@@ -11151,6 +11183,7 @@ DEFUN (show_ip_bgp_neighbors,
        char *vrf = NULL;
        char *sh_arg = NULL;
        enum show_type sh_type;
+       afi_t afi = AFI_MAX;
 
        bool uj = use_json(argc, argv);
 
@@ -11166,13 +11199,29 @@ DEFUN (show_ip_bgp_neighbors,
                vrf = argv[idx + 1]->arg;
 
        idx++;
+
+       if (argv_find(argv, argc, "ipv4", &idx)) {
+               sh_type = show_ipv4_all;
+               afi = AFI_IP;
+       } else if (argv_find(argv, argc, "ipv6", &idx)) {
+               sh_type = show_ipv6_all;
+               afi = AFI_IP6;
+       } else {
+               sh_type = show_all;
+       }
+
        if (argv_find(argv, argc, "A.B.C.D", &idx)
            || argv_find(argv, argc, "X:X::X:X", &idx)
            || argv_find(argv, argc, "WORD", &idx)) {
                sh_type = show_peer;
                sh_arg = argv[idx]->arg;
-       } else
-               sh_type = show_all;
+       }
+
+       if (sh_type == show_peer && afi == AFI_IP) {
+               sh_type = show_ipv4_peer;
+       } else if (sh_type == show_peer && afi == AFI_IP6) {
+               sh_type = show_ipv6_peer;
+       }
 
        return bgp_show_neighbor_vty(vty, vrf, sh_type, sh_arg, uj);
 }
@@ -11267,8 +11316,9 @@ DEFUN (show_ip_bgp_attr_info,
        return CMD_SUCCESS;
 }
 
-static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
-                                  safi_t safi, bool use_json)
+static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
+                                  afi_t afi, safi_t safi,
+                                  bool use_json, json_object *json)
 {
        struct bgp *bgp;
        struct listnode *node;
@@ -11277,13 +11327,10 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
        char *ecom_str;
        vpn_policy_direction_t dir;
 
-       if (use_json) {
-               json_object *json = NULL;
+       if (json) {
                json_object *json_import_vrfs = NULL;
                json_object *json_export_vrfs = NULL;
 
-               json = json_object_new_object();
-
                bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
 
                if (!bgp) {
@@ -11354,11 +11401,12 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
                        XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
                }
 
-               vty_out(vty, "%s\n",
-                       json_object_to_json_string_ext(json,
+               if (use_json) {
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string_ext(json,
                                                      JSON_C_TO_STRING_PRETTY));
-               json_object_free(json);
-
+                       json_object_free(json);
+               }
        } else {
                bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
 
@@ -11422,6 +11470,54 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
        return CMD_SUCCESS;
 }
 
+static int bgp_show_all_instance_route_leak_vty(struct vty *vty, afi_t afi,
+                                               safi_t safi, bool use_json)
+{
+       struct listnode *node, *nnode;
+       struct bgp *bgp;
+       char *vrf_name = NULL;
+       json_object *json = NULL;
+       json_object *json_vrf = NULL;
+       json_object *json_vrfs = NULL;
+
+       if (use_json) {
+               json = json_object_new_object();
+               json_vrfs = json_object_new_object();
+       }
+
+       for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+
+               if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)
+                       vrf_name = bgp->name;
+
+               if (use_json) {
+                       json_vrf = json_object_new_object();
+               } else {
+                       vty_out(vty, "\nInstance %s:\n",
+                               (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+                               ? VRF_DEFAULT_NAME : bgp->name);
+               }
+               bgp_show_route_leak_vty(vty, vrf_name, afi, safi, 0, json_vrf);
+               if (use_json) {
+                       if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+                               json_object_object_add(json_vrfs,
+                                               VRF_DEFAULT_NAME, json_vrf);
+                       else
+                               json_object_object_add(json_vrfs, vrf_name,
+                                                      json_vrf);
+               }
+       }
+
+       if (use_json) {
+               json_object_object_add(json, "vrfs", json_vrfs);
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(json,
+                                               JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
+       return CMD_SUCCESS;
+}
+
 /* "show [ip] bgp route-leak" command.  */
 DEFUN (show_ip_bgp_route_leak,
        show_ip_bgp_route_leak_cmd,
@@ -11441,6 +11537,7 @@ DEFUN (show_ip_bgp_route_leak,
 
        bool uj = use_json(argc, argv);
        int idx = 0;
+       json_object *json = NULL;
 
        /* show [ip] bgp */
        if (argv_find(argv, argc, "ip", &idx)) {
@@ -11470,7 +11567,13 @@ DEFUN (show_ip_bgp_route_leak,
                return CMD_WARNING;
        }
 
-       return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj);
+       if (vrf && strmatch(vrf, "all"))
+               return bgp_show_all_instance_route_leak_vty(vty, afi, safi, uj);
+
+       if (uj)
+               json = json_object_new_object();
+
+       return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj, json);
 }
 
 static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
@@ -14456,8 +14559,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc,
 
        /* Free temporary community list string allocated by
           argv_concat().  */
-       if (str)
-               XFREE(MTYPE_TMP, str);
+       XFREE(MTYPE_TMP, str);
 
        if (ret < 0) {
                community_list_perror(vty, ret);
@@ -14508,8 +14610,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc,
 
        /* Free temporary community list string allocated by
           argv_concat().  */
-       if (str)
-               XFREE(MTYPE_TMP, str);
+       XFREE(MTYPE_TMP, str);
 
        if (ret < 0) {
                community_list_perror(vty, ret);
index f833ab89d71be5c8949adc896864f93356512d9d..66fcbb3f3afa9ed82a79b676985b45bcbb6d116e 100644 (file)
@@ -1586,8 +1586,7 @@ struct bgp_redist *bgp_redist_add(struct bgp *bgp, afi_t afi, uint8_t type,
                bgp->redist[afi][type] = list_new();
 
        red_list = bgp->redist[afi][type];
-       red = (struct bgp_redist *)XCALLOC(MTYPE_BGP_REDIST,
-                                          sizeof(struct bgp_redist));
+       red = XCALLOC(MTYPE_BGP_REDIST, sizeof(struct bgp_redist));
        red->instance = instance;
 
        listnode_add(red_list, red);
@@ -1633,8 +1632,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
                        return CMD_WARNING;
 
 #if ENABLE_BGP_VNC
-               if (bgp->vrf_id == VRF_DEFAULT
-                   && type == ZEBRA_ROUTE_VNC_DIRECT) {
+               if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) {
                        vnc_export_bgp_enable(
                                bgp, afi); /* only enables if mode bits cfg'd */
                }
@@ -1694,8 +1692,7 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
        if (red->rmap.name && (strcmp(red->rmap.name, name) == 0))
                return 0;
 
-       if (red->rmap.name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
        /* Decrement the count for existing routemap and
         * increment the count for new route map.
         */
@@ -1796,7 +1793,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
  * status. red lookup fails if there is no zebra connection.
  */
 #if ENABLE_BGP_VNC
-       if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) {
+       if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) {
                vnc_export_bgp_disable(bgp, afi);
        }
 #endif
@@ -1808,8 +1805,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
        bgp_redistribute_unreg(bgp, afi, type, instance);
 
        /* Unset route-map. */
-       if (red->rmap.name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
        route_map_counter_decrement(red->rmap.map);
        red->rmap.name = NULL;
        red->rmap.map = NULL;
@@ -1823,23 +1819,42 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
        return CMD_SUCCESS;
 }
 
-/* Update redistribute vrf bitmap during triggers like
-   restart networking or delete/add VRFs */
-void bgp_update_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id)
+void bgp_redistribute_redo(struct bgp *bgp)
+{
+       afi_t afi;
+       int i;
+       struct list *red_list;
+       struct listnode *node;
+       struct bgp_redist *red;
+
+       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+               for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+
+                       red_list = bgp->redist[afi][i];
+                       if (!red_list)
+                               continue;
+
+                       for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
+                               bgp_redistribute_resend(bgp, afi, i,
+                                                       red->instance);
+                       }
+               }
+       }
+}
+
+/* Unset redistribute vrf bitmap during triggers like
+   restart networking or delete VRFs */
+void bgp_unset_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id)
 {
        int i;
        afi_t afi;
 
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
-                       if ((old_vrf_id == VRF_UNKNOWN)
-                           || vrf_bitmap_check(zclient->redist[afi][i],
-                                               old_vrf_id)) {
+                       if (vrf_bitmap_check(zclient->redist[afi][i],
+                                            old_vrf_id))
                                vrf_bitmap_unset(zclient->redist[afi][i],
                                                 old_vrf_id);
-                               vrf_bitmap_set(zclient->redist[afi][i],
-                                              bgp->vrf_id);
-                       }
        return;
 }
 
@@ -1864,9 +1879,8 @@ void bgp_zebra_instance_register(struct bgp *bgp)
        /* Register for router-id, interfaces, redistributed routes. */
        zclient_send_reg_requests(zclient, bgp->vrf_id);
 
-       /* For default instance, register to learn about VNIs, if appropriate.
-        */
-       if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT && is_evpn_enabled())
+       /* For EVPN instance, register to learn about VNIs, if appropriate. */
+       if (bgp->advertise_all_vni)
                bgp_zebra_advertise_all_vni(bgp, 1);
 
        bgp_nht_register_nexthops(bgp);
@@ -1884,9 +1898,8 @@ void bgp_zebra_instance_deregister(struct bgp *bgp)
        if (BGP_DEBUG(zebra, ZEBRA))
                zlog_debug("Deregistering VRF %u", bgp->vrf_id);
 
-       /* For default instance, unregister learning about VNIs, if appropriate.
-        */
-       if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT && is_evpn_enabled())
+       /* For EVPN instance, unregister learning about VNIs, if appropriate. */
+       if (bgp->advertise_all_vni)
                bgp_zebra_advertise_all_vni(bgp, 0);
 
        /* Deregister for router-id, interfaces, redistributed routes. */
index fc19c5e17f5c6bd3ab1ecd79418b051cc42b18f6..b912870b80dbf94e0e5f58dd0f3d87c672b70c81 100644 (file)
@@ -49,6 +49,7 @@ extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer);
 extern void bgp_zebra_instance_register(struct bgp *);
 extern void bgp_zebra_instance_deregister(struct bgp *);
 
+extern void bgp_redistribute_redo(struct bgp *bgp);
 extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, uint8_t,
                                            unsigned short);
 extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
index a920cfeeec14524ad55789fb4028a18cd21a424c..225f1199081b517c0d418e5f830173664203a464 100644 (file)
@@ -116,7 +116,7 @@ static int bgp_check_main_socket(bool create, struct bgp *bgp)
 {
        static int bgp_server_main_created;
 
-       if (create == true) {
+       if (create) {
                if (bgp_server_main_created)
                        return 0;
                if (bgp_socket(bgp, bm->port, bm->address) < 0)
@@ -253,6 +253,8 @@ static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id)
        if (is_evpn_enabled())
                bgp_evpn_handle_router_id_update(bgp, TRUE);
 
+       vpn_handle_router_id_update(bgp, TRUE);
+
        IPV4_ADDR_COPY(&bgp->router_id, id);
 
        /* Set all peer's local identifier with this value. */
@@ -270,6 +272,8 @@ static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id)
        if (is_evpn_enabled())
                bgp_evpn_handle_router_id_update(bgp, FALSE);
 
+       vpn_handle_router_id_update(bgp, FALSE);
+
        return 0;
 }
 
@@ -707,6 +711,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
 {
        struct peer_af *af;
        int afid;
+       struct bgp *bgp;
 
        if (!peer)
                return NULL;
@@ -715,6 +720,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
        if (afid >= BGP_AF_MAX)
                return NULL;
 
+       bgp = peer->bgp;
        assert(peer->peer_af_array[afid] == NULL);
 
        /* Allocate new peer af */
@@ -725,6 +731,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
        af->safi = safi;
        af->afid = afid;
        af->peer = peer;
+       bgp->af_peer_count[afi][safi]++;
 
        return af;
 }
@@ -747,6 +754,7 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
 {
        struct peer_af *af;
        int afid;
+       struct bgp *bgp;
 
        if (!peer)
                return -1;
@@ -759,6 +767,7 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
        if (!af)
                return -1;
 
+       bgp = peer->bgp;
        bgp_stop_announce_route_timer(af);
 
        if (PAF_SUBGRP(af)) {
@@ -768,8 +777,12 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
                                   af->subgroup->id, peer->host);
        }
 
+
        update_subgroup_remove_peer(af->subgroup, af);
 
+       if (bgp->af_peer_count[afi][safi])
+               bgp->af_peer_count[afi][safi]--;
+
        peer->peer_af_array[afid] = NULL;
        XFREE(MTYPE_BGP_PEER_AF, af);
        return 0;
@@ -1099,8 +1112,7 @@ static void peer_free(struct peer *peer)
                peer->update_if = NULL;
        }
 
-       if (peer->notify.data)
-               XFREE(MTYPE_TMP, peer->notify.data);
+       XFREE(MTYPE_TMP, peer->notify.data);
        memset(&peer->notify, 0, sizeof(struct bgp_notify));
 
        if (peer->clear_node_queue)
@@ -1322,8 +1334,7 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
                peer_dst->update_source =
                        sockunion_dup(peer_src->update_source);
        } else if (peer_src->update_if) {
-               if (peer_dst->update_if)
-                       XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
+               XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
                if (peer_dst->update_source) {
                        sockunion_free(peer_dst->update_source);
                        peer_dst->update_source = NULL;
@@ -1333,8 +1344,7 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
        }
 
        if (peer_src->ifname) {
-               if (peer_dst->ifname)
-                       XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname);
+               XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname);
 
                peer_dst->ifname =
                        XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname);
@@ -1541,14 +1551,12 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
                        peer->su = *su;
                else
                        bgp_peer_conf_if_to_su_update(peer);
-               if (peer->host)
-                       XFREE(MTYPE_BGP_PEER_HOST, peer->host);
+               XFREE(MTYPE_BGP_PEER_HOST, peer->host);
                peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if);
        } else if (su) {
                peer->su = *su;
                sockunion2str(su, buf, SU_ADDRSTRLEN);
-               if (peer->host)
-                       XFREE(MTYPE_BGP_PEER_HOST, peer->host);
+               XFREE(MTYPE_BGP_PEER_HOST, peer->host);
                peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf);
        }
        peer->local_as = local_as;
@@ -2384,8 +2392,7 @@ static int peer_group_cmp(struct peer_group *g1, struct peer_group *g2)
 /* Peer group cofiguration. */
 static struct peer_group *peer_group_new(void)
 {
-       return (struct peer_group *)XCALLOC(MTYPE_PEER_GROUP,
-                                           sizeof(struct peer_group));
+       return XCALLOC(MTYPE_PEER_GROUP, sizeof(struct peer_group));
 }
 
 static void peer_group_free(struct peer_group *group)
@@ -2416,8 +2423,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
 
        group = peer_group_new();
        group->bgp = bgp;
-       if (group->name)
-               XFREE(MTYPE_PEER_GROUP_HOST, group->name);
+       XFREE(MTYPE_PEER_GROUP_HOST, group->name);
        group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name);
        group->peer = list_new();
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
@@ -2425,8 +2431,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
        group->conf = peer_new(bgp);
        if (!bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
                group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
-       if (group->conf->host)
-               XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
+       XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
        group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name);
        group->conf->group = group;
        group->conf->as = 0;
@@ -2722,7 +2727,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
                        peer->sort = group->conf->sort;
                }
 
-               if (!group->conf->as) {
+               if (!group->conf->as && peer_sort(peer)) {
                        if (peer_sort(group->conf) != BGP_PEER_INTERNAL
                            && peer_sort(group->conf) != peer_sort(peer)) {
                                if (as)
@@ -2880,14 +2885,19 @@ static struct bgp *bgp_create(as_t *as, const char *name,
                                   name, *as);
        }
 
+       /* Default the EVPN VRF to the default one */
+       if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !bgp_master.bgp_evpn) {
+               bgp_lock(bgp);
+               bm->bgp_evpn = bgp;
+       }
+
        bgp_lock(bgp);
        bgp->heuristic_coalesce = true;
        bgp->inst_type = inst_type;
        bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT
                                                               : VRF_UNKNOWN;
        bgp->peer_self = peer_new(bgp);
-       if (bgp->peer_self->host)
-               XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
+       XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
        bgp->peer_self->host =
                XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
        if (bgp->peer_self->hostname != NULL) {
@@ -3079,6 +3089,29 @@ struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
        return (vrf->info) ? (struct bgp *)vrf->info : NULL;
 }
 
+/* Sets the BGP instance where EVPN is enabled */
+void bgp_set_evpn(struct bgp *bgp)
+{
+       if (bm->bgp_evpn == bgp)
+               return;
+
+       /* First, release the reference count we hold on the instance */
+       if (bm->bgp_evpn)
+               bgp_unlock(bm->bgp_evpn);
+
+       bm->bgp_evpn = bgp;
+
+       /* Increase the reference count on this new VRF */
+       if (bm->bgp_evpn)
+               bgp_lock(bm->bgp_evpn);
+}
+
+/* Returns the BGP instance where EVPN is enabled, if any */
+struct bgp *bgp_get_evpn(void)
+{
+       return bm->bgp_evpn;
+}
+
 /* handle socket creation or deletion, if necessary
  * this is called for all new BGP instances
  */
@@ -3363,6 +3396,14 @@ int bgp_delete(struct bgp *bgp)
        if (vrf)
                bgp_vrf_unlink(bgp, vrf);
 
+       /* Update EVPN VRF pointer */
+       if (bm->bgp_evpn == bgp) {
+               if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+                       bgp_set_evpn(NULL);
+               else
+                       bgp_set_evpn(bgp_get_default());
+       }
+
        thread_master_free_unused(bm->master);
        bgp_unlock(bgp); /* initial reference */
 
@@ -3404,8 +3445,7 @@ void bgp_free(struct bgp *bgp)
                if (bgp->rib[afi][safi])
                        bgp_table_finish(&bgp->rib[afi][safi]);
                rmap = &bgp->table_map[afi][safi];
-               if (rmap->name)
-                       XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+               XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
        }
 
        bgp_scan_finish(bgp);
@@ -3435,10 +3475,8 @@ void bgp_free(struct bgp *bgp)
                        ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
        }
 
-       if (bgp->name)
-               XFREE(MTYPE_BGP, bgp->name);
-       if (bgp->name_pretty)
-               XFREE(MTYPE_BGP, bgp->name_pretty);
+       XFREE(MTYPE_BGP, bgp->name);
+       XFREE(MTYPE_BGP, bgp->name_pretty);
 
        XFREE(MTYPE_BGP, bgp);
 }
@@ -4368,8 +4406,7 @@ int peer_ebgp_multihop_unset(struct peer *peer)
 /* Neighbor description. */
 int peer_description_set(struct peer *peer, const char *desc)
 {
-       if (peer->desc)
-               XFREE(MTYPE_PEER_DESC, peer->desc);
+       XFREE(MTYPE_PEER_DESC, peer->desc);
 
        peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
 
@@ -4378,8 +4415,7 @@ int peer_description_set(struct peer *peer, const char *desc)
 
 int peer_description_unset(struct peer *peer)
 {
-       if (peer->desc)
-               XFREE(MTYPE_PEER_DESC, peer->desc);
+       XFREE(MTYPE_PEER_DESC, peer->desc);
 
        peer->desc = NULL;
 
@@ -5125,15 +5161,13 @@ int peer_advertise_interval_unset(struct peer *peer)
 /* neighbor interface */
 void peer_interface_set(struct peer *peer, const char *str)
 {
-       if (peer->ifname)
-               XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
+       XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
        peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
 }
 
 void peer_interface_unset(struct peer *peer)
 {
-       if (peer->ifname)
-               XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
+       XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
        peer->ifname = NULL;
 }
 
index c7d137c76c169bc8acddfd781a3293b29ab2f99c..b0f65675342d3d82896ea87f1bded9833e443592 100644 (file)
@@ -99,6 +99,9 @@ enum bgp_af_index {
        for (afi = AFI_IP; afi < AFI_MAX; afi++)                               \
                for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
 
+#define FOREACH_SAFI(safi)                                            \
+       for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+
 extern struct frr_pthread *bgp_pth_io;
 extern struct frr_pthread *bgp_pth_ka;
 
@@ -150,6 +153,9 @@ struct bgp_master {
        /* dynamic mpls label allocation pool */
        struct labelpool labelpool;
 
+       /* BGP-EVPN VRF ID. Defaults to default VRF (if any) */
+       struct bgp* bgp_evpn;
+
        bool terminating;       /* global flag that sigint terminate seen */
        QOBJ_FIELDS
 };
@@ -374,6 +380,9 @@ struct bgp {
 #define BGP_CONFIG_VRF_TO_VRF_IMPORT                   (1 << 7)
 #define BGP_CONFIG_VRF_TO_VRF_EXPORT                   (1 << 8)
 
+       /* BGP per AF peer count */
+       uint32_t af_peer_count[AFI_MAX][SAFI_MAX];
+
        /* Route table for next-hop lookup cache. */
        struct bgp_table *nexthop_cache_table[AFI_MAX];
 
@@ -1506,6 +1515,8 @@ extern struct bgp *bgp_get_default(void);
 extern struct bgp *bgp_lookup(as_t, const char *);
 extern struct bgp *bgp_lookup_by_name(const char *);
 extern struct bgp *bgp_lookup_by_vrf_id(vrf_id_t);
+extern struct bgp *bgp_get_evpn(void);
+extern void bgp_set_evpn(struct bgp *bgp);
 extern struct peer *peer_lookup(struct bgp *, union sockunion *);
 extern struct peer *peer_lookup_by_conf_if(struct bgp *, const char *);
 extern struct peer *peer_lookup_by_hostname(struct bgp *, const char *);
@@ -1901,7 +1912,7 @@ static inline void bgp_vrf_unlink(struct bgp *bgp, struct vrf *vrf)
        bgp->vrf_id = VRF_UNKNOWN;
 }
 
-extern void bgp_update_redist_vrf_bitmaps(struct bgp *, vrf_id_t);
+extern void bgp_unset_redist_vrf_bitmaps(struct bgp *, vrf_id_t);
 
 /* For benefit of rfapi */
 extern struct peer *peer_new(struct bgp *bgp);
index d621d58e48a7ef501fee9121128272a040f2ea0b..2220f0ed9abf4fd758c981288f6ac93b8ee61b35 100644 (file)
@@ -3457,8 +3457,7 @@ static void bgp_rfapi_delete_l2_group(struct vty *vty, /* NULL = no output */
                ecommunity_free(&rfg->rt_export_list);
        if (rfg->labels)
                list_delete(&rfg->labels);
-       if (rfg->rfp_cfg)
-               XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg);
+       XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg);
        listnode_delete(bgp->rfapi_cfg->l2_groups, rfg);
 
        rfapi_l2_group_del(rfg);
@@ -3815,8 +3814,7 @@ struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg)
        struct rfapi_cfg *h;
        afi_t afi;
 
-       h = (struct rfapi_cfg *)XCALLOC(MTYPE_RFAPI_CFG,
-                                       sizeof(struct rfapi_cfg));
+       h = XCALLOC(MTYPE_RFAPI_CFG, sizeof(struct rfapi_cfg));
        assert(h);
 
        h->nve_groups_sequential = list_new();
@@ -3878,8 +3876,7 @@ void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h)
                ecommunity_free(&h->default_rt_export_list);
        if (h->default_rt_import_list)
                ecommunity_free(&h->default_rt_import_list);
-       if (h->default_rfp_cfg)
-               XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg);
+       XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg);
        for (afi = AFI_IP; afi < AFI_MAX; afi++) {
                agg_table_finish(h->nve_groups_vn[afi]);
                agg_table_finish(h->nve_groups_un[afi]);
index df2d404f6987317c4c99b705b922e088778c3f08..93729c14763d831c0d419611452f896a6a7ffc09 100644 (file)
@@ -4285,7 +4285,7 @@ struct rfapi *bgp_rfapi_new(struct bgp *bgp)
 
        assert(bgp->rfapi_cfg == NULL);
 
-       h = (struct rfapi *)XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi));
+       h = XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi));
 
        for (afi = AFI_IP; afi < AFI_MAX; afi++) {
                h->un[afi] = agg_table_init();
index 2b08ea493cfcc94c1331bcd7fae29ee3209ab28d..7cac7ac7a16680036a4caf1a30dbf30fff02598c 100644 (file)
@@ -114,21 +114,6 @@ DEFUN (no_debug_bgp_vnc,
        return CMD_WARNING_CONFIG_FAILED;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN(no_debug_bgp_vnc,
-             undebug_bgp_vnc_cmd,
-            "undebug bgp vnc <rfapi-query|import-bi-attach|import-del-remote|verbose>",
-             "Undebug\n"
-             BGP_STR
-             VNC_STR
-             "rfapi query handling\n"
-             "import BI atachment\n"
-             "import delete remote routes\n"
-             "verbose logging\n")
-
-
 /***********************************************************************
  *     no debug bgp vnc all
  ***********************************************************************/
@@ -148,17 +133,6 @@ DEFUN (no_debug_bgp_vnc_all,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN (no_debug_bgp_vnc_all,
-              undebug_bgp_vnc_all_cmd,
-              "undebug all bgp vnc",
-              "Undebug\n"
-              "Disable all VNC debugging\n"
-              BGP_STR
-              VNC_STR)
-
 /***********************************************************************
  *     show/save
  ***********************************************************************/
@@ -190,7 +164,7 @@ static int bgp_vnc_config_write_debug(struct vty *vty)
        int write = 0;
        size_t i;
 
-       for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) {
+       for (i = 0; i < array_size(vncdebug); ++i) {
                if (conf_vnc_debug & vncdebug[i].bit) {
                        vty_out(vty, "debug bgp vnc %s\n", vncdebug[i].name);
                        write++;
@@ -210,11 +184,7 @@ void vnc_debug_init(void)
        install_element(CONFIG_NODE, &debug_bgp_vnc_cmd);
        install_element(ENABLE_NODE, &no_debug_bgp_vnc_cmd);
        install_element(CONFIG_NODE, &no_debug_bgp_vnc_cmd);
-       install_element(ENABLE_NODE, &undebug_bgp_vnc_cmd);
-       install_element(CONFIG_NODE, &undebug_bgp_vnc_cmd);
 
        install_element(ENABLE_NODE, &no_debug_bgp_vnc_all_cmd);
        install_element(CONFIG_NODE, &no_debug_bgp_vnc_all_cmd);
-       install_element(ENABLE_NODE, &undebug_bgp_vnc_all_cmd);
-       install_element(CONFIG_NODE, &undebug_bgp_vnc_all_cmd);
 }
index 98f719969c0cb1ff6b1e7c921199f1f38370a400..b08e922962252340d462af725e748eed15972609 100644 (file)
@@ -608,10 +608,8 @@ static void vnc_zebra_add_del_prefix(struct bgp *bgp,
                                            add);
        }
 
-       if (nhp_ary)
-               XFREE(MTYPE_TMP, nhp_ary);
-       if (nh_ary)
-               XFREE(MTYPE_TMP, nh_ary);
+       XFREE(MTYPE_TMP, nhp_ary);
+       XFREE(MTYPE_TMP, nh_ary);
 }
 
 void vnc_zebra_add_prefix(struct bgp *bgp,
@@ -789,10 +787,8 @@ static void vnc_zebra_add_del_group_afi(struct bgp *bgp,
                                }
                        }
                }
-               if (nhp_ary)
-                       XFREE(MTYPE_TMP, nhp_ary);
-               if (nh_ary)
-                       XFREE(MTYPE_TMP, nh_ary);
+               XFREE(MTYPE_TMP, nhp_ary);
+               XFREE(MTYPE_TMP, nh_ary);
        }
 }
 
index fcfc4bd2fbd37ad6aa002890b24fd0b68a8a0c0a..9ae196fcb19e5fa5f2ae5ac3032f088edcec19fc 100755 (executable)
@@ -765,7 +765,7 @@ AC_DEFINE_UNQUOTED([CONFIGFILE_MASK], [${enable_configfile_mask}], [Mask for con
 enable_logfile_mask=${enable_logfile_mask:-0600}
 AC_DEFINE_UNQUOTED([LOGFILE_MASK], [${enable_logfile_mask}], [Mask for log files])
 
-MPATH_NUM=1
+MPATH_NUM=16
 
 case "${enable_multipath}" in
   0)
index c57573cb9fe2ea7357ae5dbc1b933b7879f8d7a0..f1ec2ad3ea0d78db5c0855ed751e755cf18ad29f 100644 (file)
@@ -1,9 +1,10 @@
+.. _building-centos6:
+
 CentOS 6
 ========================================
 
-(As an alternative to this installation, you may prefer to create a FRR
-rpm package yourself and install that package instead. See instructions
-in redhat/README.rpm\_build.md on how to build a rpm package)
+This document describes installation from source. If you want to build an RPM,
+see :ref:`packaging-redhat`.
 
 Instructions are tested with ``CentOS 6.8`` on ``x86_64`` platform
 
@@ -24,7 +25,7 @@ CentOS 6 restrictions:
    PIMd is needed
 -  MPLS is not supported on ``CentOS 6``. MPLS requires Linux Kernel 4.5
    or higher (LDP can be built, but may have limited use without MPLS)
--  Zebra is unable to detect what bridge/vrf an interface is associcated
+-  Zebra is unable to detect what bridge/vrf an interface is associated
    with (IFLA\_INFO\_SLAVE\_KIND does not exist in the kernel headers,
    you can use a newer kernel + headers to get this functionality)
 -  frr\_reload.py will not work, as this requires Python 2.7, and CentOS
@@ -42,7 +43,7 @@ Add packages:
 
 .. code-block:: shell
 
-   sudo yum install git autoconf automake libtool make gawk \
+   sudo yum install git autoconf automake libtool make \
       readline-devel texinfo net-snmp-devel groff pkgconfig \
       json-c-devel pam-devel flex epel-release c-ares-devel
 
@@ -235,7 +236,7 @@ settings)::
    # Controls source route verification
    net.ipv4.conf.default.rp_filter = 0
 
-Load the modifed sysctl's on the system:
+Load the modified sysctl's on the system:
 
 .. code-block:: shell
 
index 8f82cd6c9ab6ab6b8acf6271065ea894fe1d6d66..ea3c44478c02d535f2f9affb63db3c6bf7262a11 100644 (file)
@@ -1,9 +1,8 @@
 CentOS 7
 ========================================
 
-(As an alternative to this installation, you may prefer to create a FRR
-rpm package yourself and install that package instead. See instructions
-in redhat/README.rpm\_build.md on how to build a rpm package)
+This document describes installation from source. If you want to build an RPM,
+see :ref:`packaging-redhat`.
 
 CentOS 7 restrictions:
 ----------------------
@@ -19,7 +18,7 @@ Add packages:
 
 ::
 
-    sudo yum install git autoconf automake libtool make gawk \
+    sudo yum install git autoconf automake libtool make \
       readline-devel texinfo net-snmp-devel groff pkgconfig \
       json-c-devel pam-devel bison flex pytest c-ares-devel \
       python-devel systemd-devel python-sphinx
@@ -127,7 +126,7 @@ following content:
     net.ipv4.conf.all.forwarding=1
     net.ipv6.conf.all.forwarding=1
 
-Load the modifed sysctl's on the system:
+Load the modified sysctl's on the system:
 
 ::
 
index d0f4182bae505f1a077acc6ba457e2b393f0023d..9c6e48a6f83cb2365e643eeb38d6859bf567bed5 100644 (file)
@@ -15,7 +15,7 @@ Add packages:
 
 ::
 
-   sudo apt-get install git autoconf automake libtool make gawk \
+   sudo apt-get install git autoconf automake libtool make \
       libreadline-dev texinfo libjson-c-dev pkg-config bison flex python-pip \
       libc-ares-dev python3-dev python3-sphinx build-essential libsystemd-dev
 
diff --git a/doc/developer/building-frr-for-fedora.rst b/doc/developer/building-frr-for-fedora.rst
new file mode 100644 (file)
index 0000000..204c185
--- /dev/null
@@ -0,0 +1,122 @@
+Fedora 24+
+==========
+
+This document describes installation from source. If you want to build an RPM,
+see :ref:`packaging-redhat`.
+
+These instructions have been tested on Fedora 24+.
+
+Installing Dependencies
+-----------------------
+
+.. code-block:: console
+
+   sudo dnf install git autoconf automake libtool make \
+     readline-devel texinfo net-snmp-devel groff pkgconfig json-c-devel \
+     pam-devel pytest bison flex c-ares-devel python3-devel python2-sphinx \
+     perl-core patch
+
+.. include:: building-libyang.rst
+
+Building & Installing FRR
+-------------------------
+
+Add FRR user and groups
+^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+   sudo groupadd -g 92 frr
+   sudo groupadd -r -g 85 frrvty
+   sudo useradd -u 92 -g 92 -M -r -G frrvty -s /sbin/nologin \
+     -c "FRR FRRouting suite" -d /var/run/frr frr
+
+Compile
+^^^^^^^
+
+.. include:: include-compile.rst
+
+Install FRR configuration files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+   sudo install -m 775 -o frr -g frr -d /var/log/frr
+   sudo install -m 775 -o frr -g frrvty -d /etc/frr
+   sudo install -m 640 -o frr -g frrvty tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/frr.conf /etc/frr/frr.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons /etc/frr/daemons
+
+Tweak sysctls
+^^^^^^^^^^^^^
+
+Some sysctls need to be changed in order to enable IPv4/IPv6 forwarding and
+MPLS (if supported by your platform). If your platform does not support MPLS,
+skip the MPLS related configuration in this section.
+
+Create a new file ``/etc/sysctl.d/90-routing-sysctl.conf`` with the following
+content:
+
+::
+
+   #
+   # Enable packet forwarding
+   #
+   net.ipv4.conf.all.forwarding=1
+   net.ipv6.conf.all.forwarding=1
+   #
+   # Enable MPLS Label processing on all interfaces
+   #
+   #net.mpls.conf.eth0.input=1
+   #net.mpls.conf.eth1.input=1
+   #net.mpls.conf.eth2.input=1
+   #net.mpls.platform_labels=100000
+
+.. note::
+
+   MPLS must be invidividually enabled on each interface that requires it. See
+   the example in the config block above.
+
+Load the modifed sysctls on the system:
+
+.. code-block:: console
+
+   sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
+
+Create a new file ``/etc/modules-load.d/mpls.conf`` with the following content:
+
+::
+
+   # Load MPLS Kernel Modules
+   mpls-router
+   mpls-iptunnel
+
+And load the kernel modules on the running system:
+
+.. code-block:: console
+
+   sudo modprobe mpls-router mpls-iptunnel
+
+Install service files
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+   sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
+   sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
+   sudo systemctl enable frr
+
+Enable daemons
+^^^^^^^^^^^^^^
+
+Open :file:`/etc/frr/daemons` with your text editor of choice. Look for the
+section with ``watchfrr_enable=...`` and ``zebra=...`` etc.  Enable the daemons
+as required by changing the value to ``yes``.
+
+Start FRR
+^^^^^^^^^
+
+.. code-block:: frr
+
+   sudo systemctl start frr
diff --git a/doc/developer/building-frr-for-fedora24.rst b/doc/developer/building-frr-for-fedora24.rst
deleted file mode 100644 (file)
index 2edf9b3..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-Fedora 24
-=========================================
-
-(As an alternative to this installation, you may prefer to create a FRR
-rpm package yourself and install that package instead. See instructions
-in redhat/README.rpm\_build.md on how to build a rpm package)
-
-Install required packages
--------------------------
-
-Add packages:
-
-::
-
-    sudo dnf install git autoconf automake libtool make gawk \
-      readline-devel texinfo net-snmp-devel groff pkgconfig \
-      json-c-devel pam-devel pytest bison flex c-ares-devel \
-      python3-devel python3-sphinx
-
-.. include:: building-libyang.rst
-
-Get FRR, compile it and install it (from Git)
----------------------------------------------
-
-**This assumes you want to build and install FRR from source and not
-using any packages**
-
-Add frr groups and user
-^^^^^^^^^^^^^^^^^^^^^^^
-
-::
-
-    sudo groupadd -g 92 frr
-    sudo groupadd -r -g 85 frrvty
-    sudo useradd -u 92 -g 92 -M -r -G frrvty -s /sbin/nologin \
-      -c "FRR FRRouting suite" -d /var/run/frr frr
-
-Download Source, configure and compile it
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-(You may prefer different options on configure statement. These are just
-an example.)
-
-::
-
-    git clone https://github.com/frrouting/frr.git frr
-    cd frr
-    ./bootstrap.sh
-    ./configure \
-        --bindir=/usr/bin \
-        --sbindir=/usr/lib/frr \
-        --sysconfdir=/etc/frr \
-        --libdir=/usr/lib/frr \
-        --libexecdir=/usr/lib/frr \
-        --localstatedir=/var/run/frr \
-        --with-moduledir=/usr/lib/frr/modules \
-        --enable-snmp=agentx \
-        --enable-multipath=64 \
-        --enable-user=frr \
-        --enable-group=frr \
-        --enable-vty-group=frrvty \
-        --disable-exampledir \
-        --enable-fpm \
-        --with-pkg-git-version \
-        --with-pkg-extra-version=-MyOwnFRRVersion
-    make
-    make check
-    sudo make install
-
-Create empty FRR configuration files
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-::
-
-    sudo mkdir /var/log/frr
-    sudo mkdir /etc/frr
-    sudo touch /etc/frr/zebra.conf
-    sudo touch /etc/frr/bgpd.conf
-    sudo touch /etc/frr/ospfd.conf
-    sudo touch /etc/frr/ospf6d.conf
-    sudo touch /etc/frr/isisd.conf
-    sudo touch /etc/frr/ripd.conf
-    sudo touch /etc/frr/ripngd.conf
-    sudo touch /etc/frr/pimd.conf
-    sudo touch /etc/frr/ldpd.conf
-    sudo touch /etc/frr/nhrpd.conf
-    sudo touch /etc/frr/eigrpd.conf
-    sudo touch /etc/frr/babeld.conf
-    sudo chown -R frr:frr /etc/frr/
-    sudo touch /etc/frr/vtysh.conf
-    sudo chown frr:frrvty /etc/frr/vtysh.conf
-    sudo chmod 640 /etc/frr/*.conf
-
-Install daemon config file
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-::
-
-    sudo install -p -m 644 redhat/daemons /etc/frr/
-    sudo chown frr:frr /etc/frr/daemons
-
-Edit /etc/frr/daemons as needed to select the required daemons
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Look for the section with ``watchfrr_enable=...`` and ``zebra=...`` etc.
-Enable the daemons as required by changing the value to ``yes``
-
-Enable IP & IPv6 forwarding (and MPLS)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Create a new file ``/etc/sysctl.d/90-routing-sysctl.conf`` with the
-following content: (Please make sure to list all interfaces with
-required MPLS similar to ``net.mpls.conf.eth0.input=1``)
-
-::
-
-    # Sysctl for routing
-    #
-    # Routing: We need to forward packets
-    net.ipv4.conf.all.forwarding=1
-    net.ipv6.conf.all.forwarding=1
-    #
-    # Enable MPLS Label processing on all interfaces
-    net.mpls.conf.eth0.input=1
-    net.mpls.conf.eth1.input=1
-    net.mpls.conf.eth2.input=1
-    net.mpls.platform_labels=100000
-
-Load the modifed sysctl's on the system:
-
-::
-
-    sudo sysctl -p /etc/sysctl.d/90-routing-sysctl.conf
-
-Create a new file ``/etc/modules-load.d/mpls.conf`` with the following
-content:
-
-::
-
-    # Load MPLS Kernel Modules
-    mpls-router
-    mpls-iptunnel
-
-And load the kernel modules on the running system:
-
-::
-
-    sudo modprobe mpls-router mpls-iptunnel
-
-Install frr Service and redhat init files
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-::
-
-    sudo install -p -m 644 redhat/frr.service /usr/lib/systemd/system/frr.service
-    sudo install -p -m 755 redhat/frr.init /usr/lib/frr/frr
-
-Enable required frr at startup
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-::
-
-    sudo systemctl enable frr
-
-Reboot or start FRR manually
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-::
-
-    sudo systemctl start frr
index a6539309a238b04145bad584c5afb5f5e11393e2..86c44f4d90cfc1883fabe2b76e582d845282d088 100644 (file)
@@ -11,12 +11,12 @@ FreeBSD 10 restrictions:
 Install required packages
 -------------------------
 
-Add packages: (Allow the install of the package managment tool if this
+Add packages: (Allow the install of the package management tool if this
 is first package install and asked)
 
 ::
 
-    pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
+    pkg install git autoconf automake libtool gmake json-c pkgconf \
         bison flex py27-pytest c-ares python3 py-sphinx
 
 Make sure there is no /usr/bin/flex preinstalled (and use the newly
index 16d06e0a6647af5680183dc58b4cf443e9e0d4f6..5e56c8cd7a8034eb7f4bd5921e6b4e7986fb38fe 100644 (file)
@@ -11,12 +11,12 @@ FreeBSD 11 restrictions:
 Install required packages
 -------------------------
 
-Add packages: (Allow the install of the package managment tool if this
+Add packages: (Allow the install of the package management tool if this
 is first package install and asked)
 
 .. code-block:: shell
 
-   pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
+   pkg install git autoconf automake libtool gmake json-c pkgconf \
       bison flex py27-pytest c-ares python3 py36-sphinx texinfo
 
 Make sure there is no /usr/bin/flex preinstalled (and use the newly
index 36492fb88657fe5549118cd9c3ea0a32711f332d..59241d1d13763f4e82e757b396f632246fe72d2e 100644 (file)
@@ -11,14 +11,14 @@ FreeBSD 9 restrictions:
 Install required packages
 -------------------------
 
-Add packages: (Allow the install of the package managment tool if this
+Add packages: (Allow the install of the package management tool if this
 is first package install and asked)
 
 ::
 
-    pkg install -y git autoconf automake libtool gmake gawk \
+    pkg install -y git autoconf automake libtool gmake \
         pkgconf texinfo json-c bison flex py27-pytest c-ares \
-        python3 py-sphinx
+        python3 py-sphinx libexecinfo
 
 Make sure there is no /usr/bin/flex preinstalled (and use the newly
 installed in /usr/local/bin): (FreeBSD frequently provides a older flex
index a042077fd0f0d1ec42e8b281114d98c7070e8d91..49091c49b400bf0195dfc166c5b98cd050430b19 100644 (file)
@@ -22,7 +22,7 @@ Add packages:
 
 ::
 
-    sudo pkg_add git autoconf automake libtool gmake gawk openssl \
+    sudo pkg_add git autoconf automake libtool gmake openssl \
        pkg-config json-c python27 py27-test python35 py-sphinx
 
 Install SSL Root Certificates (for git https access):
index b65891916c3d72d433a46481360ed80aae66f5f2..64c462a5c8b77b6ccd54eec2c3dfa9310cf41866 100644 (file)
@@ -13,7 +13,7 @@ Install required packages
 
 ::
 
-    sudo pkgin install git autoconf automake libtool gmake gawk openssl \
+    sudo pkgin install git autoconf automake libtool gmake openssl \
        pkg-config json-c python27 py27-test python35 py-sphinx
 
 Install SSL Root Certificates (for git https access):
index 416c89c6677a5980124e846f81ebb74d331c5efd..ffc7a078e54b9f539e7488204223324e5e07a952 100644 (file)
@@ -37,7 +37,7 @@ Add packages:
       library/idnkit/header-idnkit \
       system/header \
       system/library/math/header-math \
-      git libtool gawk pkg-config
+      git libtool pkg-config
 
 Add additional Solaris packages:
 
index 0f8d4d0f25ff293caebe1aa12812574d9578dd55..f307cacdfcf8f7296633b3f581a7527abc486741 100644 (file)
@@ -15,7 +15,7 @@ Add packages:
 ::
 
     pkg_add git autoconf-2.69p2 automake-1.15.1 libtool bison
-    pkg_add gmake gawk dejagnu openssl json-c py-test py-sphinx
+    pkg_add gmake json-c py-test py-sphinx libexecinfo
 
 Select Python2.7 as default (required for pytest)
 
index b9be1b52260e485aa0d0398fd10edbfd2208fff8..5d8f82f27ecf6f7446a236a49a22e85d2acf596c 100644 (file)
@@ -9,7 +9,7 @@ For Debian based distributions, run:
 ::
 
     sudo apt-get install git build-essential libssl-dev libncurses5-dev \
-       unzip gawk zlib1g-dev subversion mercurial
+       unzip zlib1g-dev subversion mercurial
 
 For other environments, instructions can be found in the
 `official documentation
@@ -63,10 +63,10 @@ Usage
 -----
 
 Edit ``/usr/sbin/frr.init`` and add/remove the daemons name in section
-``DAEMONS=`` or don't install unneded packages For example: zebra bgpd ldpd
+``DAEMONS=`` or don't install unneeded packages For example: zebra bgpd ldpd
 isisd nhrpd ospfd ospf6d pimd ripd ripngd
 
-Enable the serivce
+Enable the service
 ^^^^^^^^^^^^^^^^^^
 
 -  ``service frr enable``
index b1eaf57e8d52de355bbf62d9ba424679bcee4a37..6e2765c1c86cc7c4827d4e95b0e342fd93782148 100644 (file)
@@ -1,35 +1,30 @@
-Ubuntu 14.04LTS
-===============================================
+Ubuntu 14.04 LTS
+================
 
--  MPLS is not supported on ``Ubuntu 14.04`` with default kernel. MPLS
-   requires Linux Kernel 4.5 or higher (LDP can be built, but may have
-   limited use without MPLS) For an updated Ubuntu Kernel, see
-   http://kernel.ubuntu.com/~kernel-ppa/mainline/
-
-Install required packages
--------------------------
+This document describes installation from source. If you want to build a
+``deb``, see :ref:`packaging-debian`.
 
-Add packages:
+Installing Dependencies
+-----------------------
 
-::
+.. code-block:: console
 
+   apt-get update
    apt-get install \
-      git autoconf automake libtool make gawk libreadline-dev texinfo \
-      dejagnu pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest \
-      libc-ares-dev python3-dev python3-sphinx install-info build-essential
+      git autoconf automake libtool make libreadline-dev texinfo \
+      pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest \
+      libc-ares-dev python3-dev python3-sphinx install-info build-essential \
+      libsnmp-dev perl
 
 .. include:: building-libyang.rst
 
-Get FRR, compile it and install it (from Git)
----------------------------------------------
-
-**This assumes you want to build and install FRR from source and not
-using any packages**
+Building & Installing FRR
+-------------------------
 
-Add frr groups and user
+Add FRR user and groups
 ^^^^^^^^^^^^^^^^^^^^^^^
 
-::
+.. code-block:: console
 
     sudo groupadd -r -g 92 frr
     sudo groupadd -r -g 85 frrvty
@@ -37,102 +32,104 @@ Add frr groups and user
        --gecos "FRR suite" --shell /sbin/nologin frr
     sudo usermod -a -G frrvty frr
 
-Download Source, configure and compile it
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Compile
+^^^^^^^
 
-(You may prefer different options on configure statement. These are just
-an example.)
+.. include:: include-compile.rst
 
-::
+Install FRR configuration files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-    git clone https://github.com/frrouting/frr.git frr
-    cd frr
-    ./bootstrap.sh
-    ./configure \
-        --prefix=/usr \
-        --enable-exampledir=/usr/share/doc/frr/examples/ \
-        --localstatedir=/var/run/frr \
-        --sbindir=/usr/lib/frr \
-        --sysconfdir=/etc/frr \
-        --enable-multipath=64 \
-        --enable-user=frr \
-        --enable-group=frr \
-        --enable-vty-group=frrvty \
-        --enable-configfile-mask=0640 \
-        --enable-logfile-mask=0640 \
-        --enable-fpm \
-        --with-pkg-git-version \
-        --with-pkg-extra-version=-MyOwnFRRVersion
-    make
-    make check
-    sudo make install
-
-Create empty FRR configuration files
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. code-block:: console
+
+   sudo install -m 775 -o frr -g frr -d /var/log/frr
+   sudo install -m 775 -o frr -g frrvty -d /etc/frr
+   sudo install -m 640 -o frr -g frrvty tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/frr.conf /etc/frr/frr.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons /etc/frr/daemons
+
+Tweak sysctls
+^^^^^^^^^^^^^
+
+Some sysctls need to be changed in order to enable IPv4/IPv6 forwarding and
+MPLS (if supported by your platform). If your platform does not support MPLS,
+skip the MPLS related configuration in this section.
+
+Edit :file:`/etc/sysctl.conf` and uncomment the following values (ignore the
+other settings):
 
 ::
 
-    sudo install -m 755 -o frr -g frr -d /var/log/frr
-    sudo install -m 775 -o frr -g frrvty -d /etc/frr
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
-    sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
-
-Enable IP & IPv6 forwarding
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
-other settings)
+   # Uncomment the next line to enable packet forwarding for IPv4
+   net.ipv4.ip_forward=1
+
+   # Uncomment the next line to enable packet forwarding for IPv6
+   #  Enabling this option disables Stateless Address Autoconfiguration
+   #  based on Router Advertisements for this host
+   net.ipv6.conf.all.forwarding=1
+
+Reboot or use ``sysctl -p`` to apply the same config to the running system.
+
+Add MPLS kernel modules
+"""""""""""""""""""""""
+
+.. warning::
+
+   MPLS is not supported on Ubuntu 14.04 with the default kernel. MPLS requires
+   kernel 4.5 or higher. LDPD can be built, but may have limited use without
+   MPLS. For an updated Ubuntu Kernel, see
+   http://kernel.ubuntu.com/~kernel-ppa/mainline/
+
+Ubuntu 18.04 ships with kernel 4.15. MPLS modules are present by default.  To
+enable, add the following lines to :file:`/etc/modules-load.d/modules.conf`:
 
 ::
 
-    # Uncomment the next line to enable packet forwarding for IPv4
-    net.ipv4.ip_forward=1
+   # Load MPLS Kernel Modules
+   mpls_router
+   mpls_iptunnel
+
+
+And load the kernel modules on the running system:
+
+.. code-block:: console
+
+   sudo modprobe mpls-router mpls-iptunnel
+
+Enable MPLS Forwarding
+""""""""""""""""""""""
 
-    # Uncomment the next line to enable packet forwarding for IPv6
-    #  Enabling this option disables Stateless Address Autoconfiguration
-    #  based on Router Advertisements for this host
-    net.ipv6.conf.all.forwarding=1
+Edit :file:`/etc/sysctl.conf` and the following lines. Make sure to add a line
+equal to :file:`net.mpls.conf.eth0.input` for each interface used with MPLS.
 
-**Reboot** or use ``sysctl -p`` to apply the same config to the running
-system
+::
+
+   # Enable MPLS Label processing on all interfaces
+   net.mpls.conf.eth0.input=1
+   net.mpls.conf.eth1.input=1
+   net.mpls.conf.eth2.input=1
+   net.mpls.platform_labels=100000
 
 Install the init.d service
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-::
+.. code-block:: console
 
-    sudo install -m 755 tools/frr /etc/init.d/frr
-    sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
-    sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+   sudo install -m 755 tools/frr /etc/init.d/frr
 
 Enable daemons
 ^^^^^^^^^^^^^^
 
-| Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
-  those daemons you want to start by systemd.
-| For example.
-
-::
-
-    zebra=yes
-    bgpd=yes
-    ospfd=yes
-    ospf6d=yes
-    ripd=yes
-    ripngd=yes
-    isisd=yes
+Open :file:`/etc/frr/daemons` with your text editor of choice. Look for the
+section with ``watchfrr_enable=...`` and ``zebra=...`` etc.  Enable the daemons
+as required by changing the value to ``yes``.
 
 Start the init.d service
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
--  /etc/init.d/frr start
--  use ``/etc/init.d/frr status`` to check its status.
+.. code-block:: console
+
+  /etc/init.d/frr start
+
+Use ``/etc/init.d/frr status`` to check its status.
index 0762e07eb9e0e2b2782c63297cc1707527143070..a9a0a2f733aa96546bd10c57aaa4f9f8f05f41e7 100644 (file)
-Ubuntu 16.04LTS
-===============================================
+Ubuntu 16.04 LTS
+================
 
--  MPLS is not supported on ``Ubuntu 16.04`` with default kernel. MPLS
-   requires Linux Kernel 4.5 or higher (LDP can be built, but may have
-   limited use without MPLS) For an updated Ubuntu Kernel, see
-   http://kernel.ubuntu.com/~kernel-ppa/mainline/
-
-Install required packages
--------------------------
+This document describes installation from source. If you want to build a
+``deb``, see :ref:`packaging-debian`.
 
-Add packages:
+Installing Dependencies
+-----------------------
 
-::
+.. code-block:: console
 
+   apt-get update
    apt-get install \
-      git autoconf automake libtool make gawk libreadline-dev texinfo dejagnu \
+      git autoconf automake libtool make libreadline-dev texinfo \
       pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest \
-      libc-ares-dev python3-dev libsystemd-dev python-ipaddress \
-      python3-sphinx install-info build-essential libsystemd-dev
+      libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
+      install-info build-essential libsystemd-dev libsnmp-dev perl
 
 .. include:: building-libyang.rst
 
-Get FRR, compile it and install it (from Git)
----------------------------------------------
-
-**This assumes you want to build and install FRR from source and not
-using any packages**
+Building & Installing FRR
+-------------------------
 
-Add frr groups and user
+Add FRR user and groups
 ^^^^^^^^^^^^^^^^^^^^^^^
 
-::
+.. code-block:: console
 
-    sudo groupadd -r -g 92 frr
-    sudo groupadd -r -g 85 frrvty
-    sudo adduser --system --ingroup frr --home /var/run/frr/ \
-       --gecos "FRR suite" --shell /sbin/nologin frr
-    sudo usermod -a -G frrvty frr
+   sudo groupadd -r -g 92 frr
+   sudo groupadd -r -g 85 frrvty
+   sudo adduser --system --ingroup frr --home /var/run/frr/ \
+      --gecos "FRR suite" --shell /sbin/nologin frr
+   sudo usermod -a -G frrvty frr
 
-Download Source, configure and compile it
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Compile
+^^^^^^^
 
-(You may prefer different options on configure statement. These are just
-an example.)
+.. include:: include-compile.rst
 
-::
+Install FRR configuration files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-    git clone https://github.com/frrouting/frr.git frr
-    cd frr
-    ./bootstrap.sh
-    ./configure \
-        --prefix=/usr \
-        --enable-exampledir=/usr/share/doc/frr/examples/ \
-        --localstatedir=/var/run/frr \
-        --sbindir=/usr/lib/frr \
-        --sysconfdir=/etc/frr \
-        --enable-multipath=64 \
-        --enable-user=frr \
-        --enable-group=frr \
-        --enable-vty-group=frrvty \
-        --enable-configfile-mask=0640 \
-        --enable-logfile-mask=0640 \
-        --enable-fpm \
-        --enable-systemd=yes \
-        --with-pkg-git-version \
-        --with-pkg-extra-version=-MyOwnFRRVersion
-    make
-    make check
-    sudo make install
-
-Create empty FRR configuration files
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. code-block:: console
 
-::
+   sudo install -m 775 -o frr -g frr -d /var/log/frr
+   sudo install -m 775 -o frr -g frrvty -d /etc/frr
+   sudo install -m 640 -o frr -g frrvty tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/frr.conf /etc/frr/frr.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons /etc/frr/daemons
 
-    sudo install -m 755 -o frr -g frr -d /var/log/frr
-    sudo install -m 775 -o frr -g frrvty -d /etc/frr
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
-    sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
-    sudo install -m 640 -o frr -g frrvty /dev/null /etc/frr/vtysh.conf
-
-Enable IPv4 & IPv6 forwarding
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Edit ``/etc/sysctl.conf`` and uncomment the following values (ignore the
-other settings)
+Tweak sysctls
+^^^^^^^^^^^^^
+
+Some sysctls need to be changed in order to enable IPv4/IPv6 forwarding and
+MPLS (if supported by your platform). If your platform does not support MPLS,
+skip the MPLS related configuration in this section.
+
+Edit :file:`/etc/sysctl.conf` and uncomment the following values (ignore the
+other settings):
 
 ::
 
-    # Uncomment the next line to enable packet forwarding for IPv4
-    net.ipv4.ip_forward=1
+   # Uncomment the next line to enable packet forwarding for IPv4
+   net.ipv4.ip_forward=1
+
+   # Uncomment the next line to enable packet forwarding for IPv6
+   #  Enabling this option disables Stateless Address Autoconfiguration
+   #  based on Router Advertisements for this host
+   net.ipv6.conf.all.forwarding=1
 
-    # Uncomment the next line to enable packet forwarding for IPv6
-    #  Enabling this option disables Stateless Address Autoconfiguration
-    #  based on Router Advertisements for this host
-    net.ipv6.conf.all.forwarding=1
+Reboot or use ``sysctl -p`` to apply the same config to the running system.
 
-Enable MPLS Forwarding (with Linux Kernel >= 4.5)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Add MPLS kernel modules
+"""""""""""""""""""""""
+
+.. warning::
+
+   MPLS is not supported on Ubuntu 16.04 with the default kernel. MPLS requires
+   kernel 4.5 or higher. LDPD can be built, but may have limited use without
+   MPLS. For an updated Ubuntu Kernel, see
+   http://kernel.ubuntu.com/~kernel-ppa/mainline/
 
-Edit ``/etc/sysctl.conf`` and the following lines. Make sure to add a
-line equal to ``net.mpls.conf.eth0.input`` or each interface used with
-MPLS
+Ubuntu 18.04 ships with kernel 4.15. MPLS modules are present by default.  To
+enable, add the following lines to :file:`/etc/modules-load.d/modules.conf`:
 
 ::
 
-    # Enable MPLS Label processing on all interfaces
-    net.mpls.conf.eth0.input=1
-    net.mpls.conf.eth1.input=1
-    net.mpls.conf.eth2.input=1
-    net.mpls.platform_labels=100000
+   # Load MPLS Kernel Modules
+   mpls_router
+   mpls_iptunnel
 
-Add MPLS kernel modules
-^^^^^^^^^^^^^^^^^^^^^^^
 
-Add the following lines to ``/etc/modules-load.d/modules.conf``:
+And load the kernel modules on the running system:
 
-::
+.. code-block:: console
 
-    # Load MPLS Kernel Modules
-    mpls-router
-    mpls-iptunnel
+   sudo modprobe mpls-router mpls-iptunnel
 
-**Reboot** or use ``sysctl -p`` to apply the same config to the running
-system
+Enable MPLS Forwarding
+""""""""""""""""""""""
 
-Install the systemd service (if rebooted from last step, change directory back to frr directory)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Edit :file:`/etc/sysctl.conf` and the following lines. Make sure to add a line
+equal to :file:`net.mpls.conf.eth0.input` for each interface used with MPLS.
 
 ::
 
-    sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service
-    sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
-    sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf
-    sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+   # Enable MPLS Label processing on all interfaces
+   net.mpls.conf.eth0.input=1
+   net.mpls.conf.eth1.input=1
+   net.mpls.conf.eth2.input=1
+   net.mpls.platform_labels=100000
 
-Enable daemons
-^^^^^^^^^^^^^^
+Install service files
+^^^^^^^^^^^^^^^^^^^^^
 
-| Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for
-  those daemons you want to start by systemd.
-| For example.
+.. code-block:: console
 
-::
+   sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service
+   sudo systemctl enable frr
 
-    zebra=yes
-    bgpd=yes
-    ospfd=yes
-    ospf6d=yes
-    ripd=yes
-    ripngd=yes
-    isisd=yes
+Enable daemons
+^^^^^^^^^^^^^^
 
-Enable the systemd service
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+Open :file:`/etc/frr/daemons` with your text editor of choice. Look for the
+section with ``watchfrr_enable=...`` and ``zebra=...`` etc.  Enable the daemons
+as required by changing the value to ``yes``.
 
--  systemctl enable frr
+Start FRR
+^^^^^^^^^
 
-Start the systemd service
-^^^^^^^^^^^^^^^^^^^^^^^^^
+.. code-block:: console
 
--  systemctl start frr
--  use ``systemctl status frr`` to check its status.
+   systemctl start frr
index 089d5a216a5d02986c2f4a9c5c3e59093640ef2d..1320bda5777bbcdc6857331e014e94269b111fe2 100644 (file)
@@ -1,55 +1,44 @@
 Ubuntu 18.04 LTS
 ================
 
-Install dependencies
---------------------
+This document describes installation from source. If you want to build a
+``deb``, see :ref:`packaging-debian`.
 
-Required packages
-^^^^^^^^^^^^^^^^^
+Installing Dependencies
+-----------------------
 
-::
+.. code-block:: console
 
+   sudo apt update
    sudo apt-get install \
-      git autoconf automake libtool make gawk libreadline-dev texinfo \
+      git autoconf automake libtool make libreadline-dev texinfo \
       pkg-config libpam0g-dev libjson-c-dev bison flex python-pytest \
-      libc-ares-dev python3-dev libsystemd-dev python-ipaddress \
-      python3-sphinx install-info build-essential libsystemd-dev
+      libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
+      install-info build-essential libsystemd-dev libsnmp-dev perl
 
 .. include:: building-libyang.rst
 
-Optional packages
-^^^^^^^^^^^^^^^^^
-
-Dependencies for additional functionality can be installed as-desired.
-
 Protobuf
-~~~~~~~~
+^^^^^^^^
 
-::
+.. code-block:: console
 
-   sudo apt-get install \
-       protobuf-c-compiler \
-       libprotobuf-c-dev
+   sudo apt-get install protobuf-c-compiler libprotobuf-c-dev
 
 ZeroMQ
-~~~~~~
-
-::
+^^^^^^
 
-   sudo apt-get install \
-       libzmq5 \
-       libzmq3-dev
+.. code-block:: console
 
-Get FRR, compile it and install it (from Git)
----------------------------------------------
+   sudo apt-get install libzmq5 libzmq3-dev
 
-**This assumes you want to build and install FRR from source and not
-using any packages**
+Building & Installing FRR
+-------------------------
 
-Add frr groups and user
+Add FRR user and groups
 ^^^^^^^^^^^^^^^^^^^^^^^
 
-::
+.. code-block:: console
 
    sudo groupadd -r -g 92 frr
    sudo groupadd -r -g 85 frrvty
@@ -57,104 +46,29 @@ Add frr groups and user
       --gecos "FRR suite" --shell /sbin/nologin frr
    sudo usermod -a -G frrvty frr
 
-Download source
-^^^^^^^^^^^^^^^
-
-::
-
-   git clone https://github.com/frrouting/frr.git frr
-
-Configure
-^^^^^^^^^
-Options below are provided as an example.
-
-.. seealso:: *Installation* section of user guide
-
-.. code-block:: shell
-
-   cd frr
-   ./bootstrap.sh
-   ./configure \
-       --prefix=/usr \
-       --enable-exampledir=/usr/share/doc/frr/examples/ \
-       --localstatedir=/var/run/frr \
-       --sbindir=/usr/lib/frr \
-       --sysconfdir=/etc/frr \
-       --enable-multipath=64 \
-       --enable-user=frr \
-       --enable-group=frr \
-       --enable-vty-group=frrvty \
-       --enable-configfile-mask=0640 \
-       --enable-logfile-mask=0640 \
-       --enable-fpm \
-       --enable-systemd=yes \
-       --with-pkg-git-version \
-       --with-pkg-extra-version=-MyOwnFRRVersion
-
-If optional packages were installed, the associated feature may now be
-enabled.
-
-.. option:: --enable-protobuf
-
-Enable support for protobuf transport
-
-.. option:: --enable-zeromq
-
-Enable support for ZeroMQ transport
-
 Compile
 ^^^^^^^
 
-::
-
-   make
-   make check
-   sudo make install
-
-Create empty FRR configuration files
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. include:: include-compile.rst
 
-Although not strictly necessary, it's good practice to create empty
-configuration files _before_ starting FRR. This assures that the permissions
-are correct. If the files are not already present, FRR will create them.
+Install FRR configuration files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-It's also important to consider _which_ files to create. FRR supports writing
-configuration to a monolithic file, :file:`/etc/frr/frr.conf`.
+.. code-block:: console
 
-.. seealso:: *VTYSH* section of user guide
-
-The presence of :file:`/etc/frr/frr.conf` on startup implicitly configures FRR
-to ignore daemon-specific configuration files.
-
-Daemon-specific configuration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-   sudo install -m 755 -o frr -g frr -d /var/log/frr
+   sudo install -m 775 -o frr -g frr -d /var/log/frr
    sudo install -m 775 -o frr -g frrvty -d /etc/frr
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/zebra.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/bgpd.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospfd.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ospf6d.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/isisd.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripd.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ripngd.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/pimd.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/ldpd.conf
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/nhrpd.conf
-
-Monolithic configuration
-~~~~~~~~~~~~~~~~~~~~~~~~
+   sudo install -m 640 -o frr -g frrvty tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/frr.conf /etc/frr/frr.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons.conf /etc/frr/daemons.conf
+   sudo install -m 640 -o frr -g frr tools/etc/frr/daemons /etc/frr/daemons
 
-::
+Tweak sysctls
+^^^^^^^^^^^^^
 
-   sudo install -m 755 -o frr -g frr -d /var/log/frr
-   sudo install -m 775 -o frr -g frrvty -d /etc/frr
-   sudo install -m 640 -o frr -g frr /dev/null /etc/frr/frr.conf
-
-Enable IPv4 & IPv6 forwarding
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Some sysctls need to be changed in order to enable IPv4/IPv6 forwarding and
+MPLS (if supported by your platform). If your platform does not support MPLS,
+skip the MPLS related configuration in this section.
 
 Edit :file:`/etc/sysctl.conf` and uncomment the following values (ignore the
 other settings):
@@ -169,8 +83,10 @@ other settings):
    #  based on Router Advertisements for this host
    net.ipv6.conf.all.forwarding=1
 
+Reboot or use ``sysctl -p`` to apply the same config to the running system.
+
 Add MPLS kernel modules
-^^^^^^^^^^^^^^^^^^^^^^^
+"""""""""""""""""""""""
 
 Ubuntu 18.04 ships with kernel 4.15. MPLS modules are present by default.  To
 enable, add the following lines to :file:`/etc/modules-load.d/modules.conf`:
@@ -181,10 +97,15 @@ enable, add the following lines to :file:`/etc/modules-load.d/modules.conf`:
    mpls_router
    mpls_iptunnel
 
-Reboot or use ``sysctl -p`` to apply the same config to the running system.
+
+And load the kernel modules on the running system:
+
+.. code-block:: console
+
+   sudo modprobe mpls-router mpls-iptunnel
 
 Enable MPLS Forwarding
-^^^^^^^^^^^^^^^^^^^^^^
+""""""""""""""""""""""
 
 Edit :file:`/etc/sysctl.conf` and the following lines. Make sure to add a line
 equal to :file:`net.mpls.conf.eth0.input` for each interface used with MPLS.
@@ -197,48 +118,24 @@ equal to :file:`net.mpls.conf.eth0.input` for each interface used with MPLS.
    net.mpls.conf.eth2.input=1
    net.mpls.platform_labels=100000
 
-Install the systemd service
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Install service files
+^^^^^^^^^^^^^^^^^^^^^
 
-::
+.. code-block:: console
 
    sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service
-   sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons
-   sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf
-   sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf
+   sudo systemctl enable frr
 
 Enable daemons
 ^^^^^^^^^^^^^^
 
-Edit ``/etc/frr/daemons`` and change the value from "no" to "yes" for those
-daemons you want to start by systemd.  For example:
-
-::
-
-   zebra=yes
-   bgpd=yes
-   ospfd=yes
-   ospf6d=yes
-   ripd=yes
-   ripngd=yes
-   isisd=yes
-
-Enable the systemd service
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+Open :file:`/etc/frr/daemons` with your text editor of choice. Look for the
+section with ``watchfrr_enable=...`` and ``zebra=...`` etc.  Enable the daemons
+as required by changing the value to ``yes``.
 
-Enabling the systemd service causes FRR to be started upon boot. To enable it,
-use the following command:
-
-.. code-block:: shell
-
-   systemctl enable frr
-
-Start the systemd service
-^^^^^^^^^^^^^^^^^^^^^^^^^
+Start FRR
+^^^^^^^^^
 
 .. code-block:: shell
 
    systemctl start frr
-
-After starting the service, you can use ``systemctl status frr`` to check its
-status.
index c45c294b75295db8640da9422235c04e2a093fc7..41fe09e322fef4445a432106dc750c8de0ac3877 100644 (file)
@@ -1,57 +1,55 @@
-The libyang library can be installed from third-party packages available `here
-<https://ci1.netdef.org/browse/LIBYANG-YANGRELEASE/latestSuccessful/artifact>`_.
+FRR depends on the relatively new ``libyang`` library to provide YANG/NETCONF
+support. Unfortunately, most distributions do not yet offer a ``libyang``
+package from their repositories. Therefore we offer two options to install this
+library.
 
-Note: the libyang dev/devel packages need to be installed in addition
-to the libyang core package in order to build FRR successfully.
+**Option 1: Binary Install**
+
+The FRR project builds binary ``libyang`` packages, which we offer for download
+`here <https://ci1.netdef.org/browse/LIBYANG-YANGRELEASE/latestSuccessful/artifact>`_.
 
 .. warning::
-   libyang ABI version 0.16.74 or newer will be required to build FRR in the
-   near future since it significantly eases build and installation
-   considerations.  "0.16-r3" is equal to 0.16.105 and will work, "0.16-r2"
-   is equal to 0.16.52 and will stop working.  The CI artifacts will be
-   updated shortly.
 
-For example, for CentOS 7.x:
+   ``libyang`` version 0.16.74 or newer is required to build FRR.
+
+.. note::
 
-.. code-block:: shell
+   The ``libyang`` development packages need to be installed in addition to the
+   libyang core package in order to build FRR successfully. Make sure to
+   download and install those from the link above alongside the binary
+   packages.
 
-   wget https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-1/CentOS-7-x86_64-Packages/libyang-0.16.46-0.x86_64.rpm
-   wget https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-1/CentOS-7-x86_64-Packages/libyang-devel-0.16.46-0.x86_64.rpm
-   sudo rpm -i libyang-0.16.46-0.x86_64.rpm libyang-devel-0.16.46-0.x86_64.rpm
+   Depending on your platform, you may also need to install the PCRE
+   development package. Typically this is ``libpcre-dev`` or ``pcre-devel``.
 
-or Ubuntu 18.04:
+.. note::
 
-.. code-block:: shell
+   For Debian-based systems, the official ``libyang`` package requires recent
+   versions of ``swig`` (3.0.12) and ``debhelper`` (11) which are only
+   available in Debian buster (10).  However, ``libyang`` packages built on
+   Debian buster can be installed on both Debian jessie (8) and Debian stretch
+   (9), as well as various Ubuntu systems.  The ``python3-yang`` package will
+   not work, but the other packages (``libyang-dev`` is the one needed for FRR)
+   will.
 
-   wget https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-1/Ubuntu-18.04-x86_64-Packages/libyang-dev_0.16.46_amd64.deb
-   wget https://ci1.netdef.org/artifact/LIBYANG-YANGRELEASE/shared/build-1/Ubuntu-18.04-x86_64-Packages/libyang_0.16.46_amd64.deb
-   sudo apt install libpcre3-dev
-   sudo dpkg -i libyang-dev_0.16.46_amd64.deb libyang_0.16.46_amd64.deb
+**Option 2: Source Install**
 
 .. note::
-   For Debian-based systems, the official libyang package requires recent
-   versions of swig (3.0.12) and debhelper (11) which are only available in
-   Debian buster (10).  However, libyang packages built on Debian buster can
-   be installed on both Debian jessie (8) and Debian stretch (9), as well as
-   various Ubuntu systems.  The python3-yang package will not work, but the
-   other packages (libyang-dev is the one needed for FRR) will.
 
-Alternatively, libyang can be built and installed manually by following
-the steps below:
+   Ensure that the `libyang build requirements
+   <https://github.com/CESNET/libyang/blob/master/README.md#build-requirements>`_
+   are met before continuing. Usually this entails installing ``cmake`` and
+   ``libpcre-dev`` or ``pcre-devel``.
 
-.. code-block:: shell
+.. code-block:: console
 
-   git clone https://github.com/opensourcerouting/libyang
+   git clone https://github.com/CESNET/libyang.git
    cd libyang
-   git checkout -b tmp origin/tmp
    mkdir build; cd build
-   cmake -DENABLE_LYD_PRIV=ON ..
+   cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr ..
    make
    sudo make install
 
 When building libyang on CentOS 6, it's also necessary to pass the
 ``-DENABLE_CACHE=OFF`` parameter to cmake.
 
-Note: please check the `libyang build requirements
-<https://github.com/CESNET/libyang/blob/master/README.md#build-requirements>`_
-first.
index 96559b0abe396709dd4db989adc3265f912a267a..c13fb10ffc290da4e88d4b4a2615f3b056431a61 100644 (file)
@@ -12,7 +12,7 @@ Building FRR
    building-frr-for-centos7
    building-frr-for-debian8
    building-frr-for-debian9
-   building-frr-for-fedora24
+   building-frr-for-fedora
    building-frr-for-freebsd10
    building-frr-for-freebsd11
    building-frr-for-freebsd9
index af8673e5fabf09e27ca8835c00919be65b8be5d9..9acfab739a943f376ccc58fb23dcb843c402781b 100644 (file)
@@ -131,7 +131,7 @@ language = None
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build', 'building-libyang.rst', 'topotests-snippets.rst']
+exclude_patterns = ['_build', 'building-libyang.rst', 'topotests-snippets.rst', 'include-compile.rst']
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
index 4140a0d171e4f940b6b55a5cacef66f593fe8db6..10fe6b9c43605b656e94978a6df37455128eec61 100644 (file)
@@ -6,7 +6,7 @@ Hooks
 Libfrr provides type-safe subscribable hook points where other pieces of
 code can add one or more callback functions.  "type-safe" in this case
 applies to the function pointers used for subscriptions.  The
-implementations checks (at compile-time) wheter a callback to be added has
+implementations checks (at compile-time) whether a callback to be added has
 the appropriate function signature (parameters) for the hook.
 
 Example:
diff --git a/doc/developer/include-compile.rst b/doc/developer/include-compile.rst
new file mode 100644 (file)
index 0000000..0ff0ae3
--- /dev/null
@@ -0,0 +1,37 @@
+Clone the FRR git repo and use the included ``configure`` script to configure
+FRR's build time options to your liking. The full option listing can be
+obtained by running ``./configure -h``. The options shown below are examples.
+
+.. note::
+
+   If your platform uses ``systemd``, please make sure to add
+   ``--enable-systemd=yes`` to your configure options.
+
+.. code-block:: console
+
+   git clone https://github.com/frrouting/frr.git frr
+   cd frr
+   ./bootstrap.sh
+   ./configure \
+       --prefix=/usr \
+       --includedir=\${prefix}/include \
+       --enable-exampledir=\${prefix}/share/doc/frr/examples \
+       --bindir=\${prefix}/bin \
+       --sbindir=\${prefix}/lib/frr \
+       --libdir=\${prefix}/lib/frr \
+       --libexecdir=\${prefix}/lib/frr \
+       --localstatedir=/var/run/frr \
+       --sysconfdir=/etc/frr \
+       --with-moduledir=\${prefix}/lib/frr/modules \
+       --with-libyang-pluginsdir=\${prefix}/lib/frr/libyang_plugins \
+       --enable-configfile-mask=0640 \
+       --enable-logfile-mask=0640 \
+       --enable-snmp=agentx \
+       --enable-multipath=64 \
+       --enable-user=frr \
+       --enable-group=frr \
+       --enable-vty-group=frrvty \
+       --with-pkg-git-version \
+       --with-pkg-extra-version=-MyOwnFRRVersion
+   make
+   sudo make install
index 4338d900e65b74835313b9a9ca430e8f65f8b9d8..1dc188515827e4b9cd5a774b20ff230fd47b2844 100644 (file)
@@ -18,7 +18,7 @@ maybe by a syslog collector from all routers.)  Therefore, anything that
 needs to get the user in the loop—and only these things—are warnings or
 errors.
 
-Note that this doesn't neccessarily mean the user needs to fix something in
+Note that this doesn't necessarily mean the user needs to fix something in
 the FRR instance.  It also includes when we detect something else needs
 fixing, for example another router, the system we're running on, or the
 configuration.  The common point is that the user should probably do
index 43cbe002cffd670719a31ce0d751a6073591c322..153131bab927d2144a8a7c5989930f1232cac04e 100644 (file)
@@ -3,7 +3,7 @@
 Memtypes
 ========
 
-FRR includes wrappers arround ``malloc()`` and ``free()`` that count the number
+FRR includes wrappers around ``malloc()`` and ``free()`` that count the number
 of objects currently allocated, for each of a defined ``MTYPE``.
 
 To this extent, there are *memory groups* and *memory types*.  Each memory
index 90fc52efd0e7187d29c5f281483e7559efc0a64f..f4f38a63e904fcbd50d9119e2f46d495e7ef1120 100644 (file)
@@ -284,7 +284,7 @@ Each message begins with the following header:
 The message type field can take one of the following values:
 
 +-------------------------------+---------+
-| Messages to OSPF deamon       | Value   |
+| Messages to OSPF daemon       | Value   |
 +===============================+=========+
 | MSG\_REGISTER\_OPAQUETYPE     | 1       |
 +-------------------------------+---------+
@@ -300,7 +300,7 @@ The message type field can take one of the following values:
 +-------------------------------+---------+
 
 +-----------------------------+---------+
-| Messages from OSPF deamon   | Value   |
+| Messages from OSPF daemon   | Value   |
 +=============================+=========+
 | MSG\_REPLY                  | 10      |
 +-----------------------------+---------+
index 4a673b155b1670f0c88f77aaa05cb39c4e7832b2..23bc803d76368f32d17ee0958e0e99e9e16915fb 100644 (file)
@@ -31,7 +31,7 @@ Implementation details
 Concepts
 ^^^^^^^^
 
-Segment Routing used 3 differents OPAQUE LSA in OSPF to carry the various
+Segment Routing used 3 different OPAQUE LSA in OSPF to carry the various
 information:
 
 * **Router Information:** flood the Segment Routing capabilities of the node.
@@ -40,7 +40,7 @@ information:
 * **Extended Link:** flood the Adjaceny and Lan Adjacency Segment Identifier
 * **Extended Prefix:** flood the Prefix Segment Identifier
 
-The implementation follow previous TE and Router Information codes. It used the
+The implementation follows previous TE and Router Information codes. It used the
 OPAQUE LSA functions defined in ospf_opaque.[c,h] as well as the OSPF API. This
 latter is mandatory for the implementation as it provides the Callback to
 Segment Routing functions (see below) when an Extended Link / Prefix or Router
@@ -71,7 +71,7 @@ The figure below shows the relation between the various files:
   (4.0.0.0), Extended Prefix (7.0.0.X) and Link (8.0.0.X) by ospf_ri.c,
   respectively ospf_ext.c.
 * ospf_ri.c send back to ospf_sr.c received Router Information LSA and update
-  Self Router Information LSA with paramters provided by ospf_sr.c i.e. SRGB
+  Self Router Information LSA with parameters provided by ospf_sr.c i.e. SRGB
   and MSD. It use ospf_opaque.c functions to send/received these Opaque LSAs.
 * ospf_ext.c send back to ospf_sr.c received Extended Prefix and Link Opaque
   LSA and send self Extended Prefix and Link Opaque LSA through ospf_opaque.c
@@ -129,8 +129,8 @@ Opaque LSA it is the `ospf_opaque_lsa_install_hook()`.  For deletion, it is
 Note that incoming LSA which is already present in the LSDB will be inserted
 after the old instance of this LSA remove from the LSDB. Thus, after the first
 time, each incoming LSA will trigger a `delete` following by an `install`. This
-is not very helpfull to handle real LSA deletion. In fact, LSA deletion is done
-by Flushing LSA i.e. flood LSA after seting its age to MAX_AGE. Then, a garbage
+is not very helpful to handle real LSA deletion. In fact, LSA deletion is done
+by Flushing LSA i.e. flood LSA after setting its age to MAX_AGE. Then, a garbage
 function has the role to remove all LSA with `age == MAX_AGE` in the LSDB. So,
 to handle LSA Flush, the best is to look to the LSA age to determine if it is
 an installation or a future deletion i.e. the flushed LSA is first store in the
@@ -144,7 +144,7 @@ introduced. When this command is activated, function
 `ospf_router_info_update_sr()` is called to indicate to Router Information
 process that Segment Routing TLVs must be flood. Same function is called to
 modify the Segment Routing Global Block (SRGB) and Maximum Stack Depth (MSD)
-TLV. Only Shortest Path First (SPF) Algorithm is supported, so no possiblity
+TLV. Only Shortest Path First (SPF) Algorithm is supported, so no possibility
 to modify this TLV is offer by the code.
 
 When Opaque LSA Tyep 4 i.e. Router Information are stored in LSDB, function
@@ -159,8 +159,8 @@ Extended Link Prefix LSAs
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Like for Router Information, Segment Routing is activate at the Extended
-Link/Prefix level with new `segment-routing on` command. This trigger
-automtically the flooding of Extended Link LSA for all ospf interface where
+Link/Prefix level with new `segment-routing on` command. This triggers
+automatically the flooding of Extended Link LSA for all ospf interfaces where
 adjacency is full. For Extended Prefix LSA, the new CLI command
 `segment-routing prefix ...` will trigger the flooding of Prefix SID
 TLV/SubTLVs.
@@ -255,7 +255,7 @@ The first segment-routing statement enable it. The Second one set the SRGB,
 third line the MSD and finally, set the Prefix SID index for a given prefix.
 Note that only prefix of Loopback interface could be configured with a Prefix
 SID. It is possible to add `no-php-flag` at the end of the prefix command to
-disbale Penultimate Hop Popping. This advertises peers that they MUST NOT pop
+disable Penultimate Hop Popping. This advertises to peers that they MUST NOT pop
 the MPLS label prior to sending the packet.
 
 Known limitations
index c660f986804fc69761bc7c633a4f468988679d2c..b57286d5a1ecd57c36ef5d468866dadc736eedaa 100644 (file)
@@ -1,3 +1,5 @@
+.. _packaging-debian:
+
 Packaging Debian
 ================
 
diff --git a/doc/developer/packaging-redhat.rst b/doc/developer/packaging-redhat.rst
new file mode 100644 (file)
index 0000000..f6b9931
--- /dev/null
@@ -0,0 +1,85 @@
+.. _packaging-redhat:
+
+Packaging Red Hat
+=================
+
+Tested on CentOS 6, CentOS 7 and Fedora 24.
+
+1. On CentOS 6, refer to :ref:`building-centos6` for details on installing
+   sufficiently up-to-date package versions to enable building FRR.
+
+   Newer automake/autoconf/bison is only needed to build the RPM and is **not**
+   needed to install the binary RPM package.
+
+2. Install the build dependencies for your platform. Refer to the
+   platform-specific build documentation on how to do this.
+
+3. Install the following additional packages::
+
+      yum install rpm-build net-snmp-devel pam-devel libcap-devel
+
+   If your platform uses systemd::
+
+      yum install systemd-devel
+
+   If ``yum`` is not present on your system, use ``dnf`` instead.
+
+3. Checkout FRR::
+
+      git clone https://github.com/frrouting/frr.git frr
+
+4. Run Bootstrap and make distribution tar.gz::
+
+      cd frr
+      ./bootstrap.sh
+      ./configure --with-pkg-extra-version=-MyRPMVersion SPHINXBUILD=sphinx-build2.7
+      make dist
+
+   .. note::
+
+      The only ``configure`` option respected when building RPMs is
+      ``--with-pkg-extra-version``.
+
+5. Create RPM directory structure and populate with sources::
+
+     mkdir rpmbuild
+     mkdir rpmbuild/SOURCES
+     mkdir rpmbuild/SPECS
+     cp redhat/*.spec rpmbuild/SPECS/
+     cp frr*.tar.gz rpmbuild/SOURCES/
+
+6. Edit :file:`rpm/SPECS/frr.spec` with configuration as needed.
+
+   Look at the beginning of the file and adjust the following parameters to
+   enable or disable features as required::
+
+      ############### FRRouting (FRR) configure options #################
+      # with-feature options
+      %{!?with_pam:           %global  with_pam           0 }
+      %{!?with_ospfclient:    %global  with_ospfclient    1 }
+      %{!?with_ospfapi:       %global  with_ospfapi       1 }
+      %{!?with_irdp:          %global  with_irdp          1 }
+      %{!?with_rtadv:         %global  with_rtadv         1 }
+      %{!?with_ldpd:          %global  with_ldpd          1 }
+      %{!?with_nhrpd:         %global  with_nhrpd         1 }
+      %{!?with_eigrp:         %global  with_eigrpd        1 }
+      %{!?with_shared:        %global  with_shared        1 }
+      %{!?with_multipath:     %global  with_multipath     256 }
+      %{!?frr_user:           %global  frr_user           frr }
+      %{!?vty_group:          %global  vty_group          frrvty }
+      %{!?with_fpm:           %global  with_fpm           0 }
+      %{!?with_watchfrr:      %global  with_watchfrr      1 }
+      %{!?with_bgp_vnc:       %global  with_bgp_vnc       0 }
+      %{!?with_pimd:          %global  with_pimd          1 }
+      %{!?with_rpki:          %global  with_rpki          0 }
+
+7. Build the RPM::
+
+      rpmbuild --define "_topdir `pwd`/rpmbuild" -ba rpmbuild/SPECS/frr.spec
+
+   If building with RPKI, then download and install the additional RPKI
+   packages from
+   https://ci1.netdef.org/browse/RPKI-RTRLIB/latestSuccessful/artifact
+
+If all works correctly, then you should end up with the RPMs under
+:file:`rpmbuild/RPMS` and the source RPM under :file:`rpmbuild/SRPMS`.
index 27e6e155fb1c25f36e9829d663f1b50be30a1bcd..b174a9660c2d206373e40c9dd8bc49f07daeb52c 100644 (file)
@@ -7,3 +7,4 @@ Packaging
 
    maintainer-release-build
    packaging-debian
+   packaging-redhat
index d7699136745fb14f6dedbd96b06edf8acf74b64e..7ae48881abb87a338bf0d43ea8c2e13502bd1346 100644 (file)
@@ -5,13 +5,12 @@
 dev_RSTFILES = \
        doc/developer/bgp-typecodes.rst \
        doc/developer/bgpd.rst \
-       doc/developer/building-frr-for-openwrt.rst \
        doc/developer/building-frr-for-alpine.rst \
        doc/developer/building-frr-for-centos6.rst \
        doc/developer/building-frr-for-centos7.rst \
        doc/developer/building-frr-for-debian8.rst \
        doc/developer/building-frr-for-debian9.rst \
-       doc/developer/building-frr-for-fedora24.rst \
+       doc/developer/building-frr-for-fedora.rst \
        doc/developer/building-frr-for-freebsd10.rst \
        doc/developer/building-frr-for-freebsd11.rst \
        doc/developer/building-frr-for-freebsd9.rst \
@@ -19,6 +18,7 @@ dev_RSTFILES = \
        doc/developer/building-frr-for-netbsd7.rst \
        doc/developer/building-frr-for-omnios.rst \
        doc/developer/building-frr-for-openbsd6.rst \
+       doc/developer/building-frr-for-openwrt.rst \
        doc/developer/building-frr-for-ubuntu1404.rst \
        doc/developer/building-frr-for-ubuntu1604.rst \
        doc/developer/building-frr-for-ubuntu1804.rst \
@@ -27,6 +27,7 @@ dev_RSTFILES = \
        doc/developer/cli.rst \
        doc/developer/conf.py \
        doc/developer/hooks.rst \
+       doc/developer/include-compile.rst \
        doc/developer/index.rst \
        doc/developer/library.rst \
        doc/developer/logging.rst \
@@ -37,8 +38,9 @@ dev_RSTFILES = \
        doc/developer/ospf-api.rst \
        doc/developer/ospf-sr.rst \
        doc/developer/ospf.rst \
-       doc/developer/packaging.rst \
        doc/developer/packaging-debian.rst \
+       doc/developer/packaging-redhat.rst
+       doc/developer/packaging.rst \
        doc/developer/testing.rst \
        doc/developer/topotests-snippets.rst \
        doc/developer/topotests.rst \
index 649229b43341b6557a42064c41c5004e102fb210..fb3c928a77d57dae678b952a6d210fdbfcd651e6 100644 (file)
@@ -48,17 +48,17 @@ A sample of this snippet in a test can be found `here
 Interacting with equipment
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-You might want to interact with the topology equipments during the tests and
+You might want to interact with the topology equipment during the tests and
 there are different ways to do so.
 
 Notes:
 
-1. When using the Topogen API, all the equipments code derive from ``Topogear``
+1. When using the Topogen API, all the equipment code derives from ``Topogear``
    (`lib/topogen.py <lib/topogen.py>`__). If you feel brave you can look by
-   yourself how the abstractions that will be mentioned here works.
+   yourself how the abstractions that will be mentioned here work.
 
 2. When not using the ``Topogen`` API there is only one way to interact with
-   the equipments, which is by calling the ``mininet`` API functions directly
+   the equipment, which is by calling the ``mininet`` API functions directly
    to spawn commands.
 
 Interacting with the Linux sandbox
@@ -149,7 +149,7 @@ Translating vtysh JSON output into Python structures:
 
 .. note::
 
-   ``vtysh_(multi)cmd`` is only available for router type of equipments.
+   ``vtysh_(multi)cmd`` is only available for router types of equipment.
 
 Invoking mininet CLI
 ^^^^^^^^^^^^^^^^^^^^
@@ -195,7 +195,7 @@ Loading JSON from a file:
 Comparing JSON output
 ^^^^^^^^^^^^^^^^^^^^^
 
-After obtaining JSON output formated with Python data structures, you may use
+After obtaining JSON output formatted with Python data structures, you may use
 it to assert a minimalist schema:
 
 .. code:: py
index aa06c8dffd7defd9b373557c29f9097fc9a39b44..605b9c9a0cfeb588742850be73e8e94de4d13228 100644 (file)
@@ -151,7 +151,7 @@ Collect Memory Leak Information
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 FRR processes have the capabilities to report remaining memory allocations upon
-exit. To enable the reporting of the memory, define an enviroment variable
+exit. To enable the reporting of the memory, define an environment variable
 ``TOPOTESTS_CHECK_MEMLEAK`` with the file prefix, i.e.::
 
    export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_"
@@ -410,7 +410,7 @@ Defining the Topology
 The first step to write a new test is to define the topology. This step can be
 done in many ways, but the recommended is to use Graphviz to generate a drawing
 of the topology. It allows us to see the topology graphically and to see the
-names of equipments, links and addresses.
+names of equipment, links and addresses.
 
 Here is an example of Graphviz dot file that generates the template topology
 :file:`tests/topotests/example-test/test_template.dot` (the inlined code might
index 4a52eb0544ac8c713f3d8ce0ac466c9e3d5cbecf..160676a7b1f7eb7c909f282940316fae11945c58 100644 (file)
@@ -43,7 +43,7 @@ simplifying the output. This is discussed in :ref:`vtysh-configuration`.
 Command Extraction
 ------------------
 
-When VTYSH is built, a Perl script named :file:`extract.pl` searches the FRR
+When VTYSH is built, a Perl script named :file:`extract.pl` searches the FRR
 codebase looking for ``DEFUN``'s. It extracts these ``DEFUN``'s, transforms
 them into ``DEFSH``'s and appends them to ``vtysh_cmd.c``. Each ``DEFSH``
 contains the name of the command plus ``_vtysh``, as well as a flag that
@@ -167,7 +167,7 @@ Protocol
 VTYSH communicates with FRR daemons by way of domain socket. Each daemon
 creates its own socket, typically in :file:`/var/run/frr/<daemon>.vty`. The
 protocol is very simple. In the VTYSH to daemon direction, messages are simply
-NULL-terminated strings, whose content are CLI commands. Here is a typical
+NUL-terminated strings, whose content are CLI commands. Here is a typical
 message from VTYSH to a daemon:
 
 ::
@@ -178,7 +178,7 @@ message from VTYSH to a daemon:
    00000010: 6c0a 00                                  l..
 
 
-The response format has some more data in it. First is a NULL-terminated string
+The response format has some more data in it. First is a NUL-terminated string
 containing the plaintext response, which is just the output of the command that
 was sent in the request. This is displayed to the user. The plaintext response
 is followed by 3 null marker bytes, followed by a 1-byte status code that
index 1bb0886fd58d94d085468ba8f9a175fd5dc0e61f..b3b3a47cb03c6bbf64abc2df8742344930f1d7ed 100644 (file)
@@ -99,9 +99,14 @@ Bugfix releases are made as needed at 1 month intervals until the next
 ``MAJOR.MINOR`` release branch is pulled. Depending on the severity of the bugs,
 bugfix releases may occur sooner.
 
-Bugfixes are applied to the two most recent releases. Security fixes are
-backported to all releases less than or equal to at least one year old. Security
-fixes may also be backported to older releases depending on severity.
+Bugfixes are applied to the two most recent releases. However, backporting of bug
+fixes to older than the two most recent releases will not be prevented, if acked
+under the classical development workflow applying for a pull request.
+
+Security fixes are backported to all releases less than or equal to at least one
+year old. Security fixes may also be backported to older releases depending on
+severity.
+
 
 Long term support branches ( LTS )
 -----------------------------------------
@@ -128,7 +133,7 @@ branch is required. The work can be shared by multiple people. In all cases, the
 must be at least one person that is in charge of the maintenance branch. The person
 on people responsible for a maintenance branch must be a FRR maintainer. Note that
 they may choose to abandon support for the maintenance branch at any time. If
-noone takes over the responsibility of the LTS branch, then the support will be
+no one takes over the responsibility of the LTS branch, then the support will be
 discontinued.
 
 The LTS branch duties are the following ones:
@@ -371,7 +376,7 @@ system in which submissions from an individual representing one company should
 be merged by someone unaffiliated with that company.
 
 Guidelines for code review
-""""""""""""""""""""""""""
+--------------------------
 
 - As a rule of thumb, the depth of the review should be proportional to the
   scope and / or impact of the patch.
index f57bc1d27868eecc379211746d44bad55e19ef32..46240de1c0a1244679408c63de9ed88e3d7bdf5e 100644 (file)
@@ -129,7 +129,7 @@ language = None
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build', 'common-options.rst', 'epilogue.rst', 'defines.rst']
+exclude_patterns = ['_build', 'common-options.rst', 'epilogue.rst', 'defines.rst', 'bfd-options.rst']
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
index e1f7ec4ce83dd42592fd60da149ce4e677441cdb..cdf5e1967e47f340933b58572b8bbfb19ad20172 100644 (file)
@@ -1,3 +1,3 @@
 .. |synopsis-options| replace:: [-d|-t|-dt] [-C] [-f config-file] [-i pid-file] [-z zclient-path] [-u user] [-g group] [-A vty-addr] [-P vty-port] [-M module[:options]] [-N pathspace] [--vty_socket vty-path] [--moduledir module-path]
 .. |synopsis-options-hv| replace:: [-h] [-v]
-.. |seealso-programs| replace:: zebra(8), vtysh(1), ripd(8), ripngd(8), ospfd(8), ospf6d(8), bgpd(8), isisd(8), babeld(8), nhrpd(8), pimd(8), pbrd(8), ldpd(8), eigrpd(8), staticd(8), mtracebis(8)
+.. |seealso-programs| replace:: zebra(8), vtysh(1), ripd(8), ripngd(8), ospfd(8), ospf6d(8), bgpd(8), isisd(8), babeld(8), nhrpd(8), pimd(8), pbrd(8), ldpd(8), eigrpd(8), staticd(8), fabricd(8), mtracebis(8)
index 8201fdf1b91b076d71e88a4afe7c95652dd69b62..8fbea29ee7ec42aef3cc83d2101d35baa2877422 100644 (file)
@@ -390,7 +390,7 @@ Terminal Mode Commands
 .. index:: find COMMAND...
 .. clicmd:: find COMMAND...
 
-   This commmand performs a simple substring search across all defined commands
+   This command performs a simple substring search across all defined commands
    in all modes. As an example, suppose you're in enable mode and can't
    remember where the command to turn OSPF segment routing on is:
 
index 5b453e75c3b9ef0f1b20fc753e3349e06635502a..be331ffb99577f7c680bbf97fccbff729c9e7b83 100644 (file)
@@ -511,8 +511,8 @@ cause may lead to routing instability or oscillation across multiple speakers
 in iBGP topologies. This can occur with full-mesh iBGP, but is particularly
 problematic in non-full-mesh iBGP topologies that further reduce the routing
 information known to each speaker. This has primarily been documented with iBGP
-route-reflection topologies. However, any route-hiding technologies potentially
-could also exacerbate oscillation with MED.
+:ref:`route-reflection <bgp-route-reflector>` topologies. However, any
+route-hiding technologies potentially could also exacerbate oscillation with MED.
 
 This second issue occurs where speakers each have only a subset of routes, and
 there are cycles in the preferences between different combinations of routes -
@@ -1145,7 +1145,7 @@ is 4 octet long. The following format is used to define the community value.
    ``graceful-shutdown`` represents well-known communities value
    ``GRACEFUL_SHUTDOWN`` ``0xFFFF0000`` ``65535:0``. :rfc:`8326` implements
    the purpose Graceful BGP Session Shutdown to reduce the amount of
-   lost traffic when taking BGP sessions down for maintainance. The use
+   lost traffic when taking BGP sessions down for maintenance. The use
    of the community needs to be supported from your peers side to
    actually have any effect.
 
@@ -1176,20 +1176,20 @@ is 4 octet long. The following format is used to define the community value.
 ``llgr-stale``
    ``llgr-stale`` represents well-known communities value ``LLGR_STALE``
    ``0xFFFF0006`` ``65535:6``.
-   Assigned and intented only for use with routers supporting the
+   Assigned and intended only for use with routers supporting the
    Long-lived Graceful Restart Capability  as described in
    [Draft-IETF-uttaro-idr-bgp-persistence]_.
-   Routers recieving routes with this community may (depending on
+   Routers receiving routes with this community may (depending on
    implementation) choose allow to reject or modify routes on the
    presence or absence of this community.
 
 ``no-llgr``
    ``no-llgr`` represents well-known communities value ``NO_LLGR``
    ``0xFFFF0007`` ``65535:7``.
-   Assigned and intented only for use with routers supporting the
+   Assigned and intended only for use with routers supporting the
    Long-lived Graceful Restart Capability  as described in
    [Draft-IETF-uttaro-idr-bgp-persistence]_.
-   Routers recieving routes with this community may (depending on
+   Routers receiving routes with this community may (depending on
    implementation) choose allow to reject or modify routes on the
    presence or absence of this community.
 
@@ -1251,7 +1251,7 @@ UPDATE messages.
 There are two types of community list:
 
 standard
-   This type accepts an explicit value for the atttribute.
+   This type accepts an explicit value for the attribute.
 
 expanded
    This type accepts a regular expression. Because the regex must be
@@ -2240,10 +2240,15 @@ Displaying Routes by AS Path
 Route Reflector
 ===============
 
-.. note:: This documentation is woefully incomplete.
+BGP routers connected inside the same AS through BGP belong to an internal
+BGP session, or IBGP. In order to prevent routing table loops, IBGP does not
+advertise IBGP-learned routes to other routers in the same session. As such,
+IBGP requires a full mesh of all peers. For large networks, this quickly becomes
+unscalable. Introducing route reflectors removes the need for the full-mesh.
 
-.. index:: bgp cluster-id A.B.C.D
-.. clicmd:: bgp cluster-id A.B.C.D
+When route reflectors are configured, these will reflect the routes announced
+by the peers configured as clients. A route reflector client is configured
+with:
 
 .. index:: neighbor PEER route-reflector-client
 .. clicmd:: neighbor PEER route-reflector-client
@@ -2251,6 +2256,13 @@ Route Reflector
 .. index:: no neighbor PEER route-reflector-client
 .. clicmd:: no neighbor PEER route-reflector-client
 
+To avoid single points of failure, multiple route reflectors can be configured.
+
+A cluster is a collection of route reflectors and their clients, and is used
+by route reflectors to avoid looping.
+
+.. index:: bgp cluster-id A.B.C.D
+.. clicmd:: bgp cluster-id A.B.C.D
 
 .. _routing-policy:
 
@@ -2469,7 +2481,7 @@ certainly contains silly mistakes, if not serious flaws.
    route-map rm-no-export permit 20
    !
    route-map rm-blackhole permit 10
-    description blackhole, up-pref and ensure it cant escape this AS
+    description blackhole, up-pref and ensure it cannot escape this AS
     set ip next-hop 127.0.0.1
     set local-preference 10
     set community additive no-export
index f6af88cac8124d8c0f2bb6a4548e0cf8fc34bf5d..b274afe8a25fdac34b27f6f2650593329fe7e8fb 100644 (file)
@@ -167,7 +167,7 @@ set.  That VRF will then be selected. The below full configuration example
 depicts how Route Targets are configured and how VRFs and cross VRF
 configuration is done.  Note that the VRF are mapped on Linux Network
 Namespaces. For data traffic to cross VRF boundaries, virtual ethernet
-interfaces are created with private IP adressing scheme.
+interfaces are created with private IP addressing scheme.
 
 .. code-block:: frr
 
@@ -322,7 +322,7 @@ There are some other known issues:
 - The validation procedure depicted in :rfc:`5575` is not available.
 
   This validation procedure has not been implemented, as this feature was not
-  used in the existing setups you shared wih us.
+  used in the existing setups you shared with us.
 
 - The filtering action shaper value, if positive, is not used to apply shaping.
 
index 4e1582ccd8f8a2a57b924b6e89d1f61fd24c05b8..964297292f2ca6c418254eb5ebacb3c18d878069 100644 (file)
@@ -272,10 +272,11 @@ options from the list below.
 .. option:: --enable-multipath=X
 
    Compile FRR with up to X way ECMP supported.  This number can be from 0-999.
-   For backwards compatability with older configure options when setting X = 0,
+   For backwards compatibility with older configure options when setting X = 0,
    we will build FRR with 64 way ECMP.  This is needed because there are
    hardcoded arrays that FRR builds towards, so we need to know how big to
-   make these arrays at build time.
+   make these arrays at build time.  Additionally if this parameter is
+   not passed in FRR will default to 16 ECMP.
 
 .. option:: --enable-shell-access
 
index b6a7cd5de03e172e7e62b077bbda273570644b48..ad0a8639a34a5ff09dc9bb72171aea936731a7b7 100644 (file)
@@ -218,7 +218,7 @@ To start OSPF process you have to specify the OSPF router.
    SPF-triggering event occurs within the hold-time of the previous SPF
    calculation.
 
-   This command supercedes the *timers spf* command in previous FRR
+   This command supersedes the *timers spf* command in previous FRR
    releases.
 
 .. index:: max-metric router-lsa [on-startup|on-shutdown] (5-86400)
index 638767c55777b4a54ee7497c1a24b6875650ec82..6230bf777a46cdcbf8e58eeae6b6823ef149c36a 100644 (file)
@@ -88,7 +88,7 @@ end destination.
 
    When a incoming packet matches the destination prefix specified, take the
    packet and forward according to the nexthops specified.  This command accepts
-   both v4 and v6 prefixes.  This command is used in conjuction of the
+   both v4 and v6 prefixes.  This command is used in conjunction of the
    :clicmd:`match src-ip PREFIX` command for matching.
 
 .. clicmd:: set nexthop-group NAME
index feb77db1e154615802f19cbd70bd6a2e4c4b69ea..f4611c520b16c0e33404647713687df1d2091215 100644 (file)
@@ -210,8 +210,8 @@ is in a vrf, enter the interface command with the vrf keyword at the end.
 
    Set the IGMP version used on this interface. The default value is 3.
 
-.. index:: ip multicat boundary oil WORD
-.. clicmd:: ip multicat boundary oil WORD
+.. index:: ip multicast boundary oil WORD
+.. clicmd:: ip multicast boundary oil WORD
 
    Set a pim multicast boundary, based upon the WORD prefix-list. If a pim join
    or IGMP report is received on this interface and the Group is denied by the
index ca8f1f512fec16c08c614f2a6e3792e6fe3eb8d0..4568c2a9010c3cb34b6b8a40555c24ed350abce9 100644 (file)
@@ -29,7 +29,7 @@ documented elsewhere.
 Using SHARP
 ===========
 
-All sharp commands are under the enable node and preceeded by the ``sharp``
+All sharp commands are under the enable node and preceded by the ``sharp``
 keyword. At present, no sharp commands will be preserved in the config.
 
 .. index:: sharp install
index 9dfe1ea39c905d8755b5181b613b6c7b9607c194..a7bf0c74da0cd6c4e91c045619c5349bc51936de 100644 (file)
@@ -380,7 +380,7 @@ At startup, FRR detects the presence of that file. It detects that the file
 statistics information matches the same file statistics information as
 `/proc/self/ns/net` ( through stat() function). As statistics information
 matches, then `vrf0` stands for the new default namespace name.
-Consequently, the VRF naming `Default` will be overriden by the new discovered
+Consequently, the VRF naming `Default` will be overridden by the new discovered
 namespace name `vrf0`.
 
 For those who don't use VRF backend with *Linux network namespace*, it is
@@ -422,7 +422,7 @@ in routing entry, and can be configured like a route:
 .. index:: [no] ip route NETWORK MASK GATEWAY|INTERFACE label LABEL
 .. clicmd:: [no] ip route NETWORK MASK GATEWAY|INTERFACE label LABEL
 
-   NETWORK ans MASK stand for the IP prefix entry to be added as static
+   NETWORK and MASK stand for the IP prefix entry to be added as static
    route entry.
    GATEWAY is the gateway IP address to reach, in order to reach the prefix.
    INTERFACE is the interface behind which the prefix is located.
index dd29358b07368e78ab625d79291fc8e979a60e3d..815983a3940a195b03a04aadc1e7ef61795c8aac 100644 (file)
@@ -1,35 +1,58 @@
-FROM alpine:3.7 as source-builder
-ARG commit
-RUN apk add --no-cache abuild acct alpine-sdk attr autoconf automake bash \
-    binutils binutils-libs bison bsd-compat-headers build-base \
-    c-ares c-ares-dev ca-certificates cryptsetup-libs curl \
-    device-mapper-libs expat fakeroot flex fortify-headers g++ gcc gdbm \
-    git gmp isl json-c json-c-dev kmod lddtree libacl libatomic libattr \
-    libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc \
-    libgomp libisoburn libisofs libltdl libressl libssh2 \
-    libstdc++ libtool libuuid linux-headers lzip lzo m4 make mkinitfs mpc1 \
-    mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base \
-    patch pax-utils pcre perl pkgconf python2 python2-dev readline \
-    readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs \
-    groff gzip bc py-sphinx
-ADD . /src
-RUN (cd /src && \
-       ./bootstrap.sh && \
-       ./configure \
+# This stage builds a dist tarball from the source
+FROM alpine:edge as source-builder
+
+RUN mkdir -p /src/alpine
+COPY alpine/APKBUILD.in /src/alpine
+RUN source /src/alpine/APKBUILD.in \
+       && echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories \
+       && apk add \
+               --no-cache \
+               --update-cache \
+               $makedepends \
+               gzip
+
+COPY . /src
+ARG PKGVER
+RUN cd /src \
+       && ./bootstrap.sh \
+       && ./configure \
                --enable-numeric-version \
-               --with-pkg-extra-version=_git$commit && \
-       make dist)
-FROM alpine:3.7 as alpine-builder
-RUN apk add --no-cache abuild alpine-sdk && mkdir -p /pkgs/apk
-ADD docker/alpine/alpine-build.sh /usr/bin/
-ADD docker/alpine/builder /etc/sudoers.d
-COPY --from=source-builder /src/*.tar.gz /src/alpine/* /src/tools/etc/frr/daemons* /dist/
+               --with-pkg-extra-version="_git$PKGVER" \
+       && make dist
+
+# This stage builds an apk from the dist tarball
+FROM alpine:edge as alpine-builder
+# Don't use nocache here so that abuild can use the cache
+RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories \
+       && apk add \
+               --update-cache \
+               abuild \
+               alpine-conf \
+               alpine-sdk \
+       && setup-apkcache /var/cache/apk \
+       && mkdir -p /pkgs/apk \
+       && echo 'builder ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+COPY --from=source-builder /src/frr-*.tar.gz /src/alpine/* /dist/
 RUN adduser -D -G abuild builder && chown -R builder /dist /pkgs
 USER builder
-RUN /usr/bin/alpine-build.sh
-FROM alpine:3.7
+RUN cd /dist \
+       && abuild-keygen -a -n \
+       && abuild checksum \
+       && abuild -r -P /pkgs/apk
+
+# This stage installs frr from the apk
+FROM alpine:edge
 RUN mkdir -p /pkgs/apk
 COPY --from=alpine-builder /pkgs/apk/ /pkgs/apk/
-RUN apk add --no-cache tini
-RUN apk add --no-cache --allow-untrusted /pkgs/apk/x86_64/*.apk
+RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories \
+       && apk add \
+               --no-cache \
+               --update-cache \
+               tini \
+       && apk add \
+               --no-cache \
+               --allow-untrusted /pkgs/apk/*/*.apk \
+       && rm -rf /pkgs
+COPY docker/alpine/docker-start /usr/lib/frr/docker-start
 ENTRYPOINT [ "/sbin/tini", "--", "/usr/lib/frr/docker-start" ]
diff --git a/docker/alpine/alpine-build.sh b/docker/alpine/alpine-build.sh
deleted file mode 100755 (executable)
index d4c0311..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-set -e
-
-cd /dist
-
-sudo apk --update add alpine-conf
-sudo setup-apkcache /var/cache/apk
-abuild-keygen -a -n
-abuild checksum
-abuild -r -P /pkgs/apk
index 40ed1194fe6cb23514352d146a30ec2f689b6f0c..22a36877c039d1f0f4301d86a05704b1845b0690 100755 (executable)
@@ -1,17 +1,30 @@
 #!/bin/sh
 
 set -e
-set -v
 set -x
 
 ##
-# commit must be converted to decimal
+# Package version needs to be decimal
 ##
-c=`git rev-parse --short=10 HEAD`
-commit=`printf '%u\n' 0x$c`
-docker build -f docker/alpine/Dockerfile \
-       --build-arg commit=$commit -t frr:alpine-$c .
-id=`docker create frr:alpine-$c`
-docker cp ${id}:/pkgs/ docker
-docker rm $id
-docker rmi frr:alpine-$c
+GITREV="$(git rev-parse --short=10 HEAD)"
+PKGVER="$(printf '%u\n' 0x$GITREV)"
+
+docker build \
+       --pull \
+       --file=docker/alpine/Dockerfile \
+       --build-arg="PKGVER=$PKGVER" \
+       --tag="frr:alpine-builder-$GITREV" \
+       --target=alpine-builder \
+       .
+
+CONTAINER_ID="$(docker create "frr:alpine-builder-$GITREV")"
+docker cp "${CONTAINER_ID}:/pkgs/" docker/alpine
+docker rm "${CONTAINER_ID}"
+
+docker build \
+       --file=docker/alpine/Dockerfile \
+       --build-arg="PKGVER=$PKGVER" \
+       --tag="frr:alpine-$GITREV" \
+       .
+
+docker rmi "frr:alpine-builder-$GITREV"
diff --git a/docker/alpine/builder b/docker/alpine/builder
deleted file mode 100644 (file)
index a950b8a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-builder ALL=(ALL) NOPASSWD:ALL
diff --git a/docker/alpine/docker-start b/docker/alpine/docker-start
new file mode 100755 (executable)
index 0000000..52cfb66
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -e
+
+##
+# For volume mounts...
+##
+chown -R frr:frr /etc/frr
+/usr/lib/frr/frrinit.sh start
+
+# Sleep forever
+exec tail -f /dev/null
index 374114cf559dd279fa4935c895d8e8dddb756df9..4d6d73e20215df475c73c079cafc29bc935d6a91 100644 (file)
@@ -231,7 +231,7 @@ static const char *fsm_state2str(enum eigrp_fsm_events event)
                return "Query from Successor while in active state";
        case EIGRP_FSM_EVENT_LR_FCN:
                return "Last Reply Event, Feasibility not satisfied";
-       };
+       }
 
        return "Unknown";
 }
@@ -314,7 +314,7 @@ eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
                        if (prefix->rij->count)
                                return EIGRP_FSM_KEEP_STATE;
 
-                       zlog_info("All reply received\n");
+                       zlog_info("All reply received");
                        if (head->reported_distance < prefix->fdistance) {
                                return EIGRP_FSM_EVENT_LR_FCS;
                        }
@@ -344,7 +344,7 @@ eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
                        } else if (prefix->rij->count) {
                                return EIGRP_FSM_KEEP_STATE;
                        } else {
-                               zlog_info("All reply received\n");
+                               zlog_info("All reply received");
                                return EIGRP_FSM_EVENT_LR;
                        }
                } else if (msg->packet_type == EIGRP_OPC_UPDATE
@@ -366,7 +366,7 @@ eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
                        if (prefix->rij->count) {
                                return EIGRP_FSM_KEEP_STATE;
                        } else {
-                               zlog_info("All reply received\n");
+                               zlog_info("All reply received");
                                if (head->reported_distance
                                    < prefix->fdistance) {
                                        return EIGRP_FSM_EVENT_LR_FCS;
@@ -390,7 +390,7 @@ eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg)
                        } else if (prefix->rij->count) {
                                return EIGRP_FSM_KEEP_STATE;
                        } else {
-                               zlog_info("All reply received\n");
+                               zlog_info("All reply received");
                                return EIGRP_FSM_EVENT_LR;
                        }
                } else if (msg->packet_type == EIGRP_OPC_UPDATE
index b4d850be086f2da137b54a644f5f0ed090ee7d47..dacd5caeb51f4a48f752325e91c1949240bca1bc 100644 (file)
@@ -577,8 +577,6 @@ static uint16_t eigrp_next_sequence_encode(struct stream *s)
 static uint16_t eigrp_hello_parameter_encode(struct eigrp_interface *ei,
                                             struct stream *s, uint8_t flags)
 {
-       uint16_t length = EIGRP_TLV_PARAMETER_LEN;
-
        // add in the parameters TLV
        stream_putw(s, EIGRP_TLV_PARAMETER);
        stream_putw(s, EIGRP_TLV_PARAMETER_LEN);
@@ -605,7 +603,7 @@ static uint16_t eigrp_hello_parameter_encode(struct eigrp_interface *ei,
        // and set hold time value..
        stream_putw(s, ei->params.v_wait);
 
-       return length;
+       return EIGRP_TLV_PARAMETER_LEN;
 }
 
 /**
index a9b103de471629eaac79f248942db51089cc62e8..fc5bdbdbc5f5214c0545138340c3afeaaa4928c9 100644 (file)
@@ -1499,8 +1499,6 @@ static int eigrp_config_write(struct vty *vty)
 {
        struct eigrp *eigrp;
 
-       int write = 0;
-
        eigrp = eigrp_lookup();
        if (eigrp != NULL) {
                /* Writes 'router eigrp' section to config */
@@ -1525,7 +1523,7 @@ static int eigrp_config_write(struct vty *vty)
                //      config_write_eigrp_distance (vty, eigrp)
        }
 
-       return write;
+       return 0;
 }
 
 void eigrp_vty_show_init(void)
index 5d3e61e6d6bfe0915f0edd55d80a32b646586ec9..d91f05d25442e77cdfcc8cc662f23add696070a4 100644 (file)
@@ -1095,10 +1095,10 @@ void dict_load_end(dict_load_t *load)
                        baselevel = level = 1;
                        complete = tree[0];
 
-                       if (complete != 0) {
+                       if (complete != NULL) {
                                tree[0] = 0;
                                complete->right = dictnil;
-                               while (tree[level] != 0) {
+                               while (tree[level] != NULL) {
                                        tree[level]->right = complete;
                                        complete->parent = tree[level];
                                        complete = tree[level];
@@ -1114,7 +1114,7 @@ void dict_load_end(dict_load_t *load)
                        complete = curr;
 
                        assert(level == baselevel);
-                       while (tree[level] != 0) {
+                       while (tree[level] != NULL) {
                                tree[level]->right = complete;
                                complete->parent = tree[level];
                                complete = tree[level];
@@ -1134,7 +1134,7 @@ void dict_load_end(dict_load_t *load)
                complete = dictnil;
 
        for (i = 0; i < DICT_DEPTH_MAX; i++) {
-               if (tree[i] != 0) {
+               if (tree[i] != NULL) {
                        tree[i]->right = complete;
                        complete->parent = tree[i];
                        complete = tree[i];
index e1cdfc30ea0abbde1d51e4992f1e491cab498e27..62814329eada9289378b4530175871926f5562b8 100644 (file)
@@ -140,12 +140,9 @@ void isis_delete_adj(void *arg)
        /* remove from SPF trees */
        spftree_area_adj_del(adj->circuit->area, adj);
 
-       if (adj->area_addresses)
-               XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
-       if (adj->ipv4_addresses)
-               XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
-       if (adj->ipv6_addresses)
-               XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
+       XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
+       XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
+       XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
 
        adj_mt_finish(adj);
 
index 54a19ad23991138096685f6749ff06114a113679..148b4386616e62979ade3146492a252d7d67a3e4 100644 (file)
@@ -444,7 +444,7 @@ static int open_dlpi_dev(struct isis_circuit *circuit)
                struct strioctl sioc;
 
                pfil.Pf_Priority = 0;
-               pfil.Pf_FilterLen = sizeof(pf_filter) / sizeof(unsigned short);
+               pfil.Pf_FilterLen = array_size(pf_filter);
                memcpy(pfil.Pf_Filter, pf_filter, sizeof(pf_filter));
                /* pfmod does not support transparent ioctls */
                sioc.ic_cmd = PFIOCSETF;
index 9126e40d4233a0fd0d1dbbe47975cbc929812ecd..e74a9baadd2a45cb41adfaa83f145870fd62dfcd 100644 (file)
@@ -80,7 +80,7 @@ struct zebra_privs_t isisd_privs = {
        .vty_group = VTY_GROUP,
 #endif
        .caps_p = _caps_p,
-       .cap_num_p = sizeof(_caps_p) / sizeof(*_caps_p),
+       .cap_num_p = array_size(_caps_p),
        .cap_num_i = 0};
 
 /* isisd options */
index 330da9b216b62a5c760200dacf64f6bb0b3adf57..8e9302963dabdd6dd7c0d11d0c21adf893342474 100644 (file)
@@ -131,7 +131,7 @@ static int process_p2p_hello(struct iih_info *iih)
        if (tw_adj) {
                if (tw_adj->state > ISIS_THREEWAY_DOWN) {
                        if (isis->debugs & DEBUG_ADJ_PACKETS) {
-                               zlog_debug("ISIS-Adj (%s): Rcvd P2P IIH from (%s) with invalid three-way state: %d\n",
+                               zlog_debug("ISIS-Adj (%s): Rcvd P2P IIH from (%s) with invalid three-way state: %d",
                                           iih->circuit->area->area_tag,
                                           iih->circuit->interface->name,
                                           tw_adj->state);
@@ -144,7 +144,7 @@ static int process_p2p_hello(struct iih_info *iih)
                        || tw_adj->neighbor_circuit_id != (uint32_t) iih->circuit->idx)) {
 
                        if (isis->debugs & DEBUG_ADJ_PACKETS) {
-                               zlog_debug("ISIS-Adj (%s): Rcvd P2P IIH from (%s) which lists IS/Circuit different from us as neighbor.\n",
+                               zlog_debug("ISIS-Adj (%s): Rcvd P2P IIH from (%s) which lists IS/Circuit different from us as neighbor.",
                                           iih->circuit->area->area_tag,
                                           iih->circuit->interface->name);
                        }
@@ -1523,7 +1523,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
        }
 
        if (fabricd_initial_sync_is_complete(circuit->area) && resync_needed)
-               zlog_warn("OpenFabric: Needed to resync LSPDB using CSNP!\n");
+               zlog_warn("OpenFabric: Needed to resync LSPDB using CSNP!");
 
        retval = ISIS_OK;
 out:
@@ -2146,11 +2146,11 @@ int send_csnp(struct isis_circuit *circuit, int level)
                 * stop lsp_id in this current CSNP.
                 */
                memcpy(start, stop, ISIS_SYS_ID_LEN + 2);
-               loop = 0;
+               loop = false;
                for (int i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) {
                        if (start[i] < (uint8_t)0xff) {
                                start[i] += 1;
-                               loop = 1;
+                               loop = true;
                                break;
                        }
                }
@@ -2164,7 +2164,6 @@ int send_csnp(struct isis_circuit *circuit, int level)
 int send_l1_csnp(struct thread *thread)
 {
        struct isis_circuit *circuit;
-       int retval = ISIS_OK;
 
        circuit = THREAD_ARG(thread);
        assert(circuit);
@@ -2181,13 +2180,12 @@ int send_l1_csnp(struct thread *thread)
                         isis_jitter(circuit->csnp_interval[0], CSNP_JITTER),
                         &circuit->t_send_csnp[0]);
 
-       return retval;
+       return ISIS_OK;
 }
 
 int send_l2_csnp(struct thread *thread)
 {
        struct isis_circuit *circuit;
-       int retval = ISIS_OK;
 
        circuit = THREAD_ARG(thread);
        assert(circuit);
@@ -2204,7 +2202,7 @@ int send_l2_csnp(struct thread *thread)
                         isis_jitter(circuit->csnp_interval[1], CSNP_JITTER),
                         &circuit->t_send_csnp[1]);
 
-       return retval;
+       return ISIS_OK;
 }
 
 /*
@@ -2329,7 +2327,6 @@ int send_l1_psnp(struct thread *thread)
 {
 
        struct isis_circuit *circuit;
-       int retval = ISIS_OK;
 
        circuit = THREAD_ARG(thread);
        assert(circuit);
@@ -2342,7 +2339,7 @@ int send_l1_psnp(struct thread *thread)
                         isis_jitter(circuit->psnp_interval[0], PSNP_JITTER),
                         &circuit->t_send_psnp[0]);
 
-       return retval;
+       return ISIS_OK;
 }
 
 /*
@@ -2352,7 +2349,6 @@ int send_l1_psnp(struct thread *thread)
 int send_l2_psnp(struct thread *thread)
 {
        struct isis_circuit *circuit;
-       int retval = ISIS_OK;
 
        circuit = THREAD_ARG(thread);
        assert(circuit);
@@ -2366,7 +2362,7 @@ int send_l2_psnp(struct thread *thread)
                         isis_jitter(circuit->psnp_interval[1], PSNP_JITTER),
                         &circuit->t_send_psnp[1]);
 
-       return retval;
+       return ISIS_OK;
 }
 
 /*
index 20f3e62a7418bdd147d43b7082eaa36b4d6b7954..3a864fb356c658eb604f6bf5d7f0ed3480abc5c8 100644 (file)
@@ -504,8 +504,7 @@ void isis_redist_area_finish(struct isis_area *area)
                                redist = &area->redist_settings[protocol][type]
                                                               [level];
                                redist->redist = 0;
-                               if (redist->map_name)
-                                       XFREE(MTYPE_ISIS, redist->map_name);
+                               XFREE(MTYPE_ISIS, redist->map_name);
                        }
                        route_table_finish(area->ext_reach[protocol][level]);
                }
index 5a6c7bc3003718a36561f59771a09a5239482c21..fbb1e5714cc97caf7af1d2042dcc0cbf8629debe 100644 (file)
@@ -1913,7 +1913,7 @@ static void format_item_auth(uint16_t mtid, struct isis_item *i,
        default:
                sbuf_push(buf, indent, "  Unknown (%" PRIu8 ")\n", auth->type);
                break;
-       };
+       }
 }
 
 static void free_item_auth(struct isis_item *i)
@@ -3202,8 +3202,7 @@ void isis_tlvs_set_protocols_supported(struct isis_tlvs *tlvs,
                                       struct nlpids *nlpids)
 {
        tlvs->protocols_supported.count = nlpids->count;
-       if (tlvs->protocols_supported.protocols)
-               XFREE(MTYPE_ISIS_TLV, tlvs->protocols_supported.protocols);
+       XFREE(MTYPE_ISIS_TLV, tlvs->protocols_supported.protocols);
        if (nlpids->count) {
                tlvs->protocols_supported.protocols =
                        XCALLOC(MTYPE_ISIS_TLV, nlpids->count);
index dfe74e325ed0f2831b0e5c303c3d2ae63ac5b2b3..79d79f8911647653be9c590c00fe21dc7235f15b 100644 (file)
@@ -362,6 +362,10 @@ static int isis_zebra_read(int command, struct zclient *zclient,
        if (zapi_route_decode(zclient->ibuf, &api) < 0)
                return -1;
 
+       if (api.prefix.family == AF_INET6
+           && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
+               return 0;
+
        /*
         * Avoid advertising a false default reachability. (A default
         * route installed by IS-IS gets redistributed from zebra back
index 178c203f5e9f64ca66fdcbe617a95e8723ef570f..7e27a64de7bcc20f490b61e3240d0fc945977065 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -34,8 +34,8 @@
 
 DEFINE_MTYPE_STATIC(LIB, BFD_INFO, "BFD info")
 
-int bfd_debug = 0;
-struct bfd_gbl bfd_gbl;
+static int bfd_debug = 0;
+static struct bfd_gbl bfd_gbl;
 
 /*
  * bfd_gbl_init - Initialize the BFD global structure
index b46241ac87a54aca53adf12567120dae5dd1e1f8..559457c11998ec0bbd968b734b5a6fbf826aeabd 100644 (file)
@@ -1277,8 +1277,7 @@ int cmd_execute(struct vty *vty, const char *cmd,
 
        hook_call(cmd_execute_done, vty, cmd_exec);
 
-       if (cmd_out)
-               XFREE(MTYPE_TMP, cmd_out);
+       XFREE(MTYPE_TMP, cmd_out);
 
        return ret;
 }
@@ -2408,8 +2407,7 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel)
 
        ret = zlog_set_file(fullpath, loglevel);
 
-       if (p)
-               XFREE(MTYPE_TMP, p);
+       XFREE(MTYPE_TMP, p);
 
        if (!ret) {
                if (vty)
@@ -2417,8 +2415,7 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel)
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       if (host.logfile)
-               XFREE(MTYPE_HOST, host.logfile);
+       XFREE(MTYPE_HOST, host.logfile);
 
        host.logfile = XSTRDUP(MTYPE_HOST, fname);
 
@@ -2487,8 +2484,7 @@ static void disable_log_file(void)
 {
        zlog_reset_file();
 
-       if (host.logfile)
-               XFREE(MTYPE_HOST, host.logfile);
+       XFREE(MTYPE_HOST, host.logfile);
 
        host.logfile = NULL;
 }
@@ -2637,8 +2633,7 @@ int cmd_banner_motd_file(const char *file)
                return CMD_ERR_NO_FILE;
        in = strstr(rpath, SYSCONFDIR);
        if (in == rpath) {
-               if (host.motdfile)
-                       XFREE(MTYPE_HOST, host.motdfile);
+               XFREE(MTYPE_HOST, host.motdfile);
                host.motdfile = XSTRDUP(MTYPE_HOST, file);
        } else
                success = CMD_WARNING_CONFIG_FAILED;
@@ -2723,8 +2718,7 @@ DEFUN(find,
 /* Set config filename.  Called from vty.c */
 void host_config_set(const char *filename)
 {
-       if (host.config)
-               XFREE(MTYPE_HOST, host.config);
+       XFREE(MTYPE_HOST, host.config);
        host.config = XSTRDUP(MTYPE_HOST, filename);
 }
 
@@ -2904,24 +2898,15 @@ void cmd_terminate(void)
                cmdvec = NULL;
        }
 
-       if (host.name)
-               XFREE(MTYPE_HOST, host.name);
-       if (host.domainname)
-               XFREE(MTYPE_HOST, host.domainname);
-       if (host.password)
-               XFREE(MTYPE_HOST, host.password);
-       if (host.password_encrypt)
-               XFREE(MTYPE_HOST, host.password_encrypt);
-       if (host.enable)
-               XFREE(MTYPE_HOST, host.enable);
-       if (host.enable_encrypt)
-               XFREE(MTYPE_HOST, host.enable_encrypt);
-       if (host.logfile)
-               XFREE(MTYPE_HOST, host.logfile);
-       if (host.motdfile)
-               XFREE(MTYPE_HOST, host.motdfile);
-       if (host.config)
-               XFREE(MTYPE_HOST, host.config);
+       XFREE(MTYPE_HOST, host.name);
+       XFREE(MTYPE_HOST, host.domainname);
+       XFREE(MTYPE_HOST, host.password);
+       XFREE(MTYPE_HOST, host.password_encrypt);
+       XFREE(MTYPE_HOST, host.enable);
+       XFREE(MTYPE_HOST, host.enable_encrypt);
+       XFREE(MTYPE_HOST, host.logfile);
+       XFREE(MTYPE_HOST, host.motdfile);
+       XFREE(MTYPE_HOST, host.config);
 
        list_delete(&varhandlers);
        qobj_finish();
index 0e8669c4b5aed451718f7e47a7bd5eeba0b08003..4757fd951f665d890de648cef60546d5dbdb47fc 100644 (file)
@@ -471,7 +471,7 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)
        struct cmd_token *tok = gn->data;
        const char *color;
 
-       if (wasend == true) {
+       if (wasend) {
                wasend = false;
                return;
        }
index 7cc10a230da54e6ada64740a6c2697c31ffd607c..be40bd2603d5acf78b16e0632aca5e53279d417e 100644 (file)
@@ -32,7 +32,7 @@ DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE, "Distribute list")
 DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_IFNAME, "Dist-list ifname")
 DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_NAME, "Dist-list name")
 
-struct list *dist_ctx_list;
+static struct list *dist_ctx_list;
 
 static struct distribute *distribute_new(void)
 {
@@ -44,16 +44,15 @@ static void distribute_free(struct distribute *dist)
 {
        int i = 0;
 
-       if (dist->ifname)
-               XFREE(MTYPE_DISTRIBUTE_IFNAME, dist->ifname);
+       XFREE(MTYPE_DISTRIBUTE_IFNAME, dist->ifname);
 
-       for (i = 0; i < DISTRIBUTE_MAX; i++)
-               if (dist->list[i])
-                       XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[i]);
+       for (i = 0; i < DISTRIBUTE_MAX; i++) {
+               XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[i]);
+       }
 
-       for (i = 0; i < DISTRIBUTE_MAX; i++)
-               if (dist->prefix[i])
-                       XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[i]);
+       for (i = 0; i < DISTRIBUTE_MAX; i++) {
+               XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[i]);
+       }
 
        XFREE(MTYPE_DISTRIBUTE, dist);
 }
@@ -83,8 +82,7 @@ struct distribute *distribute_lookup(struct distribute_ctx *ctx,
 
        dist = hash_lookup(ctx->disthash, &key);
 
-       if (key.ifname)
-               XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
+       XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
 
        return dist;
 }
@@ -128,8 +126,7 @@ static struct distribute *distribute_get(struct distribute_ctx *ctx,
        ret = hash_get(ctx->disthash, &key,
                       (void *(*)(void *))distribute_hash_alloc);
 
-       if (key.ifname)
-               XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
+       XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
 
        return ret;
 }
@@ -163,8 +160,7 @@ static void distribute_list_set(struct distribute_ctx *ctx,
 
        dist = distribute_get(ctx, ifname);
 
-       if (dist->list[type])
-               XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]);
+       XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]);
        dist->list[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, alist_name);
 
        /* Apply this distribute-list to the interface. */
@@ -210,8 +206,7 @@ static void distribute_list_prefix_set(struct distribute_ctx *ctx,
 
        dist = distribute_get(ctx, ifname);
 
-       if (dist->prefix[type])
-               XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]);
+       XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]);
        dist->prefix[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, plist_name);
 
        /* Apply this distribute-list to the interface. */
diff --git a/lib/event_counter.c b/lib/event_counter.c
deleted file mode 100644 (file)
index 57dbfb5..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2016 Christian Franke
- *
- * This file is part of Quagga.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, you can use, redistribute and/or modify it under the
- * following terms:
- *
- * Quagga is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-
-#include "event_counter.h"
-
-void event_counter_inc(struct event_counter *counter)
-{
-       counter->count++;
-       counter->last = time(NULL);
-}
-
-const char *event_counter_format(const struct event_counter *counter)
-{
-       struct tm last_change_store;
-       struct tm *last_change;
-       char timebuf[sizeof("Thu, 01 Jan 1970 00:00:00 +0000")];
-       static char rv[20 + sizeof("  last: ") + sizeof(timebuf)];
-
-       last_change = localtime_r(&counter->last, &last_change_store);
-       if (!last_change
-           || strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %T %z",
-                       last_change)
-                      == 0) {
-               strlcpy(timebuf, "???", sizeof(timebuf));
-       }
-
-       snprintf(rv, sizeof(rv), "%5llu  last: %s", counter->count,
-                counter->last ? timebuf : "(never)");
-       return rv;
-}
diff --git a/lib/event_counter.h b/lib/event_counter.h
deleted file mode 100644 (file)
index 8ae276f..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2016 Christian Franke
- *
- * This file is part of Quagga.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, you can use, redistribute and/or modify it under the
- * following terms:
- *
- * Quagga is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ZEBRA_EVENT_COUNTER_H
-#define _ZEBRA_EVENT_COUNTER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct event_counter {
-       unsigned long long count;
-       time_t last;
-};
-
-void event_counter_inc(struct event_counter *counter);
-const char *event_counter_format(const struct event_counter *counter);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
index e18597afb07c0a92537c26909516b1b4faa47983..d7fa1a84f8955960e010cb7a673368262103dc9b 100644 (file)
@@ -61,7 +61,7 @@ static void err_key_fini(void)
 /*
  * Global shared hash table holding reference text for all defined errors.
  */
-pthread_mutex_t refs_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t refs_mtx = PTHREAD_MUTEX_INITIALIZER;
 struct hash *refs;
 
 static bool ferr_hash_cmp(const void *a, const void *b)
index 317c1b68b78609d1a8634b080b28c36a8cc9f21a..276df4b4d7da3a3aa7a6d351a930c735ccc044db 100644 (file)
@@ -128,8 +128,7 @@ static struct access_master *access_master_get(afi_t afi)
 /* Allocate new filter structure. */
 static struct filter *filter_new(void)
 {
-       return (struct filter *)XCALLOC(MTYPE_ACCESS_FILTER,
-                                       sizeof(struct filter));
+       return XCALLOC(MTYPE_ACCESS_FILTER, sizeof(struct filter));
 }
 
 static void filter_free(struct filter *filter)
@@ -202,8 +201,7 @@ static int filter_match_zebra(struct filter *mfilter, const struct prefix *p)
 /* Allocate new access list structure. */
 static struct access_list *access_list_new(void)
 {
-       return (struct access_list *)XCALLOC(MTYPE_ACCESS_LIST,
-                                            sizeof(struct access_list));
+       return XCALLOC(MTYPE_ACCESS_LIST, sizeof(struct access_list));
 }
 
 /* Free allocated access_list. */
@@ -242,11 +240,9 @@ static void access_list_delete(struct access_list *access)
        else
                list->head = access->next;
 
-       if (access->name)
-               XFREE(MTYPE_ACCESS_LIST_STR, access->name);
+       XFREE(MTYPE_ACCESS_LIST_STR, access->name);
 
-       if (access->remark)
-               XFREE(MTYPE_TMP, access->remark);
+       XFREE(MTYPE_TMP, access->remark);
 
        access_list_free(access);
 }
index d7f655271b853c5c7ce4d2862ec4a43ca8cf33de..2a18e5cfc6ac1c8692a359268efdd8bb39e0087b 100644 (file)
@@ -110,8 +110,7 @@ void frr_pthread_destroy(struct frr_pthread *fpt)
        pthread_mutex_destroy(&fpt->mtx);
        pthread_mutex_destroy(fpt->running_cond_mtx);
        pthread_cond_destroy(fpt->running_cond);
-       if (fpt->name)
-               XFREE(MTYPE_FRR_PTHREAD, fpt->name);
+       XFREE(MTYPE_FRR_PTHREAD, fpt->name);
        XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond_mtx);
        XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond);
        XFREE(MTYPE_FRR_PTHREAD, fpt);
index cfea238d95b1e34de249b4ac7c3012b3497e7aad..7781beae5e95535a9762605e7ef2178d84321e51 100644 (file)
@@ -176,8 +176,6 @@ int funcname_frrzmq_thread_add_read(struct thread_master *master,
                cb = *cbp;
        else {
                cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb));
-               if (!cb)
-                       return -1;
 
                cb->write.cancelled = 1;
                *cbp = cb;
@@ -286,8 +284,6 @@ int funcname_frrzmq_thread_add_write(struct thread_master *master,
                cb = *cbp;
        else {
                cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb));
-               if (!cb)
-                       return -1;
 
                cb->read.cancelled = 1;
                *cbp = cb;
index 85d968182b042f87a46f7eb33e9802339ca818d3..fd337073f812d30aa77ffea4adf325e47f1eb10d 100644 (file)
@@ -155,13 +155,13 @@ void frrstr_strvec_free(vector v)
 bool begins_with(const char *str, const char *prefix)
 {
        if (!str || !prefix)
-               return 0;
+               return false;
 
        size_t lenstr = strlen(str);
        size_t lenprefix = strlen(prefix);
 
        if (lenprefix > lenstr)
-               return 0;
+               return false;
 
        return strncmp(str, prefix, lenprefix) == 0;
 }
index 20d5879c67784278225635c000c540bc00ccf3d7..c6fd3c04adece80ad9f8930e56f15a5e62935a12 100644 (file)
@@ -44,7 +44,7 @@ void pretty_print_graph(struct vty *vty, struct graph_node *, int, int,
 void init_cmdgraph(struct vty *, struct graph **);
 
 /** shim interface commands **/
-struct graph *nodegraph = NULL, *nodegraph_free = NULL;
+static struct graph *nodegraph = NULL, *nodegraph_free = NULL;
 
 #define check_nodegraph()                                                      \
        do {                                                                   \
index 9f9fc31d3740f9b6d22f9abd9fb3f67aa2632e86..884c8f22af72baabc740bc0af1f758bded705f05 100644 (file)
@@ -33,7 +33,7 @@ DEFINE_MTYPE(LIB, HASH, "Hash")
 DEFINE_MTYPE(LIB, HASH_BACKET, "Hash Bucket")
 DEFINE_MTYPE_STATIC(LIB, HASH_INDEX, "Hash Index")
 
-pthread_mutex_t _hashes_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _hashes_mtx = PTHREAD_MUTEX_INITIALIZER;
 static struct list *_hashes;
 
 struct hash *hash_create_size(unsigned int size,
@@ -95,8 +95,6 @@ static void hash_expand(struct hash *hash)
 
        new_index = XCALLOC(MTYPE_HASH_INDEX,
                            sizeof(struct hash_bucket *) * new_size);
-       if (new_index == NULL)
-               return;
 
        hash->stats.empty = new_size;
 
@@ -324,8 +322,7 @@ void hash_free(struct hash *hash)
        }
        pthread_mutex_unlock(&_hashes_mtx);
 
-       if (hash->name)
-               XFREE(MTYPE_HASH, hash->name);
+       XFREE(MTYPE_HASH, hash->name);
 
        XFREE(MTYPE_HASH_INDEX, hash->index);
        XFREE(MTYPE_HASH, hash);
index 48841c7ee8abd660eaf514545548b0645e1a512d..5fdeb4540bb2598d3bf85b390d3859900ff020d2 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -56,9 +56,6 @@ DEFINE_QOBJ_TYPE(interface)
 DEFINE_HOOK(if_add, (struct interface * ifp), (ifp))
 DEFINE_KOOH(if_del, (struct interface * ifp), (ifp))
 
-/* List of interfaces in only the default VRF */
-int ptm_enable = 0;
-
 /* Compare interface names, returning an integer greater than, equal to, or
  * less than 0, (following the strcmp convention), according to the
  * relationship between ifp1 and ifp2.  Interface names consist of an
@@ -234,8 +231,7 @@ void if_delete(struct interface *ifp)
 
        if_link_params_free(ifp);
 
-       if (ifp->desc)
-               XFREE(MTYPE_TMP, ifp->desc);
+       XFREE(MTYPE_TMP, ifp->desc);
 
        XFREE(MTYPE_IF, ifp);
 }
@@ -397,6 +393,7 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id)
        struct interface *ifp;
 
        switch (vrf_get_backend()) {
+       case VRF_BACKEND_UNKNOWN:
        case VRF_BACKEND_NETNS:
                ifp = if_lookup_by_name(name, vrf_id);
                if (ifp)
@@ -708,8 +705,7 @@ void connected_free(struct connected *connected)
        if (connected->destination)
                prefix_free(connected->destination);
 
-       if (connected->label)
-               XFREE(MTYPE_CONNECTED_LABEL, connected->label);
+       XFREE(MTYPE_CONNECTED_LABEL, connected->label);
 
        XFREE(MTYPE_CONNECTED, connected);
 }
@@ -1281,6 +1277,11 @@ static int lib_interface_create(enum nb_event event,
                                  vrf->name);
                        return NB_ERR_VALIDATION;
                }
+
+               /* if VRF is netns or not yet known - init for instance
+                * then assumption is that passed config is exact
+                * then the user intent was not to use an other iface
+                */
                if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
                        ifp = if_lookup_by_name_all_vrf(ifname);
                        if (ifp && ifp->vrf_id != vrf->vrf_id) {
@@ -1349,8 +1350,7 @@ static int lib_interface_description_modify(enum nb_event event,
                return NB_OK;
 
        ifp = yang_dnode_get_entry(dnode, true);
-       if (ifp->desc)
-               XFREE(MTYPE_TMP, ifp->desc);
+       XFREE(MTYPE_TMP, ifp->desc);
        description = yang_dnode_get_string(dnode, NULL);
        ifp->desc = XSTRDUP(MTYPE_TMP, description);
 
@@ -1366,8 +1366,7 @@ static int lib_interface_description_delete(enum nb_event event,
                return NB_OK;
 
        ifp = yang_dnode_get_entry(dnode, true);
-       if (ifp->desc)
-               XFREE(MTYPE_TMP, ifp->desc);
+       XFREE(MTYPE_TMP, ifp->desc);
 
        return NB_OK;
 }
index 53bbcbfe57b6548b542444031303779a0ab0263e..d8236b6b255e3829c446dea3ad6d27b9da18111d 100644 (file)
@@ -31,7 +31,7 @@ DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, "Interface route map container name")
 DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map")
 DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name")
 
-struct list *if_rmap_ctx_list;
+static struct list *if_rmap_ctx_list;
 
 static struct if_rmap *if_rmap_new(void)
 {
@@ -44,13 +44,10 @@ static struct if_rmap *if_rmap_new(void)
 
 static void if_rmap_free(struct if_rmap *if_rmap)
 {
-       if (if_rmap->ifname)
-               XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname);
+       XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname);
 
-       if (if_rmap->routemap[IF_RMAP_IN])
-               XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
-       if (if_rmap->routemap[IF_RMAP_OUT])
-               XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
+       XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
+       XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
 
        XFREE(MTYPE_IF_RMAP, if_rmap);
 }
@@ -65,8 +62,7 @@ struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname)
 
        if_rmap = hash_lookup(ctx->ifrmaphash, &key);
 
-       if (key.ifname)
-               XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
+       XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
 
        return if_rmap;
 }
@@ -106,8 +102,7 @@ static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname)
 
        ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc);
 
-       if (key.ifname)
-               XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
+       XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
 
        return ret;
 }
@@ -136,16 +131,12 @@ static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx,
        if_rmap = if_rmap_get(ctx, ifname);
 
        if (type == IF_RMAP_IN) {
-               if (if_rmap->routemap[IF_RMAP_IN])
-                       XFREE(MTYPE_IF_RMAP_NAME,
-                             if_rmap->routemap[IF_RMAP_IN]);
+               XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
                if_rmap->routemap[IF_RMAP_IN] =
                        XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name);
        }
        if (type == IF_RMAP_OUT) {
-               if (if_rmap->routemap[IF_RMAP_OUT])
-                       XFREE(MTYPE_IF_RMAP_NAME,
-                             if_rmap->routemap[IF_RMAP_OUT]);
+               XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
                if_rmap->routemap[IF_RMAP_OUT] =
                        XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name);
        }
index 935d13772752a2a668fc4d9699793c4addd7845a..f07c56f0a64500b009fe6fa9766bc1f4b51b9abf 100644 (file)
 
 #include <zebra.h>
 
+#include "memory.h"
 #include "queue.h"
 #include "imsg.h"
 
-int imsg_fd_overhead = 0;
+static int imsg_fd_overhead = 0;
 
-int imsg_get_fd(struct imsgbuf *);
+static int imsg_get_fd(struct imsgbuf *);
 
 #ifndef __OpenBSD__
 /*
@@ -35,7 +36,7 @@ static int available_fds(unsigned int n)
        unsigned int i;
        int ret, fds[256];
 
-       if (n > (sizeof(fds) / sizeof(fds[0])))
+       if (n > (unsigned int)array_size(fds))
                return (1);
 
        ret = 0;
index cb6946f37e7c40902153095fb8170419104d2bfc..0d561ef3a4f25db2b60725e9fdb63a0ff2b6af45 100644 (file)
@@ -116,7 +116,7 @@ uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
        /* fallthru */
        case 1:
                a += k[0];
-       };
+       }
 
        __jhash_mix(a, b, c);
 
@@ -151,7 +151,7 @@ uint32_t jhash2(const uint32_t *k, uint32_t length, uint32_t initval)
        /* fallthru */
        case 1:
                a += k[0];
-       };
+       }
 
        __jhash_mix(a, b, c);
 
index 9aa3ef695f3833929e1149e6f1bc2e3aaa0565c4..fc9f0f9cfa95f811a2fef15ab96860babb8edd82 100644 (file)
@@ -32,7 +32,7 @@ DEFINE_QOBJ_TYPE(keychain)
 DEFINE_QOBJ_TYPE(key)
 
 /* Master list of key chain. */
-struct list *keychain_list;
+static struct list *keychain_list;
 
 static struct keychain *keychain_new(void)
 {
@@ -116,8 +116,7 @@ static struct keychain *keychain_get(const char *name)
 
 static void keychain_delete(struct keychain *keychain)
 {
-       if (keychain->name)
-               XFREE(MTYPE_KEYCHAIN, keychain->name);
+       XFREE(MTYPE_KEYCHAIN, keychain->name);
 
        list_delete(&keychain->key);
        listnode_delete(keychain_list, keychain);
@@ -217,8 +216,7 @@ static void key_delete(struct keychain *keychain, struct key *key)
 {
        listnode_delete(keychain->key, key);
 
-       if (key->string)
-               XFREE(MTYPE_KEY, key->string);
+       XFREE(MTYPE_KEY, key->string);
        key_free(key);
 }
 
index 9119b04992aabb62f5c96121686c6576da61d212..1afe30d618486594fe454f1d8816bdb3e7ca2a0f 100644 (file)
@@ -61,7 +61,7 @@ static char dbfile_default[512];
 #endif
 static char vtypath_default[256];
 
-bool debug_memstats_at_exit = 0;
+bool debug_memstats_at_exit = false;
 static bool nodetach_term, nodetach_daemon;
 
 static char comb_optstr[256];
index c424a5bc98ae1d31df7cc6563af701cbbeec8308..8724e0db9349b64618b58568869ce1519a961a7d 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -57,7 +57,7 @@ struct zlog *zlog_default = NULL;
 bool zlog_startup_stderr = true;
 
 /* lock protecting zlog_default for mt-safe zlog */
-pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER;
 
 const char *zlog_priority[] = {
        "emergencies",   "alerts",      "critical",  "errors", "warnings",
@@ -851,8 +851,7 @@ void closezlog(void)
        if (zl->fp != NULL)
                fclose(zl->fp);
 
-       if (zl->filename != NULL)
-               XFREE(MTYPE_ZLOG, zl->filename);
+       XFREE(MTYPE_ZLOG, zl->filename);
 
        XFREE(MTYPE_ZLOG, zl);
        zlog_default = NULL;
@@ -911,8 +910,7 @@ int zlog_reset_file(void)
        logfile_fd = -1;
        zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
 
-       if (zl->filename)
-               XFREE(MTYPE_ZLOG, zl->filename);
+       XFREE(MTYPE_ZLOG, zl->filename);
        zl->filename = NULL;
 
        pthread_mutex_unlock(&loglock);
@@ -993,6 +991,7 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_ROUTER_ID_DELETE),
        DESC_ENTRY(ZEBRA_ROUTER_ID_UPDATE),
        DESC_ENTRY(ZEBRA_HELLO),
+       DESC_ENTRY(ZEBRA_CAPABILITIES),
        DESC_ENTRY(ZEBRA_NEXTHOP_REGISTER),
        DESC_ENTRY(ZEBRA_NEXTHOP_UNREGISTER),
        DESC_ENTRY(ZEBRA_NEXTHOP_UPDATE),
@@ -1014,6 +1013,7 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_VRF_LABEL),
        DESC_ENTRY(ZEBRA_INTERFACE_VRF_UPDATE),
        DESC_ENTRY(ZEBRA_BFD_CLIENT_REGISTER),
+       DESC_ENTRY(ZEBRA_BFD_CLIENT_DEREGISTER),
        DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV),
        DESC_ENTRY(ZEBRA_INTERFACE_DISABLE_RADV),
        DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB),
@@ -1025,6 +1025,9 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC),
        DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK),
        DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK),
+       DESC_ENTRY(ZEBRA_FEC_REGISTER),
+       DESC_ENTRY(ZEBRA_FEC_UNREGISTER),
+       DESC_ENTRY(ZEBRA_FEC_UPDATE),
        DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI),
        DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW),
        DESC_ENTRY(ZEBRA_ADVERTISE_SVI_MACIP),
@@ -1059,6 +1062,11 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_IPSET_DESTROY),
        DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD),
        DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE),
+       DESC_ENTRY(ZEBRA_IPSET_NOTIFY_OWNER),
+       DESC_ENTRY(ZEBRA_IPSET_ENTRY_NOTIFY_OWNER),
+       DESC_ENTRY(ZEBRA_IPTABLE_ADD),
+       DESC_ENTRY(ZEBRA_IPTABLE_DELETE),
+       DESC_ENTRY(ZEBRA_IPTABLE_NOTIFY_OWNER),
        DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL),
 };
 #undef DESC_ENTRY
index 6754b945796ac174041190eec6fd9383a422448e..098c5506846a5e13606511db48ebc545d8963f1d 100644 (file)
@@ -141,8 +141,7 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err,
        return rtinfo;
 
 out_fail:
-       if (rtinfo->load_args)
-               XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
+       XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
        XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
        return NULL;
 }
index ef2f5dc95326d7ddc2d8f48511632f757ee445df..55c66fdc3df2374108b317cba4d04195c1fd4920 100644 (file)
@@ -344,8 +344,7 @@ void ns_delete(struct ns *ns)
        // if_terminate (&ns->iflist);
 
        RB_REMOVE(ns_head, &ns_tree, ns);
-       if (ns->name)
-               XFREE(MTYPE_NS_NAME, ns->name);
+       XFREE(MTYPE_NS_NAME, ns->name);
 
        XFREE(MTYPE_NS, ns);
 }
index d25b470277b40167b6064a8a4719f145c555072c..474abee3091c80e092b48c3b6c94d6ec223a41ab 100644 (file)
@@ -121,12 +121,17 @@ const char *nexthop_type_to_str(enum nexthop_types_t nh_type)
 /*
  * Check if the labels match for the 2 nexthops specified.
  */
-int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2)
+int nexthop_labels_match(const struct nexthop *nh1, const struct nexthop *nh2)
 {
-       struct mpls_label_stack *nhl1, *nhl2;
+       const struct mpls_label_stack *nhl1, *nhl2;
 
        nhl1 = nh1->nh_label;
        nhl2 = nh2->nh_label;
+
+       /* No labels is a match */
+       if (!nhl1 && !nhl2)
+               return 1;
+
        if (!nhl1 || !nhl2)
                return 0;
 
@@ -212,7 +217,8 @@ bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2)
                break;
        }
 
-       return true;
+       /* Compare labels too (if present) */
+       return (!!nexthop_labels_match(nh1, nh2));
 }
 
 /* Update nexthop with label information. */
index fd27ca207bf1a1ffc41ae76eddce681730f01792..9cdb040fc4dd18fecd215ed66aa40780ffdd2a57 100644 (file)
@@ -143,10 +143,12 @@ extern bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2);
 extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
 extern int nexthop_same_no_recurse(const struct nexthop *next1,
                                   const struct nexthop *next2);
-extern int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2);
+extern int nexthop_labels_match(const struct nexthop *nh1,
+                               const struct nexthop *nh2);
 extern int nexthop_same_firsthop(struct nexthop *next1, struct nexthop *next2);
 
-extern const char *nexthop2str(const struct nexthop *nexthop, char *str, int size);
+extern const char *nexthop2str(const struct nexthop *nexthop,
+                              char *str, int size);
 extern struct nexthop *nexthop_next(struct nexthop *nexthop);
 extern unsigned int nexthop_level(struct nexthop *nexthop);
 
index 23ea96f75c24a4332a9f453b218e9757f0fdc887..5fb4ea5234f0f489f32178e4ed72dcf41f07b6d4 100644 (file)
@@ -49,7 +49,7 @@ nexthop_group_cmd_compare(const struct nexthop_group_cmd *nhgc1,
 RB_GENERATE(nhgc_entry_head, nexthop_group_cmd, nhgc_entry,
            nexthop_group_cmd_compare)
 
-struct nhgc_entry_head nhgc_entries;
+static struct nhgc_entry_head nhgc_entries;
 
 static inline int
 nexthop_group_cmd_compare(const struct nexthop_group_cmd *nhgc1,
@@ -118,11 +118,11 @@ void nexthop_del(struct nexthop_group *nhg, struct nexthop *nh)
        nh->next = NULL;
 }
 
-void copy_nexthops(struct nexthop **tnh, struct nexthop *nh,
+void copy_nexthops(struct nexthop **tnh, const struct nexthop *nh,
                   struct nexthop *rparent)
 {
        struct nexthop *nexthop;
-       struct nexthop *nh1;
+       const struct nexthop *nh1;
 
        for (nh1 = nh; nh1; nh1 = nh1->next) {
                nexthop = nexthop_new();
@@ -188,11 +188,25 @@ static int nhgc_cmp_helper(const char *a, const char *b)
        return strcmp(a, b);
 }
 
+static int nhgc_addr_cmp_helper(const union sockunion *a, const union sockunion *b)
+{
+       if (!a && !b)
+               return 0;
+
+       if (a && !b)
+               return -1;
+
+       if (!a && b)
+               return 1;
+
+       return sockunion_cmp(a, b);
+}
+
 static int nhgl_cmp(struct nexthop_hold *nh1, struct nexthop_hold *nh2)
 {
        int ret;
 
-       ret = sockunion_cmp(&nh1->addr, &nh2->addr);
+       ret = nhgc_addr_cmp_helper(nh1->addr, nh2->addr);
        if (ret)
                return ret;
 
@@ -205,11 +219,12 @@ static int nhgl_cmp(struct nexthop_hold *nh1, struct nexthop_hold *nh2)
 
 static void nhgl_delete(struct nexthop_hold *nh)
 {
-       if (nh->intf)
-               XFREE(MTYPE_TMP, nh->intf);
+       XFREE(MTYPE_TMP, nh->intf);
 
-       if (nh->nhvrf_name)
-               XFREE(MTYPE_TMP, nh->nhvrf_name);
+       XFREE(MTYPE_TMP, nh->nhvrf_name);
+
+       if (nh->addr)
+               sockunion_free(nh->addr);
 
        XFREE(MTYPE_TMP, nh);
 }
@@ -294,8 +309,8 @@ static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc,
                nh->nhvrf_name = XSTRDUP(MTYPE_TMP, nhvrf_name);
        if (intf)
                nh->intf = XSTRDUP(MTYPE_TMP, intf);
-
-       nh->addr = *addr;
+       if (addr)
+               nh->addr = sockunion_dup(addr);
 
        listnode_add_sort(nhgc->nhg_list, nh);
 }
@@ -310,7 +325,7 @@ static void nexthop_group_unsave_nhop(struct nexthop_group_cmd *nhgc,
 
        for (ALL_LIST_ELEMENTS_RO(nhgc->nhg_list, node, nh)) {
                if (nhgc_cmp_helper(nhvrf_name, nh->nhvrf_name) == 0 &&
-                   sockunion_cmp(addr, &nh->addr) == 0 &&
+                   nhgc_addr_cmp_helper(addr, nh->addr) == 0 &&
                    nhgc_cmp_helper(intf, nh->intf) == 0)
                        break;
        }
@@ -322,13 +337,7 @@ static void nexthop_group_unsave_nhop(struct nexthop_group_cmd *nhgc,
                return;
 
        list_delete_node(nhgc->nhg_list, node);
-
-       if (nh->nhvrf_name)
-               XFREE(MTYPE_TMP, nh->nhvrf_name);
-       if (nh->intf)
-               XFREE(MTYPE_TMP, nh->intf);
-
-       XFREE(MTYPE_TMP, nh);
+       nhgl_delete(nh);
 }
 
 static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
@@ -349,36 +358,45 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
 
        nhop->vrf_id = vrf->vrf_id;
 
-       if (addr->sa.sa_family == AF_INET) {
-               nhop->gate.ipv4.s_addr = addr->sin.sin_addr.s_addr;
-               if (intf) {
-                       nhop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
-                       nhop->ifindex = ifname2ifindex(intf, vrf->vrf_id);
-                       if (nhop->ifindex == IFINDEX_INTERNAL)
-                               return false;
-               } else
-                       nhop->type = NEXTHOP_TYPE_IPV4;
-       } else {
-               memcpy(&nhop->gate.ipv6, &addr->sin6.sin6_addr, 16);
-               if (intf) {
-                       nhop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
-                       nhop->ifindex = ifname2ifindex(intf, vrf->vrf_id);
-                       if (nhop->ifindex == IFINDEX_INTERNAL)
-                               return false;
-               } else
-                       nhop->type = NEXTHOP_TYPE_IPV6;
+       if (intf) {
+               nhop->ifindex = ifname2ifindex(intf, vrf->vrf_id);
+               if (nhop->ifindex == IFINDEX_INTERNAL)
+                       return false;
        }
 
+       if (addr) {
+               if (addr->sa.sa_family == AF_INET) {
+                       nhop->gate.ipv4.s_addr = addr->sin.sin_addr.s_addr;
+                       if (intf)
+                               nhop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+                       else
+                               nhop->type = NEXTHOP_TYPE_IPV4;
+               } else {
+                       nhop->gate.ipv6 = addr->sin6.sin6_addr;
+                       if (intf)
+                               nhop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+                       else
+                               nhop->type = NEXTHOP_TYPE_IPV6;
+               }
+       } else
+               nhop->type = NEXTHOP_TYPE_IFINDEX;
+
        return true;
 }
 
 DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
-      "[no] nexthop <A.B.C.D|X:X::X:X>$addr [INTERFACE]$intf [nexthop-vrf NAME$name]",
+      "[no] nexthop\
+        <\
+         <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
+         |INTERFACE$intf\
+       >\
+       [nexthop-vrf NAME$name]",
       NO_STR
       "Specify one of the nexthops in this ECMP group\n"
       "v4 Address\n"
       "v6 Address\n"
       "Interface to use\n"
+      "Interface to use\n"
       "If the nexthop is in a different vrf tell us\n"
       "The nexthop-vrf Name\n")
 {
@@ -387,13 +405,6 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
        struct nexthop *nh;
        bool legal;
 
-       /*
-        * This is impossible to happen as that the cli parser refuses
-        * to let you get here without an addr, but the SA system
-        * does not understand this intricacy
-        */
-       assert(addr);
-
        legal = nexthop_group_parse_nexthop(&nhop, addr, intf, name);
 
        if (nhop.type == NEXTHOP_TYPE_IPV6
@@ -482,9 +493,10 @@ static void nexthop_group_write_nexthop_internal(struct vty *vty,
 {
        char buf[100];
 
-       vty_out(vty, "nexthop ");
+       vty_out(vty, "nexthop");
 
-       vty_out(vty, "%s", sockunion2str(&nh->addr, buf, sizeof(buf)));
+       if (nh->addr)
+               vty_out(vty, " %s", sockunion2str(nh->addr, buf, sizeof(buf)));
 
        if (nh->intf)
                vty_out(vty, " %s", nh->intf);
@@ -506,7 +518,7 @@ static int nexthop_group_write(struct vty *vty)
                vty_out(vty, "nexthop-group %s\n", nhgc->name);
 
                for (ALL_LIST_ELEMENTS_RO(nhgc->nhg_list, node, nh)) {
-                       vty_out(vty, "  ");
+                       vty_out(vty, " ");
                        nexthop_group_write_nexthop_internal(vty, nh);
                }
 
@@ -528,7 +540,7 @@ void nexthop_group_enable_vrf(struct vrf *vrf)
                        struct nexthop nhop;
                        struct nexthop *nh;
 
-                       if (!nexthop_group_parse_nexthop(&nhop, &nhh->addr,
+                       if (!nexthop_group_parse_nexthop(&nhop, nhh->addr,
                                                         nhh->intf,
                                                         nhh->nhvrf_name))
                                continue;
@@ -564,7 +576,7 @@ void nexthop_group_disable_vrf(struct vrf *vrf)
                        struct nexthop nhop;
                        struct nexthop *nh;
 
-                       if (!nexthop_group_parse_nexthop(&nhop, &nhh->addr,
+                       if (!nexthop_group_parse_nexthop(&nhop, nhh->addr,
                                                         nhh->intf,
                                                         nhh->nhvrf_name))
                                continue;
@@ -602,7 +614,7 @@ void nexthop_group_interface_state_change(struct interface *ifp,
                                struct nexthop nhop;
 
                                if (!nexthop_group_parse_nexthop(
-                                           &nhop, &nhh->addr, nhh->intf,
+                                           &nhop, nhh->addr, nhh->intf,
                                            nhh->nhvrf_name))
                                        continue;
 
index b14cbb5b5c7314ebd0a7d7d2428bc085765fc24b..d96d0ab9f5d2f55c6008a2413f84f94c81cf9731 100644 (file)
@@ -44,7 +44,7 @@ void nexthop_group_delete(struct nexthop_group **nhg);
 
 void nexthop_add(struct nexthop **target, struct nexthop *nexthop);
 void nexthop_del(struct nexthop_group *nhg, struct nexthop *nexthop);
-void copy_nexthops(struct nexthop **tnh, struct nexthop *nh,
+void copy_nexthops(struct nexthop **tnh, const struct nexthop *nh,
                   struct nexthop *rparent);
 
 /* The following for loop allows to iterate over the nexthop
@@ -68,7 +68,7 @@ void copy_nexthops(struct nexthop **tnh, struct nexthop *nh,
 
 struct nexthop_hold {
        char *nhvrf_name;
-       union sockunion addr;
+       union sockunion *addr;
        char *intf;
 };
 
index 15139aa8d04049f6272b5bdd4a4be25dc03eda85..edf7e0eca6893add20ad0dbbd5927b23d78500ee 100644 (file)
@@ -348,39 +348,58 @@ static void nb_config_diff_del_changes(struct nb_config_cbs *changes)
  * configurations. Given a new subtree, calculate all new YANG data nodes,
  * excluding default leafs and leaf-lists. This is a recursive function.
  */
-static void nb_config_diff_new_subtree(const struct lyd_node *dnode,
-                                      struct nb_config_cbs *changes)
+static void nb_config_diff_created(const struct lyd_node *dnode,
+                                  struct nb_config_cbs *changes)
 {
+       enum nb_operation operation;
        struct lyd_node *child;
 
-       LY_TREE_FOR (dnode->child, child) {
-               enum nb_operation operation;
+       switch (dnode->schema->nodetype) {
+       case LYS_LEAF:
+       case LYS_LEAFLIST:
+               if (lyd_wd_default((struct lyd_node_leaf_list *)dnode))
+                       break;
 
-               switch (child->schema->nodetype) {
-               case LYS_LEAF:
-               case LYS_LEAFLIST:
-                       if (lyd_wd_default((struct lyd_node_leaf_list *)child))
-                               break;
+               if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
+                       operation = NB_OP_CREATE;
+               else if (nb_operation_is_valid(NB_OP_MODIFY, dnode->schema))
+                       operation = NB_OP_MODIFY;
+               else
+                       return;
 
-                       if (nb_operation_is_valid(NB_OP_CREATE, child->schema))
-                               operation = NB_OP_CREATE;
-                       else if (nb_operation_is_valid(NB_OP_MODIFY,
-                                                      child->schema))
-                               operation = NB_OP_MODIFY;
-                       else
-                               continue;
+               nb_config_diff_add_change(changes, operation, dnode);
+               break;
+       case LYS_CONTAINER:
+       case LYS_LIST:
+               if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
+                       nb_config_diff_add_change(changes, NB_OP_CREATE, dnode);
 
-                       nb_config_diff_add_change(changes, operation, child);
-                       break;
-               case LYS_CONTAINER:
-               case LYS_LIST:
-                       if (nb_operation_is_valid(NB_OP_CREATE, child->schema))
-                               nb_config_diff_add_change(changes, NB_OP_CREATE,
-                                                         child);
-                       nb_config_diff_new_subtree(child, changes);
-                       break;
-               default:
-                       break;
+               /* Process child nodes recursively. */
+               LY_TREE_FOR (dnode->child, child) {
+                       nb_config_diff_created(child, changes);
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static void nb_config_diff_deleted(const struct lyd_node *dnode,
+                                  struct nb_config_cbs *changes)
+{
+       if (nb_operation_is_valid(NB_OP_DESTROY, dnode->schema))
+               nb_config_diff_add_change(changes, NB_OP_DESTROY, dnode);
+       else if (CHECK_FLAG(dnode->schema->nodetype, LYS_CONTAINER)) {
+               struct lyd_node *child;
+
+               /*
+                * Non-presence containers need special handling since they
+                * don't have "destroy" callbacks. In this case, what we need to
+                * do is to call the "destroy" callbacks of their child nodes
+                * when applicable (i.e. optional nodes).
+                */
+               LY_TREE_FOR (dnode->child, child) {
+                       nb_config_diff_deleted(child, changes);
                }
        }
 }
@@ -399,42 +418,27 @@ static void nb_config_diff(const struct nb_config *config1,
        for (int i = 0; diff->type[i] != LYD_DIFF_END; i++) {
                LYD_DIFFTYPE type;
                struct lyd_node *dnode;
-               enum nb_operation operation;
 
                type = diff->type[i];
 
                switch (type) {
                case LYD_DIFF_CREATED:
                        dnode = diff->second[i];
-
-                       if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
-                               operation = NB_OP_CREATE;
-                       else if (nb_operation_is_valid(NB_OP_MODIFY,
-                                                      dnode->schema))
-                               operation = NB_OP_MODIFY;
-                       else
-                               continue;
+                       nb_config_diff_created(dnode, changes);
                        break;
                case LYD_DIFF_DELETED:
                        dnode = diff->first[i];
-                       operation = NB_OP_DESTROY;
+                       nb_config_diff_deleted(dnode, changes);
                        break;
                case LYD_DIFF_CHANGED:
                        dnode = diff->second[i];
-                       operation = NB_OP_MODIFY;
+                       nb_config_diff_add_change(changes, NB_OP_MODIFY, dnode);
                        break;
                case LYD_DIFF_MOVEDAFTER1:
                case LYD_DIFF_MOVEDAFTER2:
                default:
                        continue;
                }
-
-               nb_config_diff_add_change(changes, operation, dnode);
-
-               if (type == LYD_DIFF_CREATED
-                   && CHECK_FLAG(dnode->schema->nodetype,
-                                 LYS_CONTAINER | LYS_LIST))
-                       nb_config_diff_new_subtree(dnode, changes);
        }
 
        lyd_free_diff(diff);
index a8e00178194c16bff91f0318e20929e35973bc1c..a499d48c12ad4889ada85ed352c5df0425e0a205 100644 (file)
@@ -1383,7 +1383,7 @@ error:
 
 static int frr_confd_finish(void)
 {
-       if (confd_connected == false)
+       if (!confd_connected)
                return 0;
 
        frr_confd_finish_cdb();
index 41c8e4f8c0246fdc9b0921c77f7c33db8bf24d83..2a97e1e5b2bfc57c51d8b6fdffe47f02afa60745 100644 (file)
@@ -326,8 +326,7 @@ static void prefix_list_delete(struct prefix_list *plist)
        else
                list->head = plist->next;
 
-       if (plist->desc)
-               XFREE(MTYPE_TMP, plist->desc);
+       XFREE(MTYPE_TMP, plist->desc);
 
        /* Make sure master's recent changed prefix-list information is
           cleared. */
@@ -338,8 +337,7 @@ static void prefix_list_delete(struct prefix_list *plist)
        if (master->delete_hook)
                (*master->delete_hook)(plist);
 
-       if (plist->name)
-               XFREE(MTYPE_MPREFIX_LIST_STR, plist->name);
+       XFREE(MTYPE_MPREFIX_LIST_STR, plist->name);
 
        XFREE(MTYPE_PREFIX_LIST_TRIE, plist->trie);
 
index 1565de216eb0e5f013e754c2edadde057bd36f0a..87b54a681a1d5ed99273bd75723771ac360cb500 100644 (file)
@@ -133,8 +133,6 @@ static int pqueue_expand(struct pqueue *queue)
 
        newarray =
                XCALLOC(MTYPE_PQUEUE_DATA, queue->array_size * DATA_SIZE * 2);
-       if (newarray == NULL)
-               return 0;
 
        memcpy(newarray, queue->array, queue->array_size * DATA_SIZE);
 
index 80a89cc3c707bb86a66d95bf3acf1e2e0b738f68..52bb266f115bcbdd016ac45bdc8398a8d317146d 100644 (file)
@@ -944,8 +944,7 @@ int str2prefix_eth(const char *str, struct prefix_eth *p)
        ret = 1;
 
 done:
-       if (cp)
-               XFREE(MTYPE_TMP, cp);
+       XFREE(MTYPE_TMP, cp);
 
        return ret;
 }
@@ -1503,8 +1502,7 @@ char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size)
        if (!mac)
                return NULL;
        if (!buf)
-               ptr = (char *)XMALLOC(MTYPE_TMP,
-                                     ETHER_ADDR_STRLEN * sizeof(char));
+               ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
        else {
                assert(size >= ETHER_ADDR_STRLEN);
                ptr = buf;
@@ -1585,8 +1583,7 @@ char *esi_to_str(const esi_t *esi, char *buf, int size)
        if (!esi)
                return NULL;
        if (!buf)
-               ptr = (char *)XMALLOC(MTYPE_TMP,
-                                     ESI_STR_LEN * sizeof(char));
+               ptr = XMALLOC(MTYPE_TMP, ESI_STR_LEN * sizeof(char));
        else {
                assert(size >= ESI_STR_LEN);
                ptr = buf;
index ae931288c02527736a18a039d3876f8d459aebcf..a1c2086b8db4e6727a6f6d1401ec1d2b4d5c0e28 100644 (file)
@@ -511,6 +511,19 @@ static inline int is_host_route(struct prefix *p)
        return 0;
 }
 
+static inline int is_default_host_route(struct prefix *p)
+{
+       if (p->family == AF_INET) {
+               return (p->u.prefix4.s_addr == INADDR_ANY &&
+                       p->prefixlen == IPV4_MAX_BITLEN);
+       } else if (p->family == AF_INET6) {
+               return ((!memcmp(&p->u.prefix6, &in6addr_any,
+                                sizeof(struct in6_addr))) &&
+                       p->prefixlen == IPV6_MAX_BITLEN);
+       }
+       return 0;
+}
+
 #ifdef __cplusplus
 }
 #endif
index 2932800070cce1f5143807ec014ee75caf5651a3..59f24afe4a5aecc4a84f47b18a778401ed8d4dd1 100644 (file)
@@ -706,13 +706,21 @@ struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
        if (!privs)
                return NULL;
 
-       errno = 0;
-       if (privs->change(ZPRIVS_RAISE)) {
-               zlog_err("%s: Failed to raise privileges (%s)",
-                        funcname, safe_strerror(errno));
+       /* If we're already elevated, just return */
+       pthread_mutex_lock(&(privs->mutex));
+       {
+               if (++(privs->refcount) == 1) {
+                       errno = 0;
+                       if (privs->change(ZPRIVS_RAISE)) {
+                               zlog_err("%s: Failed to raise privileges (%s)",
+                                        funcname, safe_strerror(errno));
+                       }
+                       errno = save_errno;
+                       privs->raised_in_funcname = funcname;
+               }
        }
-       errno = save_errno;
-       privs->raised_in_funcname = funcname;
+       pthread_mutex_unlock(&(privs->mutex));
+
        return privs;
 }
 
@@ -723,13 +731,22 @@ void _zprivs_lower(struct zebra_privs_t **privs)
        if (!*privs)
                return;
 
-       errno = 0;
-       if ((*privs)->change(ZPRIVS_LOWER)) {
-               zlog_err("%s: Failed to lower privileges (%s)",
-                        (*privs)->raised_in_funcname, safe_strerror(errno));
+       /* Don't lower privs if there's another caller */
+       pthread_mutex_lock(&(*privs)->mutex);
+       {
+               if (--((*privs)->refcount) == 0) {
+                       errno = 0;
+                       if ((*privs)->change(ZPRIVS_LOWER)) {
+                               zlog_err("%s: Failed to lower privileges (%s)",
+                                        (*privs)->raised_in_funcname,
+                                        safe_strerror(errno));
+                       }
+                       errno = save_errno;
+                       (*privs)->raised_in_funcname = NULL;
+               }
        }
-       errno = save_errno;
-       (*privs)->raised_in_funcname = NULL;
+       pthread_mutex_unlock(&(*privs)->mutex);
+
        *privs = NULL;
 }
 
@@ -743,6 +760,9 @@ void zprivs_preinit(struct zebra_privs_t *zprivs)
                exit(1);
        }
 
+       pthread_mutex_init(&(zprivs->mutex), NULL);
+       zprivs->refcount = 0;
+
        if (zprivs->vty_group) {
                /* in a "NULL" setup, this is allowed to fail too, but still
                 * try. */
index 1fee423a95e35dff57d1e332aac9fc73afab6f5a..01ddba46223e207a7eecca88a867dddce71e96af 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef _ZEBRA_PRIVS_H
 #define _ZEBRA_PRIVS_H
 
+#include <pthread.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -59,6 +61,14 @@ struct zebra_privs_t {
        zebra_capabilities_t *caps_i; /* caps to allow inheritance of */
        int cap_num_p;                /* number of caps in arrays */
        int cap_num_i;
+
+       /* Mutex and counter used to avoid race conditions in multi-threaded
+        * processes. The privs elevation is process-wide, so we need to
+        * avoid changing the privilege status across threads.
+        */
+       pthread_mutex_t mutex;
+       uint32_t refcount;
+
        const char *user; /* user and group to run as */
        const char *group;
        const char *vty_group; /* group to chown vty socket to */
index 7c1ee2353c6719a554df6f011b0d75683ca98ef2..4898a8d0fa776e0650a6b440f4a3e8aa4b201e97 100644 (file)
@@ -538,10 +538,8 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
                break;
        }
 
-       if (dep_name)
-               XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
-       if (rmap_name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+       XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
 
        return retval;
 }
@@ -1075,8 +1073,7 @@ static void route_map_index_delete(struct route_map_index *index, int notify)
                index->map->head = index->next;
 
        /* Free 'char *nextrm' if not NULL */
-       if (index->nextrm)
-               XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm);
+       XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm);
 
        /* Execute event hook. */
        if (route_map_master.event_hook && notify) {
@@ -1231,8 +1228,7 @@ static void route_map_rule_delete(struct route_map_rule_list *list,
        if (rule->cmd->func_free)
                (*rule->cmd->func_free)(rule->value);
 
-       if (rule->rule_str)
-               XFREE(MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str);
+       XFREE(MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str);
 
        if (rule->next)
                rule->next->prev = rule->prev;
@@ -1779,8 +1775,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name,
                }
 
                ret_map_name = (char *)hash_release(dep->dep_rmap_hash, rname);
-               if (ret_map_name)
-                       XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name);
+               XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name);
 
                if (!dep->dep_rmap_hash->count) {
                        dep = hash_release(dephash, dname);
index 57b41503e1c142d5c4c6b7b8f18da96c80ae8225..f00ff4921e59ecd1757b2eaf7517034a55e8061b 100644 (file)
@@ -38,7 +38,7 @@
 
 
 /* master signals descriptor struct */
-struct quagga_sigevent_master_t {
+static struct quagga_sigevent_master_t {
        struct thread *t;
 
        struct quagga_signal_t *signals;
index f245560c45829cd5e41a11f0e8f527248bf59b13..3b14be46767b5fbbb26bfce5f7e10c3c5872571d 100644 (file)
@@ -18,7 +18,6 @@ lib_libfrr_la_SOURCES = \
        lib/csv.c \
        lib/debug.c \
        lib/distribute.c \
-       lib/event_counter.c \
        lib/ferr.c \
        lib/filter.c \
        lib/frr_pthread.c \
@@ -144,7 +143,6 @@ pkginclude_HEADERS += \
        lib/db.h \
        lib/debug.h \
        lib/distribute.h \
-       lib/event_counter.h \
        lib/ferr.h \
        lib/fifo.h \
        lib/filter.h \
index 055587434ccfc9ec06d0877b910e5487ebd7e9e1..2760b83fb3c4aadd4d3f31cda56e654d8c7f3288 100644 (file)
@@ -52,10 +52,10 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
        } while (0);
 
 /* control variable for initializer */
-pthread_once_t init_once = PTHREAD_ONCE_INIT;
+static pthread_once_t init_once = PTHREAD_ONCE_INIT;
 pthread_key_t thread_current;
 
-pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
 static struct list *masters;
 
 static void thread_free(struct thread_master *master, struct thread *thread);
@@ -93,10 +93,9 @@ static void cpu_record_hash_free(void *a)
 static void vty_out_cpu_thread_history(struct vty *vty,
                                       struct cpu_thread_history *a)
 {
-       vty_out(vty, "%5"PRIdFAST32" %10lu.%03lu %9"PRIuFAST32
-               " %8lu %9lu %8lu %9lu", a->total_active,
-               a->cpu.total / 1000, a->cpu.total % 1000, a->total_calls,
-               a->cpu.total / a->total_calls, a->cpu.max,
+       vty_out(vty, "%5zu %10zu.%03lu %9zu %8zu %9zu %8lu %9lu",
+               a->total_active, a->cpu.total / 1000, a->cpu.total % 1000,
+               a->total_calls, a->cpu.total / a->total_calls, a->cpu.max,
                a->real.total / a->total_calls, a->real.max);
        vty_out(vty, " %c%c%c%c%c %s\n",
                a->types & (1 << THREAD_READ) ? 'R' : ' ',
@@ -414,8 +413,6 @@ struct thread_master *thread_master_create(const char *name)
        pthread_once(&init_once, &initializer);
 
        rv = XCALLOC(MTYPE_THREAD_MASTER, sizeof(struct thread_master));
-       if (rv == NULL)
-               return NULL;
 
        /* Initialize master mutex */
        pthread_mutex_init(&rv->mtx, NULL);
@@ -484,8 +481,7 @@ void thread_master_set_name(struct thread_master *master, const char *name)
 {
        pthread_mutex_lock(&master->mtx);
        {
-               if (master->name)
-                       XFREE(MTYPE_THREAD_MASTER, master->name);
+               XFREE(MTYPE_THREAD_MASTER, master->name);
                master->name = XSTRDUP(MTYPE_THREAD_MASTER, name);
        }
        pthread_mutex_unlock(&master->mtx);
@@ -649,8 +645,7 @@ void thread_master_free(struct thread_master *m)
        hash_free(m->cpu_record);
        m->cpu_record = NULL;
 
-       if (m->name)
-               XFREE(MTYPE_THREAD_MASTER, m->name);
+       XFREE(MTYPE_THREAD_MASTER, m->name);
        XFREE(MTYPE_THREAD_MASTER, m->handler.pfds);
        XFREE(MTYPE_THREAD_MASTER, m->handler.copy);
        XFREE(MTYPE_THREAD_MASTER, m);
index df93bc33b948e0c6c04e2d96967852f7b0ebda38..bc289be9c0c2481b45da71bad39f8cbf5fde8f9f 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -56,6 +56,7 @@ struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id);
 struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name);
 
 static int vrf_backend;
+static int vrf_backend_configured;
 static struct zebra_privs_t *vrf_daemon_privs;
 static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;
 
@@ -63,7 +64,7 @@ static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;
  * Turn on/off debug code
  * for vrf.
  */
-int debug_vrf = 0;
+static int debug_vrf = 0;
 
 /* Holding VRF hooks  */
 struct vrf_master {
@@ -613,12 +614,15 @@ int vrf_is_backend_netns(void)
 
 int vrf_get_backend(void)
 {
+       if (!vrf_backend_configured)
+               return VRF_BACKEND_UNKNOWN;
        return vrf_backend;
 }
 
 void vrf_configure_backend(int vrf_backend_netns)
 {
        vrf_backend = vrf_backend_netns;
+       vrf_backend_configured = 1;
 }
 
 int vrf_handler_create(struct vty *vty, const char *vrfname,
@@ -662,7 +666,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
                                "VRF %u is already configured with VRF %s\n",
                                vrf->vrf_id, vrf->name);
                else
-                       zlog_info("VRF %u is already configured with VRF %s\n",
+                       zlog_info("VRF %u is already configured with VRF %s",
                                  vrf->vrf_id, vrf->name);
                return CMD_WARNING_CONFIG_FAILED;
        }
index b947ab1d52ca1640146baeff242c6f05c93fb28a..d8fedf91116b8b5b6a67bb12e050e53aabd5e3ea 100644 (file)
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -101,8 +101,9 @@ RB_PROTOTYPE(vrf_name_head, vrf, name_entry, vrf_name_compare)
 DECLARE_QOBJ_TYPE(vrf)
 
 /* Allow VRF with netns as backend */
-#define VRF_BACKEND_VRF_LITE 0
-#define VRF_BACKEND_NETNS    1
+#define VRF_BACKEND_VRF_LITE   0
+#define VRF_BACKEND_NETNS      1
+#define VRF_BACKEND_UNKNOWN    2
 
 extern struct vrf_id_head vrfs_by_id;
 extern struct vrf_name_head vrfs_by_name;
index d6fda8cbb4596735b1c648de22ec5046ff1099cc..dae8e825993ba84356c3ef5797bc2221400a2d00 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -93,7 +93,7 @@ struct vty *vty_exclusive_lock;
 static int no_password_check = 0;
 
 /* Integrated configuration file path */
-char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
+static char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
 
 static int do_log_commands = 0;
 
@@ -974,8 +974,7 @@ static void vty_complete_command(struct vty *vty)
        default:
                break;
        }
-       if (matched)
-               XFREE(MTYPE_TMP, matched);
+       XFREE(MTYPE_TMP, matched);
 }
 
 static void vty_describe_fold(struct vty *vty, int cmd_width,
@@ -1169,8 +1168,7 @@ static void vty_hist_add(struct vty *vty)
                }
 
        /* Insert history entry. */
-       if (vty->hist[vty->hindex])
-               XFREE(MTYPE_VTY_HIST, vty->hist[vty->hindex]);
+       XFREE(MTYPE_VTY_HIST, vty->hist[vty->hindex]);
        vty->hist[vty->hindex] = XSTRDUP(MTYPE_VTY_HIST, vty->buf);
 
        /* History index rotation. */
@@ -2232,9 +2230,9 @@ void vty_close(struct vty *vty)
        buffer_free(vty->lbuf);
 
        /* Free command history. */
-       for (i = 0; i < VTY_MAXHIST; i++)
-               if (vty->hist[i])
-                       XFREE(MTYPE_VTY_HIST, vty->hist[i]);
+       for (i = 0; i < VTY_MAXHIST; i++) {
+               XFREE(MTYPE_VTY_HIST, vty->hist[i]);
+       }
 
        /* Unset vector. */
        if (vty->fd != -1)
@@ -2255,8 +2253,7 @@ void vty_close(struct vty *vty)
        if (vty->fd == STDIN_FILENO)
                was_stdio = true;
 
-       if (vty->buf)
-               XFREE(MTYPE_VTY, vty->buf);
+       XFREE(MTYPE_VTY, vty->buf);
 
        if (vty->error) {
                vty->error->del = vty_error_delete;
@@ -2546,8 +2543,7 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
        host_config_set(fullpath);
 
 tmp_free_and_out:
-       if (tmp)
-               XFREE(MTYPE_TMP, tmp);
+       XFREE(MTYPE_TMP, tmp);
 
        return read_success;
 }
@@ -3163,8 +3159,7 @@ void vty_init(struct thread_master *master_thread)
 
 void vty_terminate(void)
 {
-       if (vty_cwd)
-               XFREE(MTYPE_TMP, vty_cwd);
+       XFREE(MTYPE_TMP, vty_cwd);
 
        if (vtyvec && Vvty_serv_thread) {
                vty_reset();
index ca5a2003c46402940ec7fae86c2159cffd1e2d6f..9c2653e1ac0ded45a43a604adbb9f5a63a5bcf69 100644 (file)
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -290,7 +290,6 @@ struct vty_arg {
 #endif
 
 /* Exported variables */
-extern char integrate_default[];
 extern struct vty *vty_exclusive_lock;
 
 /* Prototypes. */
index fa69ec600ec93180ea90ac4e4c27c143601f2991..066d81f35020e66998fe59ec3ce75ef1754ee2b1 100644 (file)
@@ -274,7 +274,7 @@ int work_queue_run(struct thread *thread)
                wq->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY;
 
        STAILQ_FOREACH_SAFE (item, &wq->items, wq, titem) {
-               assert(item && item->data);
+               assert(item->data);
 
                /* dont run items which are past their allowed retries */
                if (item->ran > wq->spec.max_retries) {
index 6273dff3ce8e83cf929e77336b71599b0fb11feb..7ecea5f445469bbbb736b19e62c1f510ba1e31bf 100644 (file)
@@ -62,7 +62,7 @@ bool yang_str2bool(const char *value)
 
 struct yang_data *yang_data_new_bool(const char *xpath, bool value)
 {
-       return yang_data_new(xpath, (value == true) ? "true" : "false");
+       return yang_data_new(xpath, (value) ? "true" : "false");
 }
 
 bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt,
index 9db1dd74f2d91421a679ffbbfa8778ee13b84fcf..92a9d5ef3153923b31bf6340d4575826e55b5406 100644 (file)
@@ -49,13 +49,13 @@ enum event { ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT };
 /* Prototype for event manager. */
 static void zclient_event(enum event, struct zclient *);
 
+struct zclient_options zclient_options_default = {.receive_notify = false};
+
 struct sockaddr_storage zclient_addr;
 socklen_t zclient_addr_len;
 
 /* This file local debug flag. */
-int zclient_debug = 0;
-
-struct zclient_options zclient_options_default = {.receive_notify = false};
+static int zclient_debug;
 
 /* Allocate zclient structure. */
 struct zclient *zclient_new(struct thread_master *master,
@@ -414,6 +414,9 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
        /* We need router-id information. */
        zebra_message_send(zclient, ZEBRA_ROUTER_ID_ADD, vrf_id);
 
+       /* We need interface information. */
+       zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, vrf_id);
+
        /* Set unwanted redistribute route. */
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                vrf_bitmap_set(zclient->redist[afi][zclient->redist_default],
@@ -478,6 +481,8 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
        /* We need router-id information. */
        zebra_message_send(zclient, ZEBRA_ROUTER_ID_DELETE, vrf_id);
 
+       zebra_message_send(zclient, ZEBRA_INTERFACE_DELETE, vrf_id);
+
        /* Set unwanted redistribute route. */
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                vrf_bitmap_unset(zclient->redist[afi][zclient->redist_default],
@@ -629,7 +634,7 @@ void zclient_init(struct zclient *zclient, int redist_default,
        }
 
        if (zclient_debug)
-               zlog_debug("zclient_start is called");
+               zlog_debug("scheduling zclient connection");
 
        zclient_event(ZCLIENT_SCHEDULE, zclient);
 }
@@ -2504,8 +2509,9 @@ static int zclient_read(struct thread *thread)
        length -= ZEBRA_HEADER_SIZE;
 
        if (zclient_debug)
-               zlog_debug("zclient 0x%p command 0x%x VRF %u\n",
-                          (void *)zclient, command, vrf_id);
+               zlog_debug("zclient 0x%p command %s VRF %u",
+                          (void *)zclient, zserv_command_string(command),
+                          vrf_id);
 
        switch (command) {
        case ZEBRA_CAPABILITIES:
@@ -2574,14 +2580,14 @@ static int zclient_read(struct thread *thread)
                break;
        case ZEBRA_NEXTHOP_UPDATE:
                if (zclient_debug)
-                       zlog_debug("zclient rcvd nexthop update\n");
+                       zlog_debug("zclient rcvd nexthop update");
                if (zclient->nexthop_update)
                        (*zclient->nexthop_update)(command, zclient, length,
                                                   vrf_id);
                break;
        case ZEBRA_IMPORT_CHECK_UPDATE:
                if (zclient_debug)
-                       zlog_debug("zclient rcvd import check update\n");
+                       zlog_debug("zclient rcvd import check update");
                if (zclient->import_check_update)
                        (*zclient->import_check_update)(command, zclient,
                                                        length, vrf_id);
@@ -2608,7 +2614,7 @@ static int zclient_read(struct thread *thread)
                break;
        case ZEBRA_FEC_UPDATE:
                if (zclient_debug)
-                       zlog_debug("zclient rcvd fec update\n");
+                       zlog_debug("zclient rcvd fec update");
                if (zclient->fec_update)
                        (*zclient->fec_update)(command, zclient, length);
                break;
index bb5ce0fec6b2c41e65a087a8c020e1ecbf33b0c2..85e941e7bacd1d63fed3300fe7e708df39c4f420 100644 (file)
@@ -110,7 +110,7 @@ static int linux_configure_arp(const char *iface, int on)
 {
        struct ifreq ifr;
 
-       strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
+       strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
        if (ioctl(nhrp_socket_fd, SIOCGIFFLAGS, &ifr))
                return -1;
 
index 4c6827cb3d63536e4976426e02c373d95b397006..6666c6e96bca99553ab31da45477d452386faeb1 100644 (file)
@@ -122,7 +122,7 @@ static int netlink_route_recv(struct thread *t)
 
        zbuf_init(&zb, buf, sizeof(buf), 0);
        while (zbuf_recv(&zb, fd) > 0) {
-               while ((n = znl_nlmsg_pull(&zb, &payload)) != 0) {
+               while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
                        debugf(NHRP_DEBUG_KERNEL,
                               "Netlink: Received msg_type %u, msg_flags %u",
                               n->nlmsg_type, n->nlmsg_flags);
@@ -217,7 +217,7 @@ static int netlink_log_recv(struct thread *t)
 
        zbuf_init(&zb, buf, sizeof(buf), 0);
        while (zbuf_recv(&zb, fd) > 0) {
-               while ((n = znl_nlmsg_pull(&zb, &payload)) != 0) {
+               while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
                        debugf(NHRP_DEBUG_KERNEL,
                               "Netlink-log: Received msg_type %u, msg_flags %u",
                               n->nlmsg_type, n->nlmsg_flags);
index ccca100db57940b038501c5a08b44cccd3958e20..b33eaa047849e38bad0f6c4e36be90aa5cce105e 100644 (file)
@@ -327,9 +327,11 @@ int nhrp_interface_delete(int cmd, struct zclient *client, zebra_size_t length,
                return 0;
 
        debugf(NHRP_DEBUG_IF, "if-delete: %s", ifp->name);
-       if_set_index(ifp, ifp->ifindex);
+
        nhrp_interface_update(ifp);
-       /* if_delete(ifp); */
+
+       if_set_index(ifp, IFINDEX_INTERNAL);
+
        return 0;
 }
 
index fab99588c86cb10a08109f9d20172f46bbd1973c..3de4609a2bc435966bbb18d6881b370db08b14d7 100644 (file)
@@ -550,7 +550,7 @@ int sock_open_unix(const char *path)
 
        memset(&addr, 0, sizeof(struct sockaddr_un));
        addr.sun_family = AF_UNIX;
-       strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
+       strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
 
        ret = connect(fd, (struct sockaddr *)&addr,
                      sizeof(addr.sun_family) + strlen(addr.sun_path));
index 76722aad1028550c37df5510352adfaa11cfb892..484e5adae674a3ab044629e0b346d0dad7640fa5 100644 (file)
@@ -138,11 +138,11 @@ static void ospf6_area_stub_update(struct ospf6_area *area)
 
        if (IS_AREA_STUB(area)) {
                if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
-                       zlog_debug("Stubbing out area for if %s\n", area->name);
+                       zlog_debug("Stubbing out area for if %s", area->name);
                OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
        } else if (IS_AREA_ENABLED(area)) {
                if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
-                       zlog_debug("Normal area for if %s\n", area->name);
+                       zlog_debug("Normal area for if %s", area->name);
                OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
                ospf6_asbr_send_externals_to_area(area);
        }
@@ -450,7 +450,7 @@ DEFUN (area_range,
 
        range->path.u.cost_config = cost;
 
-       zlog_debug("%s: for prefix %s, flag = %x\n", __func__,
+       zlog_debug("%s: for prefix %s, flag = %x", __func__,
                   argv[idx_ipv6_prefixlen]->arg, range->flag);
        if (range->rnode == NULL) {
                ospf6_route_add(range, oa->range_table);
index 3153c29aa18ae66998f3b68435536a78f8b0b68a..2795bb9abdfb46c99ad369bb6d162bd359e8cea9 100644 (file)
@@ -1006,7 +1006,7 @@ void ospf6_asbr_send_externals_to_area(struct ospf6_area *oa)
 
        for (ALL_LSDB(oa->ospf6->lsdb, lsa)) {
                if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
-                       zlog_debug("%s: Flooding AS-External LSA %s\n",
+                       zlog_debug("%s: Flooding AS-External LSA %s",
                                   __func__, lsa->name);
                        ospf6_flood_area(NULL, lsa, oa);
                }
index 83b9001fea9cdf3498337ad405d56e74d1e2fd6f..692c84ad08e7f7f82c144f4a4f3ce631fe222782 100644 (file)
@@ -177,8 +177,7 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
        struct ospf6_interface *oi;
        unsigned int iobuflen;
 
-       oi = (struct ospf6_interface *)XCALLOC(MTYPE_OSPF6_IF,
-                                              sizeof(struct ospf6_interface));
+       oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
 
        oi->area = (struct ospf6_area *)NULL;
        oi->neighbor_list = list_new();
index 40b3522c3d7c94f033cdda8495544912623e79b1..9acbd09b1a958b2b1239f0403e80e857c619c520 100644 (file)
@@ -518,16 +518,14 @@ struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
        lsa_size = ntohs(header->length); /* XXX vulnerable */
 
        /* allocate memory for this LSA */
-       new_header = (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA_HEADER,
-                                                       lsa_size);
+       new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, lsa_size);
 
        /* copy LSA from original header */
        memcpy(new_header, header, lsa_size);
 
        /* LSA information structure */
        /* allocate memory */
-       lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
-                                         sizeof(struct ospf6_lsa));
+       lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
 
        lsa->header = (struct ospf6_lsa_header *)new_header;
 
@@ -546,16 +544,15 @@ struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
        struct ospf6_lsa_header *new_header = NULL;
 
        /* allocate memory for this LSA */
-       new_header = (struct ospf6_lsa_header *)XMALLOC(
-               MTYPE_OSPF6_LSA_HEADER, sizeof(struct ospf6_lsa_header));
+       new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER,
+                            sizeof(struct ospf6_lsa_header));
 
        /* copy LSA from original header */
        memcpy(new_header, header, sizeof(struct ospf6_lsa_header));
 
        /* LSA information structure */
        /* allocate memory */
-       lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
-                                         sizeof(struct ospf6_lsa));
+       lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
 
        lsa->header = (struct ospf6_lsa_header *)new_header;
        SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
index 5e02c0c917b66471931a6626bb32395acea53275..b551dbdfa6e2bededa49e0265567e3b2364d08d3 100644 (file)
@@ -39,10 +39,6 @@ struct ospf6_lsdb *ospf6_lsdb_create(void *data)
        struct ospf6_lsdb *lsdb;
 
        lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb));
-       if (lsdb == NULL) {
-               zlog_warn("Can't malloc lsdb");
-               return NULL;
-       }
        memset(lsdb, 0, sizeof(struct ospf6_lsdb));
 
        lsdb->data = data;
index cd688bbf89b1f87c8c330b0b99c18343c18e6b18..4acb5e3b2e1afcc10852037358dab2546d5c0a74 100644 (file)
@@ -1505,10 +1505,8 @@ int ospf6_iobuf_size(unsigned int size)
        recvnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size);
        sendnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size);
 
-       if (recvbuf)
-               XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
-       if (sendbuf)
-               XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
+       XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
+       XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
        recvbuf = recvnew;
        sendbuf = sendnew;
        iobuflen = size;
index bb451c239e6c3ae584aebd58b126cdf417d423b9..46dc621ae7d169bcd02b3897b1a47fa002c4f8ee 100644 (file)
@@ -86,10 +86,7 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
        struct ospf6_neighbor *on;
        char buf[16];
 
-       on = (struct ospf6_neighbor *)XMALLOC(MTYPE_OSPF6_NEIGHBOR,
-                                             sizeof(struct ospf6_neighbor));
-
-       memset(on, 0, sizeof(struct ospf6_neighbor));
+       on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor));
        inet_ntop(AF_INET, &router_id, buf, sizeof(buf));
        snprintf(on->name, sizeof(on->name), "%s%%%s", buf,
                 oi->interface->name);
index 79e1a44392d9ed5bc44a0cd2b64fe4dff5424f4f..b71b353e1f7feb5029295f9dca82074c0e5ce068 100644 (file)
@@ -174,8 +174,7 @@ struct ospf6_nexthop *ospf6_nexthop_create(void)
 
 void ospf6_nexthop_delete(struct ospf6_nexthop *nh)
 {
-       if (nh)
-               XFREE(MTYPE_OSPF6_NEXTHOP, nh);
+       XFREE(MTYPE_OSPF6_NEXTHOP, nh);
 }
 
 void ospf6_clear_nexthops(struct list *nh_list)
index 376950e84a25f46b8cf8992b56325adbd59a4c43..fc7c6177d7f6cc2e660959390583ced4109a6e4c 100644 (file)
@@ -1358,13 +1358,10 @@ static int ospf6TrapNbrStateChange(struct ospf6_neighbor *on, int next_state,
        index[1] = on->ospf6_if->instance_id;
        index[2] = ntohl(on->router_id);
 
-       smux_trap(ospfv3_variables,
-                 sizeof ospfv3_variables / sizeof(struct variable),
-                 ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof(oid),
-                 ospfv3_oid, sizeof ospfv3_oid / sizeof(oid), index, 3,
-                 ospf6NbrTrapList,
-                 sizeof ospf6NbrTrapList / sizeof(struct trap_object),
-                 NBRSTATECHANGE);
+       smux_trap(ospfv3_variables, array_size(ospfv3_variables),
+                 ospfv3_trap_oid, array_size(ospfv3_trap_oid), ospfv3_oid,
+                 sizeof ospfv3_oid / sizeof(oid), index, 3, ospf6NbrTrapList,
+                 array_size(ospf6NbrTrapList), NBRSTATECHANGE);
        return 0;
 }
 
@@ -1383,13 +1380,10 @@ static int ospf6TrapIfStateChange(struct ospf6_interface *oi, int next_state,
        index[0] = oi->interface->ifindex;
        index[1] = oi->instance_id;
 
-       smux_trap(ospfv3_variables,
-                 sizeof ospfv3_variables / sizeof(struct variable),
-                 ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof(oid),
-                 ospfv3_oid, sizeof ospfv3_oid / sizeof(oid), index, 2,
-                 ospf6IfTrapList,
-                 sizeof ospf6IfTrapList / sizeof(struct trap_object),
-                 IFSTATECHANGE);
+       smux_trap(ospfv3_variables, array_size(ospfv3_variables),
+                 ospfv3_trap_oid, array_size(ospfv3_trap_oid), ospfv3_oid,
+                 sizeof ospfv3_oid / sizeof(oid), index, 2, ospf6IfTrapList,
+                 array_size(ospf6IfTrapList), IFSTATECHANGE);
        return 0;
 }
 
index 2d271c1dabbfac204ccf16b2e1d52ec6a725b424..f08426fb47994173b10b32250230d44c6330ba2e 100644 (file)
@@ -107,8 +107,7 @@ static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
 {
        struct ospf6_vertex *v;
 
-       v = (struct ospf6_vertex *)XMALLOC(MTYPE_OSPF6_VERTEX,
-                                          sizeof(struct ospf6_vertex));
+       v = XMALLOC(MTYPE_OSPF6_VERTEX, sizeof(struct ospf6_vertex));
 
        /* type */
        if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) {
@@ -476,7 +475,7 @@ void ospf6_spf_calculation(uint32_t router_id,
        lsa = ospf6_create_single_router_lsa(oa, oa->lsdb_self, router_id);
        if (lsa == NULL) {
                if (IS_OSPF6_DEBUG_SPF(PROCESS))
-                       zlog_debug("%s: No router LSA for area %s\n", __func__,
+                       zlog_debug("%s: No router LSA for area %s", __func__,
                                   oa->name);
                return;
        }
@@ -1016,8 +1015,7 @@ struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
        new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, total_lsa_length);
 
        /* LSA information structure */
-       lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
-                                         sizeof(struct ospf6_lsa));
+       lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
 
        lsa->header = (struct ospf6_lsa_header *)new_header;
 
index 54f1735e7acc6652ba747695a0e96af0a8b8aab4..abdc82a73841983085325bf3f5456aca87e4c217 100644 (file)
@@ -226,6 +226,9 @@ static int ospf6_zebra_read_route(int command, struct zclient *zclient,
        if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
                return 0;
 
+       if (IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
+               return 0;
+
        ifindex = api.nexthops[0].ifindex;
        nexthop = &api.nexthops[0].gate.ipv6;
 
index a3b337a0c0b782dbd7caabb95af8ada37ee43d1a..f06e45392eb09968afe4692c93f29daf7c1fd23e 100644 (file)
@@ -74,12 +74,12 @@ void api_opaque_lsa_print(struct lsa_header *data)
        olsa = (struct opaque_lsa *)data;
 
        opaquelen = ntohs(data->length) - OSPF_LSA_HEADER_SIZE;
-       zlog_debug("apiserver_lsa_print: opaquelen=%d\n", opaquelen);
+       zlog_debug("apiserver_lsa_print: opaquelen=%d", opaquelen);
 
        for (i = 0; i < opaquelen; i++) {
                zlog_debug("0x%x ", olsa->mydata[i]);
        }
-       zlog_debug("\n");
+       zlog_debug(" ");
 }
 
 /* -----------------------------------------------------------
@@ -242,7 +242,7 @@ const char *ospf_api_errname(int errcode)
 void msg_print(struct msg *msg)
 {
        if (!msg) {
-               zlog_debug("msg_print msg=NULL!\n");
+               zlog_debug("msg_print msg=NULL!");
                return;
        }
 
index d0ee8187229535f9c1f060b6028fdc388da94e33..d6f1fba28b18c9c6505175a7ddf02224ab436ba9 100644 (file)
@@ -2024,7 +2024,7 @@ int ospf_apiserver_del_if(struct interface *ifp)
 
        /* zlog_warn for debugging */
        zlog_warn("ospf_apiserver_del_if");
-       zlog_warn("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status,
+       zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
                  ifp->ifindex);
 
        oi = ospf_apiserver_if_lookup_by_ifp(ifp);
@@ -2110,7 +2110,6 @@ void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa)
                for (i = 0; i < opaquelen; i++) {
                        zlog_debug("0x%x ", olsa->data[i]);
                }
-               zlog_debug("\n");
        }
        return;
 }
index ba2e04bf766b23b4f8daa2ad0e0b520fd6e3f9bd..ea919017d36c91394fee8e9614c12f6c719b9598 100644 (file)
@@ -79,8 +79,7 @@ struct external_info *ospf_external_info_new(uint8_t type,
 {
        struct external_info *new;
 
-       new = (struct external_info *)XCALLOC(MTYPE_OSPF_EXTERNAL_INFO,
-                                             sizeof(struct external_info));
+       new = XCALLOC(MTYPE_OSPF_EXTERNAL_INFO, sizeof(struct external_info));
        new->type = type;
        new->instance = instance;
 
index 9fd9a70c78e9e0300eb0cddcebf50c9dac82883c..419081fe592d410cd2ccab4e071cc5f575d03a2d 100644 (file)
@@ -380,12 +380,10 @@ static int ism_interface_up(struct ospf_interface *oi)
 
 static int ism_loop_ind(struct ospf_interface *oi)
 {
-       int ret = 0;
-
        /* call ism_interface_down. */
        /* ret = ism_interface_down (oi); */
 
-       return ret;
+       return 0;
 }
 
 /* Interface down event handler. */
index b3c91b9006e98c210421329e02341355196cbd36..43c5e338b0893b3b3cb8c0386cdf1ced1b748743 100644 (file)
@@ -3447,7 +3447,14 @@ static int ospf_make_ls_req_func(struct stream *s, uint16_t *length,
 
        oi = nbr->oi;
 
-       /* LS Request packet overflows interface MTU. */
+       /* LS Request packet overflows interface MTU
+        * delta is just number of bytes required for 1 LS Req
+        * ospf_packet_max will return the number of bytes can
+        * be accomodated without ospf header. So length+delta
+        * can be compared to ospf_packet_max
+        * to check if it can fit another lsreq in the same packet.
+        */
+
        if (*length + delta > ospf_packet_max(oi))
                return 0;
 
@@ -3466,7 +3473,7 @@ static int ospf_make_ls_req(struct ospf_neighbor *nbr, struct stream *s)
 {
        struct ospf_lsa *lsa;
        uint16_t length = OSPF_LS_REQ_MIN_SIZE;
-       unsigned long delta = stream_get_endp(s) + 12;
+       unsigned long delta = 12;
        struct route_table *table;
        struct route_node *rn;
        int i;
@@ -3530,8 +3537,9 @@ static int ospf_make_ls_upd(struct ospf_interface *oi, struct list *update,
 
                assert(lsa->data);
 
-               /* Will it fit? */
-               if (length + delta + ntohs(lsa->data->length) > size_noauth)
+               /* Will it fit? Minimum it has to fit atleast one */
+               if ((length + delta + ntohs(lsa->data->length) > size_noauth) &&
+                               (count > 0))
                        break;
 
                /* Keep pointer to LS age. */
@@ -3568,13 +3576,21 @@ static int ospf_make_ls_ack(struct ospf_interface *oi, struct list *ack,
 {
        struct listnode *node, *nnode;
        uint16_t length = OSPF_LS_ACK_MIN_SIZE;
-       unsigned long delta = stream_get_endp(s) + 24;
+       unsigned long delta = OSPF_LSA_HEADER_SIZE;
        struct ospf_lsa *lsa;
 
        for (ALL_LIST_ELEMENTS(ack, node, nnode, lsa)) {
                assert(lsa);
 
-               if (length + delta > ospf_packet_max(oi))
+               /* LS Ack packet overflows interface MTU
+                * delta is just number of bytes required for
+                * 1 LS Ack(1 LS Hdr) ospf_packet_max will return
+                * the number of bytes can be accomodated without
+                * ospf header. So length+delta can be compared
+                * against ospf_packet_max to check if it can fit
+                * another ls header in the same packet.
+                */
+               if ((length + delta) > ospf_packet_max(oi))
                        break;
 
                stream_put(s, lsa->data, OSPF_LSA_HEADER_SIZE);
index 4a0d4add150859818160fb5b4677d9c3fcae09e7..5f01edfbdfa75889d454c91d767b62e7a812133a 100644 (file)
@@ -1372,14 +1372,14 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
        }
 
        else {
-               zlog_debug("  Segment Routing Algorithm TLV:\n");
+               zlog_debug("  Segment Routing Algorithm TLV:");
                for (i = 0; i < ntohs(algo->header.length); i++)
                        switch (algo->value[i]) {
                        case 0:
-                               zlog_debug("    Algorithm %d: SPF\n", i);
+                               zlog_debug("    Algorithm %d: SPF", i);
                                break;
                        case 1:
-                               zlog_debug("    Algorithm %d: Strict SPF\n", i);
+                               zlog_debug("    Algorithm %d: Strict SPF", i);
                                break;
                        default:
                                zlog_debug(
index 755634a2f166c5d2d9935351a016a71a7b1b3cc1..c26545344a9f5818213fb16d2eab3f90e0eb52f7 100644 (file)
@@ -901,7 +901,7 @@ static struct ospf_lsa *lsdb_lookup_next(struct ospf_area *area, uint8_t *type,
        /* Sanity check, if LSA type unknwon
           merley skip any LSA */
        if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA)) {
-               zlog_debug("Strange request with LSA type %d\n", i);
+               zlog_debug("Strange request with LSA type %d", i);
                return NULL;
        }
 
@@ -2590,13 +2590,10 @@ static void ospfTrapNbrStateChange(struct ospf_neighbor *on)
        oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
        index[IN_ADDR_SIZE] = 0;
 
-       smux_trap(ospf_variables,
-                 sizeof ospf_variables / sizeof(struct variable),
-                 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+       smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+                 array_size(ospf_trap_oid), ospf_oid,
                  sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
-                 ospfNbrTrapList,
-                 sizeof ospfNbrTrapList / sizeof(struct trap_object),
-                 NBRSTATECHANGE);
+                 ospfNbrTrapList, array_size(ospfNbrTrapList), NBRSTATECHANGE);
 }
 
 static void ospfTrapVirtNbrStateChange(struct ospf_neighbor *on)
@@ -2608,12 +2605,10 @@ static void ospfTrapVirtNbrStateChange(struct ospf_neighbor *on)
        oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
        index[IN_ADDR_SIZE] = 0;
 
-       smux_trap(ospf_variables,
-                 sizeof ospf_variables / sizeof(struct variable),
-                 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+       smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+                 array_size(ospf_trap_oid), ospf_oid,
                  sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
-                 ospfVirtNbrTrapList,
-                 sizeof ospfVirtNbrTrapList / sizeof(struct trap_object),
+                 ospfVirtNbrTrapList, array_size(ospfVirtNbrTrapList),
                  VIRTNBRSTATECHANGE);
 }
 
@@ -2649,13 +2644,10 @@ static void ospfTrapIfStateChange(struct ospf_interface *oi)
        oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
        index[IN_ADDR_SIZE] = 0;
 
-       smux_trap(ospf_variables,
-                 sizeof ospf_variables / sizeof(struct variable),
-                 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+       smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+                 array_size(ospf_trap_oid), ospf_oid,
                  sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
-                 ospfIfTrapList,
-                 sizeof ospfIfTrapList / sizeof(struct trap_object),
-                 IFSTATECHANGE);
+                 ospfIfTrapList, array_size(ospfIfTrapList), IFSTATECHANGE);
 }
 
 static void ospfTrapVirtIfStateChange(struct ospf_interface *oi)
@@ -2667,12 +2659,10 @@ static void ospfTrapVirtIfStateChange(struct ospf_interface *oi)
        oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
        index[IN_ADDR_SIZE] = 0;
 
-       smux_trap(ospf_variables,
-                 sizeof ospf_variables / sizeof(struct variable),
-                 ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+       smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+                 array_size(ospf_trap_oid), ospf_oid,
                  sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
-                 ospfVirtIfTrapList,
-                 sizeof ospfVirtIfTrapList / sizeof(struct trap_object),
+                 ospfVirtIfTrapList, array_size(ospfVirtIfTrapList),
                  VIRTIFSTATECHANGE);
 }
 
index 9c223facd354b4326175c11d5ece75814c4eab7e..74dba273e619815fb89c9931ec250f0639ff6f74 100644 (file)
@@ -1140,13 +1140,13 @@ ospf_rtrs_print (struct route_table *rtrs)
               if (path->nexthop.s_addr == 0)
                 {
                   if (IS_DEBUG_OSPF_EVENT)
-                    zlog_debug ("   directly attached to %s\r\n",
+                    zlog_debug ("   directly attached to %s\r",
                                ifindex2ifname (path->ifindex), VRF_DEFAULT);
                 }
               else
                 {
                   if (IS_DEBUG_OSPF_EVENT)
-                    zlog_debug ("   via %s, %s\r\n",
+                    zlog_debug ("   via %s, %s\r",
                                inet_ntoa (path->nexthop),
                                ifindex2ifname (path->ifindex), VRF_DEFAULT);
                 }
index f0ddf7cc0a3e57ae47fc8e66cb0f3c62b82f1b43..a49352086828ef72692f70d72de54638459c265d 100644 (file)
@@ -1600,7 +1600,7 @@ static int ospf_sr_update_schedule(struct thread *t)
        monotime(&stop_time);
 
        if (IS_DEBUG_OSPF_SR)
-               zlog_debug("SR (%s): SPF Processing Time(usecs): %lld\n",
+               zlog_debug("SR (%s): SPF Processing Time(usecs): %lld",
                           __func__,
                           (stop_time.tv_sec - start_time.tv_sec) * 1000000LL
                                   + (stop_time.tv_usec - start_time.tv_usec));
index bb22f211a7c07ca55567b2636b07d2976e803de9..b5d8739fcb1ecc7d5e2fb6ef48a336baf8900939 100644 (file)
@@ -3029,13 +3029,13 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
                        if (ospf->stub_router_startup_time
                            != OSPF_STUB_ROUTER_UNCONFIGURED)
                                json_object_int_add(
-                                       json_vrf, "postStartEnabledMsecs",
-                                       ospf->stub_router_startup_time / 1000);
+                                       json_vrf, "postStartEnabledSecs",
+                                       ospf->stub_router_startup_time);
                        if (ospf->stub_router_shutdown_time
                            != OSPF_STUB_ROUTER_UNCONFIGURED)
                                json_object_int_add(
-                                       json_vrf, "preShutdownEnabledMsecs",
-                                       ospf->stub_router_shutdown_time / 1000);
+                                       json_vrf, "preShutdownEnabledSecs",
+                                       ospf->stub_router_shutdown_time);
                } else {
                        vty_out(vty,
                                " Stub router advertisement is configured\n");
@@ -3511,8 +3511,8 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
                        json_object_int_add(json_interface_sub, "cost",
                                            oi->output_cost);
                        json_object_int_add(
-                               json_interface_sub, "transmitDelayMsecs",
-                               1000 / OSPF_IF_PARAM(oi, transmit_delay));
+                               json_interface_sub, "transmitDelaySecs",
+                               OSPF_IF_PARAM(oi, transmit_delay));
                        json_object_string_add(json_interface_sub, "state",
                                               lookup_msg(ospf_ism_state_msg,
                                                          oi->state, NULL));
@@ -3616,20 +3616,20 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
                        if (OSPF_IF_PARAM(oi, fast_hello) == 0)
                                json_object_int_add(
                                        json_interface_sub, "timerMsecs",
-                                       1000 / OSPF_IF_PARAM(oi, v_hello));
+                                       OSPF_IF_PARAM(oi, v_hello) * 1000);
                        else
                                json_object_int_add(
                                        json_interface_sub, "timerMsecs",
                                        1000 / OSPF_IF_PARAM(oi, fast_hello));
                        json_object_int_add(json_interface_sub,
-                                           "timerDeadMsecs",
-                                           1000 / OSPF_IF_PARAM(oi, v_wait));
+                                           "timerDeadSecs",
+                                           OSPF_IF_PARAM(oi, v_wait));
                        json_object_int_add(json_interface_sub,
-                                           "timerWaitMsecs",
-                                           1000 / OSPF_IF_PARAM(oi, v_wait));
+                                           "timerWaitSecs",
+                                           OSPF_IF_PARAM(oi, v_wait));
                        json_object_int_add(
-                               json_interface_sub, "timerRetransmit",
-                               1000 / OSPF_IF_PARAM(oi, retransmit_interval));
+                               json_interface_sub, "timerRetransmitSecs",
+                               OSPF_IF_PARAM(oi, retransmit_interval));
                } else {
                        vty_out(vty, "  Timer intervals configured,");
                        vty_out(vty, " Hello ");
index ea2c492e183e6c64ab90db27fa2d778052388c4d..4cbd817ad871b08e8164c738394ca425ba8fcb9e 100644 (file)
@@ -560,8 +560,7 @@ struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type,
                ospf->external[type] = list_new();
 
        ext_list = ospf->external[type];
-       ext = (struct ospf_external *)XCALLOC(MTYPE_OSPF_EXTERNAL,
-                                             sizeof(struct ospf_external));
+       ext = XCALLOC(MTYPE_OSPF_EXTERNAL, sizeof(struct ospf_external));
        ext->instance = instance;
        EXTERNAL_INFO(ext) = route_table_init();
 
@@ -621,8 +620,7 @@ struct ospf_redist *ospf_redist_add(struct ospf *ospf, uint8_t type,
                ospf->redist[type] = list_new();
 
        red_list = ospf->redist[type];
-       red = (struct ospf_redist *)XCALLOC(MTYPE_OSPF_REDISTRIBUTE,
-                                           sizeof(struct ospf_redist));
+       red = XCALLOC(MTYPE_OSPF_REDISTRIBUTE, sizeof(struct ospf_redist));
        red->instance = instance;
        red->dmetric.type = -1;
        red->dmetric.value = -1;
index 8f8b6aeed17501f8754f95cd047529596b9fb65f..5e67990d5ef72bd0345ce497867f5c6ea54128f1 100644 (file)
@@ -71,8 +71,7 @@ static int pbr_map_sequence_compare(const struct pbr_map_sequence *pbrms1,
 
 static void pbr_map_sequence_delete(struct pbr_map_sequence *pbrms)
 {
-       if (pbrms->internal_nhg_name)
-               XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
+       XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
 
        XFREE(MTYPE_PBR_MAP_SEQNO, pbrms);
 }
index 2cba657f65e1b7a8e6a92c4a42a4177b0f5b40d6..7504752725df4d601454ab2b617dc80d296d6819 100644 (file)
@@ -50,7 +50,7 @@ static void pbr_nht_install_nexthop_group(struct pbr_nexthop_group_cache *pnhgc,
 static void
 pbr_nht_uninstall_nexthop_group(struct pbr_nexthop_group_cache *pnhgc,
                                struct nexthop_group nhg,
-                               enum nexthop_types_t nh_afi);
+                               enum nexthop_types_t nh_type);
 
 /*
  * Nexthop refcount.
@@ -157,7 +157,7 @@ static bool pbr_nh_hash_equal(const void *arg1, const void *arg2)
 
        switch (pbrnc1->nexthop->type) {
        case NEXTHOP_TYPE_IFINDEX:
-               return true;
+               return pbrnc1->nexthop->ifindex == pbrnc2->nexthop->ifindex;
        case NEXTHOP_TYPE_IPV4_IFINDEX:
        case NEXTHOP_TYPE_IPV4:
                return pbrnc1->nexthop->gate.ipv4.s_addr
@@ -264,6 +264,14 @@ void pbr_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
 
        pbr_nht_install_nexthop_group(pnhgc, nhgc->nhg);
        pbr_map_check_nh_group_change(nhgc->name);
+
+       if (nhop->type == NEXTHOP_TYPE_IFINDEX) {
+               struct interface *ifp;
+
+               ifp = if_lookup_by_index(nhop->ifindex, nhop->vrf_id);
+               if (ifp)
+                       pbr_nht_nexthop_interface_update(ifp);
+       }
 }
 
 void pbr_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
@@ -274,7 +282,7 @@ void pbr_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
        struct pbr_nexthop_group_cache *pnhgc;
        struct pbr_nexthop_cache pnhc_find = {};
        struct pbr_nexthop_cache *pnhc;
-       enum nexthop_types_t nh_afi = nhop->type;
+       enum nexthop_types_t nh_type = nhop->type;
 
        /* find pnhgc by name */
        strlcpy(pnhgc_find.name, nhgc->name, sizeof(pnhgc_find.name));
@@ -296,7 +304,7 @@ void pbr_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
        if (pnhgc->nhh->count)
                pbr_nht_install_nexthop_group(pnhgc, nhgc->nhg);
        else
-               pbr_nht_uninstall_nexthop_group(pnhgc, nhgc->nhg, nh_afi);
+               pbr_nht_uninstall_nexthop_group(pnhgc, nhgc->nhg, nh_type);
 
        pbr_map_check_nh_group_change(nhgc->name);
 }
@@ -372,39 +380,53 @@ void pbr_nht_route_removed_for_table(uint32_t table_id)
  *    - AFI_MAX on error
  */
 static afi_t pbr_nht_which_afi(struct nexthop_group nhg,
-                              enum nexthop_types_t nh_afi)
+                              enum nexthop_types_t nh_type)
 {
        struct nexthop *nexthop;
        afi_t install_afi = AFI_MAX;
        bool v6, v4, bh;
 
+       if (nh_type) {
+               switch (nh_type) {
+               case NEXTHOP_TYPE_IPV4:
+               case NEXTHOP_TYPE_IPV4_IFINDEX:
+                       return AFI_IP;
+               case NEXTHOP_TYPE_IPV6:
+               case NEXTHOP_TYPE_IPV6_IFINDEX:
+                       return AFI_IP6;
+               case NEXTHOP_TYPE_IFINDEX:
+               case NEXTHOP_TYPE_BLACKHOLE:
+                       return AFI_MAX;
+               }
+       }
+
        v6 = v4 = bh = false;
 
-       if (!nh_afi) {
-               for (ALL_NEXTHOPS(nhg, nexthop)) {
-                       nh_afi = nexthop->type;
+       for (ALL_NEXTHOPS(nhg, nexthop)) {
+               nh_type = nexthop->type;
+
+               switch (nh_type) {
+               case NEXTHOP_TYPE_IFINDEX:
+                       break;
+               case NEXTHOP_TYPE_IPV4:
+               case NEXTHOP_TYPE_IPV4_IFINDEX:
+                       v6 = true;
+                       install_afi = AFI_IP;
+                       break;
+               case NEXTHOP_TYPE_IPV6:
+               case NEXTHOP_TYPE_IPV6_IFINDEX:
+                       v4 = true;
+                       install_afi = AFI_IP6;
+                       break;
+               case NEXTHOP_TYPE_BLACKHOLE:
+                       bh = true;
                        break;
                }
        }
 
-       switch (nh_afi) {
-       case NEXTHOP_TYPE_IFINDEX:
-               break;
-       case NEXTHOP_TYPE_IPV4:
-       case NEXTHOP_TYPE_IPV4_IFINDEX:
-               v6 = true;
-               install_afi = AFI_IP;
-               break;
-       case NEXTHOP_TYPE_IPV6:
-       case NEXTHOP_TYPE_IPV6_IFINDEX:
-               v4 = true;
-               install_afi = AFI_IP6;
-               break;
-       case NEXTHOP_TYPE_BLACKHOLE:
-               bh = true;
+       /* Interface and/or blackhole nexthops only. */
+       if (!v4 && !v6)
                install_afi = AFI_MAX;
-               break;
-       }
 
        if (!bh && v6 && v4)
                DEBUGD(&pbr_dbg_nht,
@@ -423,9 +445,9 @@ static void pbr_nht_install_nexthop_group(struct pbr_nexthop_group_cache *pnhgc,
                                          struct nexthop_group nhg)
 {
        afi_t install_afi;
-       enum nexthop_types_t nh_afi = 0;
+       enum nexthop_types_t nh_type = 0;
 
-       install_afi = pbr_nht_which_afi(nhg, nh_afi);
+       install_afi = pbr_nht_which_afi(nhg, nh_type);
 
        route_add(pnhgc, nhg, install_afi);
 }
@@ -433,11 +455,11 @@ static void pbr_nht_install_nexthop_group(struct pbr_nexthop_group_cache *pnhgc,
 static void
 pbr_nht_uninstall_nexthop_group(struct pbr_nexthop_group_cache *pnhgc,
                                struct nexthop_group nhg,
-                               enum nexthop_types_t nh_afi)
+                               enum nexthop_types_t nh_type)
 {
        afi_t install_afi;
 
-       install_afi = pbr_nht_which_afi(nhg, nh_afi);
+       install_afi = pbr_nht_which_afi(nhg, nh_type);
 
        pnhgc->installed = false;
        pnhgc->valid = false;
@@ -526,7 +548,7 @@ void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms)
        struct listnode *node;
        struct pbr_map_interface *pmi;
        struct nexthop *nh;
-       enum nexthop_types_t nh_afi = 0;
+       enum nexthop_types_t nh_type = 0;
 
        if (pbrm->valid && pbrms->nhs_installed && pbrm->incoming->count) {
                for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi))
@@ -542,13 +564,13 @@ void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence *pbrms)
        pnhgc = hash_lookup(pbr_nhg_hash, &find);
 
        nh = pbrms->nhg->nexthop;
-       nh_afi = nh->type;
+       nh_type = nh->type;
        lup.nexthop = nh;
        pnhc = hash_lookup(pnhgc->nhh, &lup);
        pnhc->parent = NULL;
        hash_release(pnhgc->nhh, pnhc);
        pbr_nh_delete(&pnhc);
-       pbr_nht_uninstall_nexthop_group(pnhgc, *pbrms->nhg, nh_afi);
+       pbr_nht_uninstall_nexthop_group(pnhgc, *pbrms->nhg, nh_type);
 
        hash_release(pbr_nhg_hash, pnhgc);
 
@@ -653,6 +675,7 @@ bool pbr_nht_nexthop_group_valid(const char *name)
 
 struct pbr_nht_individual {
        struct zapi_route *nhr;
+       struct interface *ifp;
 
        uint32_t valid;
 };
@@ -716,6 +739,56 @@ void pbr_nht_nexthop_update(struct zapi_route *nhr)
        hash_iterate(pbr_nhg_hash, pbr_nht_nexthop_update_lookup, nhr);
 }
 
+static void
+pbr_nht_individual_nexthop_interface_update_lookup(struct hash_backet *b,
+                                                  void *data)
+{
+       struct pbr_nexthop_cache *pnhc = b->data;
+       struct pbr_nht_individual *pnhi = data;
+       bool old_valid;
+
+       old_valid = pnhc->valid;
+
+       if (pnhc->nexthop->type == NEXTHOP_TYPE_IFINDEX
+           && pnhc->nexthop->ifindex == pnhi->ifp->ifindex)
+               pnhc->valid = !!if_is_up(pnhi->ifp);
+
+       DEBUGD(&pbr_dbg_nht, "\tFound %s: old: %d new: %d", pnhi->ifp->name,
+              old_valid, pnhc->valid);
+
+       if (pnhc->valid)
+               pnhi->valid += 1;
+}
+
+static void pbr_nht_nexthop_interface_update_lookup(struct hash_backet *b,
+                                                   void *data)
+{
+       struct pbr_nexthop_group_cache *pnhgc = b->data;
+       struct pbr_nht_individual pnhi;
+       bool old_valid;
+
+       old_valid = pnhgc->valid;
+
+       pnhi.ifp = data;
+       pnhi.valid = 0;
+       hash_iterate(pnhgc->nhh,
+                    pbr_nht_individual_nexthop_interface_update_lookup, &pnhi);
+
+       /*
+        * If any of the specified nexthops are valid we are valid
+        */
+       pnhgc->valid = !!pnhi.valid;
+
+       if (old_valid != pnhgc->valid)
+               pbr_map_check_nh_group_change(pnhgc->name);
+}
+
+void pbr_nht_nexthop_interface_update(struct interface *ifp)
+{
+       hash_iterate(pbr_nhg_hash, pbr_nht_nexthop_interface_update_lookup,
+                    ifp);
+}
+
 static uint32_t pbr_nhg_hash_key(void *arg)
 {
        struct pbr_nexthop_group_cache *nhgc =
@@ -740,7 +813,7 @@ uint32_t pbr_nht_get_next_tableid(bool peek)
        bool found = false;
 
        for (i = pbr_nhg_low_table; i <= pbr_nhg_high_table; i++) {
-               if (nhg_tableid[i] == false) {
+               if (!nhg_tableid[i]) {
                        found = true;
                        break;
                }
index d37803fbe32e52fffeb5c0b605715064413254b4..4ef41cede7dd76a2fca02758e336787271cae2ce 100644 (file)
@@ -117,5 +117,10 @@ extern void pbr_nht_show_nexthop_group(struct vty *vty, const char *name);
  */
 extern void pbr_nht_nexthop_update(struct zapi_route *nhr);
 
+/*
+ * When we get a callback from zebra about an interface status update.
+ */
+extern void pbr_nht_nexthop_interface_update(struct interface *ifp);
+
 extern void pbr_nht_init(void);
 #endif
index f8232c9581fdfbce715364f92a7c9638a7390004..067d5c01fdfac621cebd1a0bf8fdc70dc88d8888 100644 (file)
@@ -221,13 +221,19 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
 }
 
 DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
-      "[no] set nexthop <A.B.C.D|X:X::X:X>$addr [INTERFACE]$intf [nexthop-vrf NAME$name]",
+      "[no] set nexthop\
+        <\
+         <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
+         |INTERFACE$intf\
+       >\
+        [nexthop-vrf NAME$name]",
       NO_STR
       "Set for the PBR-MAP\n"
       "Specify one of the nexthops in this map\n"
       "v4 Address\n"
       "v6 Address\n"
       "Interface to use\n"
+      "Interface to use\n"
       "If the nexthop is in a different vrf tell us\n"
       "The nexthop-vrf Name\n")
 {
@@ -255,44 +261,38 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
        memset(&nhop, 0, sizeof(nhop));
        nhop.vrf_id = vrf->vrf_id;
 
-       /*
-        * Make SA happy.  CLIPPY is not going to give us a NULL
-        * addr.
-        */
-       assert(addr);
-       if (addr->sa.sa_family == AF_INET) {
-               nhop.gate.ipv4.s_addr = addr->sin.sin_addr.s_addr;
-               if (intf) {
-                       nhop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
-                       nhop.ifindex = ifname2ifindex(intf, vrf->vrf_id);
-                       if (nhop.ifindex == IFINDEX_INTERNAL) {
-                               vty_out(vty,
-                                       "Specified Intf %s does not exist in vrf: %s\n",
-                                       intf, vrf->name);
-                               return CMD_WARNING_CONFIG_FAILED;
-                       }
-               } else
-                       nhop.type = NEXTHOP_TYPE_IPV4;
-       } else {
-               memcpy(&nhop.gate.ipv6, &addr->sin6.sin6_addr, 16);
-               if (intf) {
-                       nhop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
-                       nhop.ifindex = ifname2ifindex(intf, vrf->vrf_id);
-                       if (nhop.ifindex == IFINDEX_INTERNAL) {
-                               vty_out(vty,
-                                       "Specified Intf %s does not exist in vrf: %s\n",
-                                       intf, vrf->name);
-                               return CMD_WARNING_CONFIG_FAILED;
-                       }
+       if (intf) {
+               nhop.ifindex = ifname2ifindex(intf, vrf->vrf_id);
+               if (nhop.ifindex == IFINDEX_INTERNAL) {
+                       vty_out(vty,
+                               "Specified Intf %s does not exist in vrf: %s\n",
+                               intf, vrf->name);
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+       }
+
+       if (addr) {
+               if (addr->sa.sa_family == AF_INET) {
+                       nhop.gate.ipv4.s_addr = addr->sin.sin_addr.s_addr;
+                       if (intf)
+                               nhop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
+                       else
+                               nhop.type = NEXTHOP_TYPE_IPV4;
                } else {
-                       if (IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
-                               vty_out(vty,
-                                       "Specified a v6 LL with no interface, rejecting\n");
-                               return CMD_WARNING_CONFIG_FAILED;
+                       nhop.gate.ipv6 = addr->sin6.sin6_addr;
+                       if (intf)
+                               nhop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
+                       else {
+                               if (IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
+                                       vty_out(vty,
+                                               "Specified a v6 LL with no interface, rejecting\n");
+                                       return CMD_WARNING_CONFIG_FAILED;
+                               }
+                               nhop.type = NEXTHOP_TYPE_IPV6;
                        }
-                       nhop.type = NEXTHOP_TYPE_IPV6;
                }
-       }
+       } else
+               nhop.type = NEXTHOP_TYPE_IFINDEX;
 
        if (pbrms->nhg)
                nh = nexthop_exists(pbrms->nhg, &nhop);
@@ -335,6 +335,14 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
                pbr_map_check(pbrms);
        }
 
+       if (nhop.type == NEXTHOP_TYPE_IFINDEX) {
+               struct interface *ifp;
+
+               ifp = if_lookup_by_index(nhop.ifindex, nhop.vrf_id);
+               if (ifp)
+                       pbr_nht_nexthop_interface_update(ifp);
+       }
+
        return CMD_SUCCESS;
 }
 
@@ -616,18 +624,18 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty,
        vty_out(vty, "pbr-map %s seq %u\n", pbrm->name, pbrms->seqno);
 
        if (pbrms->src)
-               vty_out(vty, "  match src-ip %s\n",
+               vty_out(vty, " match src-ip %s\n",
                        prefix2str(pbrms->src, buff, sizeof(buff)));
 
        if (pbrms->dst)
-               vty_out(vty, "  match dst-ip %s\n",
+               vty_out(vty, " match dst-ip %s\n",
                        prefix2str(pbrms->dst, buff, sizeof(buff)));
 
        if (pbrms->nhgrp_name)
-               vty_out(vty, "  set nexthop-group %s\n", pbrms->nhgrp_name);
+               vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
 
        if (pbrms->nhg) {
-               vty_out(vty, "  set ");
+               vty_out(vty, " set ");
                nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
        }
 
index 558e635748067a4450f8410b8b512f5908f72c69..4f8f50556bb5d616a422a5d0bbe4d934e72797bb 100644 (file)
@@ -75,6 +75,8 @@ static int interface_add(int command, struct zclient *zclient,
        if (!ifp->info)
                pbr_if_new(ifp);
 
+       pbr_nht_nexthop_interface_update(ifp);
+
        return 0;
 }
 
@@ -144,6 +146,8 @@ static int interface_state_up(int command, struct zclient *zclient,
        DEBUGD(&pbr_dbg_zebra,
               "%s: %s is up", __PRETTY_FUNCTION__, ifp->name);
 
+       pbr_nht_nexthop_interface_update(ifp);
+
        return 0;
 }
 
@@ -157,6 +161,8 @@ static int interface_state_down(int command, struct zclient *zclient,
        DEBUGD(&pbr_dbg_zebra,
               "%s: %s is down", __PRETTY_FUNCTION__, ifp->name);
 
+       pbr_nht_nexthop_interface_update(ifp);
+
        return 0;
 }
 
@@ -234,18 +240,19 @@ static int rule_notify_owner(int command, struct zclient *zclient,
        switch (note) {
        case ZAPI_RULE_FAIL_INSTALL:
                pbrms->installed &= ~installed;
-               DEBUGD(&pbr_dbg_zebra, "%s: Received RULE_FAIL_INSTALL: %lu",
+               DEBUGD(&pbr_dbg_zebra,
+                      "%s: Received RULE_FAIL_INSTALL: %" PRIu64,
                       __PRETTY_FUNCTION__, pbrms->installed);
                break;
        case ZAPI_RULE_INSTALLED:
                pbrms->installed |= installed;
-               DEBUGD(&pbr_dbg_zebra, "%s: Received RULE_INSTALLED: %lu",
+               DEBUGD(&pbr_dbg_zebra, "%s: Received RULE_INSTALLED: %" PRIu64,
                       __PRETTY_FUNCTION__, pbrms->installed);
                break;
        case ZAPI_RULE_FAIL_REMOVE:
        case ZAPI_RULE_REMOVED:
                pbrms->installed &= ~installed;
-               DEBUGD(&pbr_dbg_zebra, "%s: Received RULE REMOVED: %lu",
+               DEBUGD(&pbr_dbg_zebra, "%s: Received RULE REMOVED: %" PRIu64,
                       __PRETTY_FUNCTION__, pbrms->installed);
                break;
        }
index eaec002a73bf2caf104db5be24dc90e576c5c29b..1a30904e21c82ff094e97e4cf29856638c0625d1 100644 (file)
@@ -198,7 +198,7 @@ static void pim_show_assert_helper(struct vty *vty,
        pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
        pim_time_timer_to_mmss(timer, sizeof(timer), ch->t_ifassert_timer);
 
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                pim_ifchannel_ifassert_name(ch->ifassert_state), winner_str,
                uptime, timer);
@@ -214,7 +214,7 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
        now = pim_time_monotonic_sec();
 
        vty_out(vty,
-               "Interface Address         Source          Group           State  Winner          Uptime   Timer\n");
+               "Interface        Address         Source          Group           State  Winner          Uptime   Timer\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -239,7 +239,7 @@ static void pim_show_assert_internal_helper(struct vty *vty,
 
        pim_inet4_dump("<ch_src?>", ch->sg.src, ch_src_str, sizeof(ch_src_str));
        pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
                pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
@@ -261,7 +261,7 @@ static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
                "eATD: Evaluate AssertTrackingDesired\n\n");
 
        vty_out(vty,
-               "Interface Address         Source          Group           CA  eCA ATD eATD\n");
+               "Interface        Address         Source          Group           CA  eCA ATD eATD\n");
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
                if (!pim_ifp)
@@ -292,7 +292,7 @@ static void pim_show_assert_metric_helper(struct vty *vty,
        pim_inet4_dump("<ch_grp?>", ch->sg.grp, ch_grp_str, sizeof(ch_grp_str));
        pim_inet4_dump("<addr?>", am.ip_address, addr_str, sizeof(addr_str));
 
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %4u %6u %-15s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                am.rpt_bit_flag ? "yes" : "no", am.metric_preference,
                am.route_metric, addr_str);
@@ -305,7 +305,7 @@ static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Source          Group           RPT Pref Metric Address        \n");
+               "Interface        Address         Source          Group           RPT Pref Metric Address        \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -349,7 +349,7 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
        else
                snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
 
-       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
+       vty_out(vty, "%-16s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n",
                ch->interface->name, inet_ntoa(ifaddr), ch_src_str, ch_grp_str,
                am->rpt_bit_flag ? "yes" : "no", pref_str, metr_str, addr_str);
 }
@@ -362,7 +362,7 @@ static void pim_show_assert_winner_metric(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Source          Group           RPT Pref Metric Address        \n");
+               "Interface        Address         Source          Group           RPT Pref Metric Address        \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -462,7 +462,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
                                             json, JSON_C_TO_STRING_PRETTY));
        } else {
                vty_out(vty,
-                       "Interface  Address          Source           Group            Membership\n");
+                       "Interface         Address          Source           Group            Membership\n");
 
                /*
                 * Example of the json data we are traversing
@@ -499,7 +499,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
                                type = json_object_get_type(if_field_val);
 
                                if (type == json_type_object) {
-                                       vty_out(vty, "%-9s  ", key);
+                                       vty_out(vty, "%-16s  ", key);
 
                                        json_object_object_get_ex(
                                                val, "address", &json_tmp);
@@ -566,7 +566,7 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface  State          Address  V  Querier  Query Timer    Uptime\n");
+                       "Interface         State          Address  V  Querier  Query Timer    Uptime\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -614,7 +614,7 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
                                }
                        } else {
                                vty_out(vty,
-                                       "%-9s  %5s  %15s  %d  %7s  %11s  %8s\n",
+                                       "%-16s  %5s  %15s  %d  %7s  %11s  %8s\n",
                                        ifp->name,
                                        if_is_up(ifp)
                                                ? (igmp->mtrace_only ? "mtrc"
@@ -854,7 +854,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
        now = pim_time_monotonic_sec();
 
        vty_out(vty,
-               "Interface Address         Source          Group           Socket Uptime  \n");
+               "Interface        Address         Source          Group           Socket Uptime  \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -888,7 +888,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
                        pim_inet4_dump("<src?>", ij->source_addr, source_str,
                                       sizeof(source_str));
 
-                       vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s\n",
+                       vty_out(vty, "%-16s %-15s %-15s %-15s %6d %8s\n",
                                ifp->name, pri_addr_str, source_str, group_str,
                                ij->sock_fd, uptime);
                } /* for (pim_ifp->igmp_join_list) */
@@ -1191,7 +1191,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
                        vty_out(vty, "Designated Router\n");
                        vty_out(vty, "-----------------\n");
                        vty_out(vty, "Address   : %s\n", dr_str);
-                       vty_out(vty, "Priority  : %d(%d)\n",
+                       vty_out(vty, "Priority  : %u(%d)\n",
                                pim_ifp->pim_dr_priority,
                                pim_ifp->pim_dr_num_nondrpri_neighbors);
                        vty_out(vty, "Uptime    : %s\n", dr_uptime);
@@ -1421,11 +1421,11 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
                                             json, JSON_C_TO_STRING_PRETTY));
        } else {
                vty_out(vty,
-                       "Interface  State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n");
+                       "Interface         State          Address  PIM Nbrs           PIM DR  FHR IfChannels\n");
 
                json_object_object_foreach(json, key, val)
                {
-                       vty_out(vty, "%-9s  ", key);
+                       vty_out(vty, "%-16s  ", key);
 
                        json_object_object_get_ex(val, "state", &json_tmp);
                        vty_out(vty, "%5s  ", json_object_get_string(json_tmp));
@@ -1474,12 +1474,13 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
                json = json_object_new_object();
        else {
                vty_out(vty, "\n");
-               vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
-                       "Interface", "    HELLO", "    JOIN", "   PRUNE",
-                       "   REGISTER", "  REGISTER-STOP", "  ASSERT");
-               vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
-                       "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
-                       "     Rx/Tx", "    Rx/Tx");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+                       "Interface", "       HELLO", "       JOIN",
+                       "      PRUNE", "   REGISTER", "REGISTER-STOP",
+                       "  ASSERT");
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
+                       "       Rx/Tx", "       Rx/Tx", "      Rx/Tx",
+                       "     Rx/Tx", "    Rx/Tx", "   Rx/Tx");
                vty_out(vty,
                        "---------------------------------------------------------------------------------------------------------------\n");
        }
@@ -1519,7 +1520,7 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
                        json_object_object_add(json, ifp->name, json_row);
                } else {
                        vty_out(vty,
-                               "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
+                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
                                ifp->name, pim_ifp->pim_ifstat_hello_recv,
                                pim_ifp->pim_ifstat_hello_sent,
                                pim_ifp->pim_ifstat_join_recv,
@@ -1555,14 +1556,14 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
                json = json_object_new_object();
        else {
                vty_out(vty, "\n");
-               vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+               vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s\n",
                        "Interface", "    HELLO", "    JOIN", "   PRUNE",
                        "   REGISTER", "  REGISTER-STOP", "  ASSERT");
-               vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
+               vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s\n", "",
                        "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
                        "     Rx/Tx", "    Rx/Tx");
                vty_out(vty,
-                       "---------------------------------------------------------------------------------------------------------------\n");
+                       "---------------------------------------------------------------------------------------------------------------------\n");
        }
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -1605,7 +1606,7 @@ static void pim_show_interface_traffic_single(struct pim_instance *pim,
                        json_object_object_add(json, ifp->name, json_row);
                } else {
                        vty_out(vty,
-                               "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
+                               "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n",
                                ifp->name, pim_ifp->pim_ifstat_hello_recv,
                                pim_ifp->pim_ifstat_hello_sent,
                                pim_ifp->pim_ifstat_join_recv,
@@ -1687,7 +1688,7 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
                } else
                        json_object_object_add(json_grp, ch_src_str, json_row);
        } else {
-               vty_out(vty, "%-9s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
+               vty_out(vty, "%-16s %-15s %-15s %-15s %-10s %8s %-6s %5s\n",
                        ch->interface->name, inet_ntoa(ifaddr), ch_src_str,
                        ch_grp_str,
                        pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
@@ -1709,7 +1710,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, bool uj)
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface Address         Source          Group           State      Uptime   Expire Prune\n");
+                       "Interface        Address         Source          Group           State      Uptime   Expire Prune\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
@@ -1957,7 +1958,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                vty_out(vty,
                        "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)");
                vty_out(vty,
-                       "\nInstalled Source           Group            IIF      OIL\n");
+                       "\nInstalled Source           Group            IIF               OIL\n");
        }
 
        for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
@@ -2040,9 +2041,8 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
                                                    c_oil->cc.wrong_if);
                        }
                } else {
-                       vty_out(vty, "%-9d %-15s  %-15s  %-7s  ",
-                               c_oil->installed, src_str, grp_str,
-                               in_ifname);
+                       vty_out(vty, "%-9d %-15s  %-15s  %-16s  ",
+                               c_oil->installed, src_str, grp_str, in_ifname);
                }
 
                for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
@@ -2159,7 +2159,7 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        } else {
                vty_out(vty,
-                       "Interface         Neighbor    Uptime  Holdtime  DR Pri\n");
+                       "Interface                Neighbor    Uptime  Holdtime  DR Pri\n");
        }
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2201,7 +2201,7 @@ static void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
                                                       neigh_src_str, json_row);
 
                        } else {
-                               vty_out(vty, "%-9s  %15s  %8s  %8s  %6d\n",
+                               vty_out(vty, "%-16s  %15s  %8s  %8s  %6d\n",
                                        ifp->name, neigh_src_str, uptime,
                                        expire, neigh->dr_priority);
                        }
@@ -2226,7 +2226,7 @@ static void pim_show_neighbors_secondary(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Neighbor        Secondary      \n");
+               "Interface        Address         Neighbor        Secondary      \n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -2263,7 +2263,7 @@ static void pim_show_neighbors_secondary(struct pim_instance *pim,
                                prefix2str(p, neigh_sec_str,
                                           sizeof(neigh_sec_str));
 
-                               vty_out(vty, "%-9s %-15s %-15s %-15s\n",
+                               vty_out(vty, "%-16s %-15s %-15s %-15s\n",
                                        ifp->name, inet_ntoa(ifaddr),
                                        neigh_src_str, neigh_sec_str);
                        }
@@ -2350,7 +2350,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Iif       Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n");
+                       "Iif             Source          Group           State       Uptime   JoinTimer RSTimer   KATimer   RefCnt\n");
 
        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
                char src_str[INET_ADDRSTRLEN];
@@ -2370,9 +2370,10 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                                         up->t_join_timer);
 
                /*
-                * If we have a J/P timer for the neighbor display that
+                * If the upstream is not dummy and it has a J/P timer for the
+                * neighbor display that
                 */
-               if (!up->t_join_timer) {
+               if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
                        struct pim_neighbor *nbr;
 
                        nbr = pim_neighbor_find(
@@ -2412,8 +2413,10 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                        json_row = json_object_new_object();
                        json_object_pim_upstream_add(json_row, up);
                        json_object_string_add(
-                               json_row, "inboundInterface",
-                               up->rpf.source_nexthop.interface->name);
+                           json_row, "inboundInterface",
+                           up->rpf.source_nexthop.interface
+                               ? up->rpf.source_nexthop.interface->name
+                               : "Unknown");
 
                        /*
                         * The RPF address we use is slightly different
@@ -2462,9 +2465,11 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
                        json_object_object_add(json_group, src_str, json_row);
                } else {
                        vty_out(vty,
-                               "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
-                               up->rpf.source_nexthop.interface->name, src_str,
-                               grp_str, state_str, uptime, join_timer,
+                               "%-16s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n",
+                               up->rpf.source_nexthop.interface
+                                   ? up->rpf.source_nexthop.interface->name
+                                   : "Unknown",
+                               src_str, grp_str, state_str, uptime, join_timer,
                                rs_timer, ka_timer, up->ref_count);
                }
        }
@@ -2522,7 +2527,7 @@ 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, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
+               vty_out(vty, "%-16s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n",
                        ch->interface->name, src_str, grp_str,
                        pim_macro_ch_lost_assert(ch) ? "yes" : "no",
                        pim_macro_chisin_joins(ch) ? "yes" : "no",
@@ -2548,7 +2553,7 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n");
+                       "Interface        Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD\n");
 
        /* scan per-interface (S,G) state */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2584,7 +2589,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Source          Group           RpfIface RibNextHop      RpfAddress     \n");
+                       "Source          Group           RpfIface         RibNextHop      RpfAddress     \n");
 
        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
                char src_str[INET_ADDRSTRLEN];
@@ -2627,7 +2632,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
                                               rpf_addr_str);
                        json_object_object_add(json_group, src_str, json_row);
                } else {
-                       vty_out(vty, "%-15s %-15s %-8s %-15s %-15s\n", src_str,
+                       vty_out(vty, "%-15s %-15s %-16s %-15s %-15s\n", src_str,
                                grp_str, rpf_ifname, rpf_nexthop_str,
                                rpf_addr_str);
                }
@@ -2721,7 +2726,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
                show_rpf_refresh_stats(vty, pim, now, json);
                vty_out(vty, "\n");
                vty_out(vty,
-                       "Source          Group           RpfIface RpfAddress      RibNextHop      Metric Pref\n");
+                       "Source          Group           RpfIface         RpfAddress      RibNextHop      Metric Pref\n");
        }
 
        for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) {
@@ -2769,7 +2774,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
                        json_object_object_add(json_group, src_str, json_row);
 
                } else {
-                       vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n",
+                       vty_out(vty, "%-15s %-15s %-16s %-15s %-15s %6d %4d\n",
                                src_str, grp_str, rpf_ifname, rpf_addr_str,
                                rib_nexthop_str,
                                rpf->source_nexthop.mrib_route_metric,
@@ -2804,7 +2809,7 @@ static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
                ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
 
                vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4));
-               vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL");
+               vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
                vty_out(vty, "%s ", inet_ntoa(nh_node->gate.ipv4));
                vty_out(vty, "\n");
        }
@@ -2819,8 +2824,8 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
        cwd.pim = pim;
        vty_out(vty, "Number of registered addresses: %lu\n",
                pim->rpf_hash->count);
-       vty_out(vty, "Address         Interface      Nexthop\n");
-       vty_out(vty, "-------------------------------------------\n");
+       vty_out(vty, "Address         Interface        Nexthop\n");
+       vty_out(vty, "---------------------------------------------\n");
 
        hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
 }
@@ -2839,7 +2844,7 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "Interface Address         Group           Mode Timer    Srcs V Uptime  \n");
+                       "Interface        Address         Group           Mode Timer    Srcs V Uptime  \n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2919,7 +2924,7 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
 
                                } else {
                                        vty_out(vty,
-                                               "%-9s %-15s %-15s %4s %8s %4d %d %8s\n",
+                                               "%-16s %-15s %-15s %4s %8s %4d %d %8s\n",
                                                ifp->name, ifaddr_str,
                                                group_str,
                                                grp->igmp_version == 3
@@ -2951,7 +2956,7 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Group           RetTimer Counter RetSrcs\n");
+               "Interface        Address         Group           RetTimer Counter RetSrcs\n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2999,7 +3004,7 @@ static void igmp_show_group_retransmission(struct pim_instance *pim,
                                        }
                                }
 
-                               vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d\n",
+                               vty_out(vty, "%-16s %-15s %-15s %-8s %7d %7d\n",
                                        ifp->name, ifaddr_str, group_str,
                                        grp_retr_mmss,
                                        grp->group_specific_query_retransmit_count,
@@ -3018,7 +3023,7 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
        now = pim_time_monotonic_sec();
 
        vty_out(vty,
-               "Interface Address         Group           Source          Timer Fwd Uptime  \n");
+               "Interface        Address         Group           Source          Timer Fwd Uptime  \n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3070,7 +3075,7 @@ static void igmp_show_sources(struct pim_instance *pim, struct vty *vty)
                                                now - src->source_creation);
 
                                        vty_out(vty,
-                                               "%-9s %-15s %-15s %-15s %5s %3s %8s\n",
+                                               "%-16s %-15s %-15s %-15s %5s %3s %8s\n",
                                                ifp->name, ifaddr_str,
                                                group_str, source_str, mmss,
                                                IGMP_SOURCE_TEST_FORWARDING(
@@ -3091,7 +3096,7 @@ static void igmp_show_source_retransmission(struct pim_instance *pim,
        struct interface *ifp;
 
        vty_out(vty,
-               "Interface Address         Group           Source          Counter\n");
+               "Interface        Address         Group           Source          Counter\n");
 
        /* scan interfaces */
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3133,7 +3138,7 @@ static void igmp_show_source_retransmission(struct pim_instance *pim,
                                                source_str, sizeof(source_str));
 
                                        vty_out(vty,
-                                               "%-9s %-15s %-15s %-15s %7d\n",
+                                               "%-16s %-15s %-15s %-15s %7d\n",
                                                ifp->name, ifaddr_str,
                                                group_str, source_str,
                                                src->source_query_retransmit_count);
@@ -4373,7 +4378,7 @@ static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
        vty_out(vty, "\n");
 
        vty_out(vty,
-               "Interface Address            ifi Vif  PktsIn PktsOut    BytesIn   BytesOut\n");
+               "Interface        Address            ifi Vif  PktsIn PktsOut    BytesIn   BytesOut\n");
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                struct pim_interface *pim_ifp;
@@ -4398,7 +4403,7 @@ static void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty)
 
                ifaddr = pim_ifp->primary_address;
 
-               vty_out(vty, "%-12s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
+               vty_out(vty, "%-16s %-15s %3d %3d %7lu %7lu %10lu %10lu\n",
                        ifp->name, inet_ntoa(ifaddr), ifp->ifindex,
                        pim_ifp->mroute_vif_index, (unsigned long)vreq.icount,
                        (unsigned long)vreq.ocount, (unsigned long)vreq.ibytes,
@@ -4527,7 +4532,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                json = json_object_new_object();
        } else {
                vty_out(vty,
-                       "Source          Group           Proto  Input      Output     TTL  Uptime\n");
+                       "Source          Group           Proto  Input            Output           TTL  Uptime\n");
        }
 
        now = pim_time_monotonic_sec();
@@ -4589,7 +4594,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
                     ++oif_vif_index) {
                        struct interface *ifp_out;
-                       char oif_uptime[10];
+                       char mroute_uptime[10];
                        int ttl;
 
                        ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
@@ -4598,8 +4603,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
 
                        ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
                        pim_time_uptime(
-                               oif_uptime, sizeof(oif_uptime),
-                               now - c_oil->oif_creation[oif_vif_index]);
+                               mroute_uptime, sizeof(mroute_uptime),
+                               now - c_oil->mroute_creation);
                        found_oif = 1;
 
                        if (ifp_out)
@@ -4647,7 +4652,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                                    oif_vif_index);
                                json_object_int_add(json_ifp_out, "ttl", ttl);
                                json_object_string_add(json_ifp_out, "upTime",
-                                                      oif_uptime);
+                                                      mroute_uptime);
                                if (!json_oil) {
                                        json_oil = json_object_new_object();
                                        json_object_object_add(json_source,
@@ -4677,9 +4682,9 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                }
 
                                vty_out(vty,
-                                       "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n",
+                                       "%-15s %-15s %-6s %-16s %-16s %-3d  %8s\n",
                                        src_str, grp_str, proto, in_ifname,
-                                       out_ifname, ttl, oif_uptime);
+                                       out_ifname, ttl, mroute_uptime);
 
                                if (first) {
                                        src_str[0] = '\0';
@@ -4691,7 +4696,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                }
 
                if (!uj && !found_oif) {
-                       vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d  %8s\n",
+                       vty_out(vty, "%-15s %-15s %-6s %-16s %-16s %-3d  %8s\n",
                                src_str, grp_str, "none", in_ifname, "none", 0,
                                "--:--:--");
                }
@@ -4798,7 +4803,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
                                                       json_ifp_out);
                        } else {
                                vty_out(vty,
-                                       "%-15s %-15s %-6s %-10s %-10s %-3d  %8s %s\n",
+                                       "%-15s %-15s %-6s %-16s %-16s %-3d  %8s %s\n",
                                        src_str, grp_str, proto, in_ifname,
                                        out_ifname, ttl, oif_uptime,
                                        pim->vrf->name);
@@ -4813,7 +4818,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, bool fill,
 
                if (!uj && !found_oif) {
                        vty_out(vty,
-                               "%-15s %-15s %-6s %-10s %-10s %-3d  %8s %s\n",
+                               "%-15s %-15s %-6s %-16s %-16s %-3d  %8s %s\n",
                                src_str, grp_str, proto, in_ifname, "none", 0,
                                "--:--:--", pim->vrf->name);
                }
@@ -5021,7 +5026,7 @@ DEFUN (show_ip_rib,
                return CMD_WARNING;
        }
 
-       if (pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
+       if (!pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
                vty_out(vty,
                        "Failure querying RIB nexthop for unicast address %s\n",
                        addr_str);
@@ -5159,16 +5164,14 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim,
 
        switch (pim->spt.switchover) {
        case PIM_SPT_IMMEDIATE:
-               if (pim->spt.plist)
-                       XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+               XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
 
                pim_upstream_add_lhr_star_pimreg(pim);
                break;
        case PIM_SPT_INFINITY:
                pim_upstream_remove_lhr_star_pimreg(pim, plist);
 
-               if (pim->spt.plist)
-                       XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+               XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
 
                if (plist)
                        pim->spt.plist =
@@ -6353,8 +6356,8 @@ DEFUN (interface_ip_pim_drprio,
        pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
 
        if (old_dr_prio != pim_ifp->pim_dr_priority) {
-               if (pim_if_dr_election(ifp))
-                       pim_hello_restart_now(ifp);
+               pim_if_dr_election(ifp);
+               pim_hello_restart_now(ifp);
        }
 
        return CMD_SUCCESS;
@@ -6379,8 +6382,8 @@ DEFUN (interface_no_ip_pim_drprio,
 
        if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
                pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
-               if (pim_if_dr_election(ifp))
-                       pim_hello_restart_now(ifp);
+               pim_if_dr_election(ifp);
+               pim_hello_restart_now(ifp);
        }
 
        return CMD_SUCCESS;
@@ -7411,14 +7414,6 @@ DEFUN (no_debug_msdp,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN (no_debug_msdp,
-              undebug_msdp_cmd,
-              "undebug msdp",
-              UNDEBUG_STR DEBUG_MSDP_STR)
-
 DEFUN (debug_msdp_events,
        debug_msdp_events_cmd,
        "debug msdp events",
@@ -7442,16 +7437,6 @@ DEFUN (no_debug_msdp_events,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN (no_debug_msdp_events,
-              undebug_msdp_events_cmd,
-              "undebug msdp events",
-              UNDEBUG_STR
-              DEBUG_MSDP_STR
-              DEBUG_MSDP_EVENTS_STR)
-
 DEFUN (debug_msdp_packets,
        debug_msdp_packets_cmd,
        "debug msdp packets",
@@ -7475,16 +7460,6 @@ DEFUN (no_debug_msdp_packets,
        return CMD_SUCCESS;
 }
 
-#if CONFDATE > 20190402
-CPP_NOTICE("bgpd: time to remove undebug commands")
-#endif
-ALIAS_HIDDEN (no_debug_msdp_packets,
-              undebug_msdp_packets_cmd,
-              "undebug msdp packets",
-              UNDEBUG_STR
-              DEBUG_MSDP_STR
-              DEBUG_MSDP_PACKETS_STR)
-
 DEFUN (debug_mtrace,
        debug_mtrace_cmd,
        "debug mtrace",
@@ -8918,13 +8893,10 @@ void pim_cmd_init(void)
        install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
        install_element(ENABLE_NODE, &debug_msdp_cmd);
        install_element(ENABLE_NODE, &no_debug_msdp_cmd);
-       install_element(ENABLE_NODE, &undebug_msdp_cmd);
        install_element(ENABLE_NODE, &debug_msdp_events_cmd);
        install_element(ENABLE_NODE, &no_debug_msdp_events_cmd);
-       install_element(ENABLE_NODE, &undebug_msdp_events_cmd);
        install_element(ENABLE_NODE, &debug_msdp_packets_cmd);
        install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd);
-       install_element(ENABLE_NODE, &undebug_msdp_packets_cmd);
        install_element(ENABLE_NODE, &debug_mtrace_cmd);
        install_element(ENABLE_NODE, &no_debug_mtrace_cmd);
 
@@ -8962,13 +8934,10 @@ void pim_cmd_init(void)
        install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
        install_element(CONFIG_NODE, &debug_msdp_cmd);
        install_element(CONFIG_NODE, &no_debug_msdp_cmd);
-       install_element(CONFIG_NODE, &undebug_msdp_cmd);
        install_element(CONFIG_NODE, &debug_msdp_events_cmd);
        install_element(CONFIG_NODE, &no_debug_msdp_events_cmd);
-       install_element(CONFIG_NODE, &undebug_msdp_events_cmd);
        install_element(CONFIG_NODE, &debug_msdp_packets_cmd);
        install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd);
-       install_element(CONFIG_NODE, &undebug_msdp_packets_cmd);
        install_element(CONFIG_NODE, &debug_mtrace_cmd);
        install_element(CONFIG_NODE, &no_debug_mtrace_cmd);
 
index 6933f4d5bd0af0457e1134bee61e79db40f0ecb4..92d21cf42960621673f537eea61d6be37f884e5e 100644 (file)
@@ -208,8 +208,7 @@ void pim_if_delete(struct interface *ifp)
        list_delete(&pim_ifp->upstream_switch_list);
        list_delete(&pim_ifp->sec_addr_list);
 
-       if (pim_ifp->boundary_oil_plist)
-               XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
+       XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
 
        while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
                ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
index 14ce8d7d9f63d9f2da391becf76dd17acae622ba..0fe4110f6053442cd66d9b66a359d5afc75e3868 100644 (file)
@@ -911,7 +911,7 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
        if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) {
                if (PIM_DEBUG_TRACE)
                        zlog_debug(
-                               "%s: Received prune with no relevant ifchannel %s(%s) state: %d",
+                               "%s: Received prune with no relevant ifchannel %s%s state: %d",
                                __PRETTY_FUNCTION__, ifp->name,
                                pim_str_sg_dump(sg), source_flags);
                return;
index 1fb624a6a0bde85f6542697ed8312eef70020c1f..0758e2f784eb6c7ddec8300fe0b7b1d39e1fd701 100644 (file)
@@ -66,16 +66,13 @@ static bool mtrace_fwd_info_weak(struct pim_instance *pim,
        struct pim_nexthop nexthop;
        struct interface *ifp_in;
        struct in_addr nh_addr;
-       int ret;
        char nexthop_str[INET_ADDRSTRLEN];
 
        nh_addr.s_addr = 0;
 
        memset(&nexthop, 0, sizeof(nexthop));
 
-       ret = pim_nexthop_lookup(pim, &nexthop, mtracep->src_addr, 1);
-
-       if (ret != 0) {
+       if (!pim_nexthop_lookup(pim, &nexthop, mtracep->src_addr, 1)) {
                if (PIM_DEBUG_MTRACE)
                        zlog_debug("mtrace not found neighbor");
                return false;
@@ -133,6 +130,13 @@ static bool mtrace_fwd_info(struct pim_instance *pim,
        if (!up)
                return false;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return false;
+       }
+
        ifp_in = up->rpf.source_nexthop.interface;
        nh_addr = up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4;
        total = htonl(MTRACE_UNKNOWN_COUNT);
@@ -411,9 +415,7 @@ static int mtrace_un_forward_packet(struct pim_instance *pim, struct ip *ip_hdr,
 
        if (interface == NULL) {
                memset(&nexthop, 0, sizeof(nexthop));
-               ret = pim_nexthop_lookup(pim, &nexthop, ip_hdr->ip_dst, 0);
-
-               if (ret != 0) {
+               if (!pim_nexthop_lookup(pim, &nexthop, ip_hdr->ip_dst, 0)) {
                        close(fd);
                        if (PIM_DEBUG_MTRACE)
                                zlog_warn(
@@ -561,7 +563,6 @@ static int mtrace_send_response(struct pim_instance *pim,
                                struct igmp_mtrace *mtracep, size_t mtrace_len)
 {
        struct pim_nexthop nexthop;
-       int ret;
 
        mtracep->type = PIM_IGMP_MTRACE_RESPONSE;
 
@@ -592,9 +593,7 @@ static int mtrace_send_response(struct pim_instance *pim,
        } else {
                memset(&nexthop, 0, sizeof(nexthop));
                /* TODO: should use unicast rib lookup */
-               ret = pim_nexthop_lookup(pim, &nexthop, mtracep->rsp_addr, 1);
-
-               if (ret != 0) {
+               if (!pim_nexthop_lookup(pim, &nexthop, mtracep->rsp_addr, 1)) {
                        if (PIM_DEBUG_MTRACE)
                                zlog_warn(
                                        "Dropped response qid=%ud, no route to "
index ae5032be73f7d41088a7e19f54babc2f8351d8ef..cbacaf3ea872733b4c749c3875e2230cf6c68bb2 100644 (file)
@@ -439,9 +439,6 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
        size_t packet_size = 0;
        size_t group_size = 0;
 
-       on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface,
-                rpf->rpf_addr.u.prefix4);
-
        if (rpf->source_nexthop.interface)
                pim_ifp = rpf->source_nexthop.interface->info;
        else {
@@ -450,6 +447,9 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
                return -1;
        }
 
+       on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface,
+               rpf->rpf_addr.u.prefix4);
+
        if (!pim_ifp) {
                zlog_warn("%s: multicast not enabled on interface %s",
                          __PRETTY_FUNCTION__,
index 7726ffda576da4c1e982ffec1c0fe035f82fe2cd..06a9e6d0d646888b2d0bbca6b31b3b95cb6404b2 100644 (file)
@@ -213,8 +213,18 @@ void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore)
 {
 #ifdef PIM_JP_AGG_DEBUG
        struct interface *ifp;
-       struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info;
-       struct pim_instance *pim = pim_ifp->pim;
+       struct pim_interface *pim_ifp;
+       struct pim_instance *pim;
+
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
+       pim_ifp = up->rpf.source_nexthop.interface->info;
+       pim = pim_ifp->pim;
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
index dc42899c7b924c6288e95d3a8832c4098101a0e2..5a8991c4c0b64332977c07d74239aa94b026c863 100644 (file)
@@ -68,7 +68,7 @@ struct zebra_privs_t pimd_privs = {
        .vty_group = VTY_GROUP,
 #endif
        .caps_p = _caps_p,
-       .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]),
+       .cap_num_p = array_size(_caps_p),
        .cap_num_i = 0};
 
 static const struct frr_yang_module_info *pimd_yang_modules[] = {
index dd9e21cae8782a030f8e498376b4f918d91e8278..a2d50aba5159c5b8f5d7b3360ee2122914836303 100644 (file)
@@ -234,7 +234,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
        up->channel_oil->cc.pktcnt++;
        PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
        // resolve mfcc_parent prior to mroute_add in channel_add_oif
-       if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) {
+       if (up->rpf.source_nexthop.interface &&
+           up->channel_oil->oil.mfcc_parent >= MAXVIFS) {
                int vif_index = 0;
                vif_index = pim_if_find_vifindex_by_ifindex(
                        pim_ifp->pim,
@@ -301,6 +302,13 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                return 0;
        }
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return 0;
+       }
+
        pim_ifp = up->rpf.source_nexthop.interface->info;
 
        rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL;
@@ -505,8 +513,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) {
                        // No if channel, but upstream we are at the RP.
                        if (pim_nexthop_lookup(pim_ifp->pim, &source,
-                                              up->upstream_register, 0)
-                           == 0) {
+                                              up->upstream_register, 0)) {
                                pim_register_stop_send(source.interface, &sg,
                                                       pim_ifp->primary_address,
                                                       up->upstream_register);
@@ -523,8 +530,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                } else {
                        if (I_am_RP(pim_ifp->pim, up->sg.grp)) {
                                if (pim_nexthop_lookup(pim_ifp->pim, &source,
-                                                      up->upstream_register, 0)
-                                   == 0)
+                                                      up->upstream_register,
+                                                      0))
                                        pim_register_stop_send(
                                                source.interface, &sg,
                                                pim_ifp->primary_address,
@@ -956,6 +963,8 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
        }
 
        c_oil->installed = 1;
+       c_oil->mroute_creation = pim_time_monotonic_sec();
+
        return 0;
 }
 
@@ -1022,7 +1031,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
                        sg.grp = c_oil->oil.mfcc_mcastgrp;
                        if (PIM_DEBUG_MROUTE)
                                zlog_debug(
-                                       "Channel(%s) is not installed no need to collect data from kernel",
+                                       "Channel%s is not installed no need to collect data from kernel",
                                        pim_str_sg_dump(&sg));
                }
                return;
@@ -1041,7 +1050,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
                        sg.grp = c_oil->oil.mfcc_mcastgrp;
 
                        zlog_warn(
-                               "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s",
+                               "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=%s: errno=%d: %s",
                                (unsigned long)SIOCGETSGCNT,
                                pim_str_sg_dump(&sg), errno,
                                safe_strerror(errno));
index a4f87fa1a65c36d68e8530af18939091d6d6cbd3..395c4af35f941b93f6778f691e4e599cc3f6a096 100644 (file)
@@ -1256,8 +1256,7 @@ static void pim_msdp_mg_free(struct pim_instance *pim)
        if (PIM_DEBUG_MSDP_EVENTS) {
                zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name);
        }
-       if (mg->mesh_group_name)
-               XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name);
+       XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name);
 
        if (mg->mbr_list)
                list_delete(&mg->mbr_list);
index 436f2dec277e723e1fc748546289e61c688b7789..a63b09fc1f9a05b4119bb85eefda954224788010 100644 (file)
@@ -540,7 +540,7 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
           Upon PIM neighbor UP, iterate all RPs and update
           nexthop cache with this neighbor.
         */
-       pim_resolve_rp_nh(pim_ifp->pim);
+       pim_resolve_rp_nh(pim_ifp->pim, neigh);
 
        pim_rp_setup(pim_ifp->pim);
 
index b6cd1a7d11493f49a5076149b43125c7de8b7d09..5e550dfe853558084cd8c2c0528623d6963436d5 100644 (file)
@@ -39,6 +39,7 @@
 #include "pim_jp_agg.h"
 #include "pim_zebra.h"
 #include "pim_zlookup.h"
+#include "pim_rp.h"
 
 /**
  * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
@@ -170,6 +171,8 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
        struct pim_nexthop_cache *pnc = NULL;
        struct pim_nexthop_cache lookup;
        struct zclient *zclient = NULL;
+       struct listnode *upnode = NULL;
+       struct pim_upstream *upstream = NULL;
 
        zclient = pim_zebra_zclient_get();
 
@@ -177,8 +180,30 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
        lookup.rpf.rpf_addr = *addr;
        pnc = hash_lookup(pim->rpf_hash, &lookup);
        if (pnc) {
-               if (rp)
+               if (rp) {
+                       /* Release the (*, G)upstream from pnc->upstream_hash,
+                        * whose Group belongs to the RP getting deleted
+                        */
+                       for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
+                               upstream)) {
+                               struct prefix grp;
+                               struct rp_info *trp_info;
+
+                               if (upstream->sg.src.s_addr != INADDR_ANY)
+                                       continue;
+
+                               grp.family = AF_INET;
+                               grp.prefixlen = IPV4_MAX_BITLEN;
+                               grp.u.prefix4 = upstream->sg.grp;
+
+                               trp_info = pim_rp_find_match_group(pim, &grp);
+                               if (trp_info == rp)
+                                       hash_release(pnc->upstream_hash,
+                                                    upstream);
+                       }
                        listnode_delete(pnc->rp_list, rp);
+               }
+
                if (up)
                        hash_release(pnc->upstream_hash, up);
 
@@ -207,6 +232,17 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr,
        }
 }
 
+void pim_rp_nexthop_del(struct rp_info *rp_info)
+{
+       rp_info->rp.source_nexthop.interface = NULL;
+       rp_info->rp.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr =
+               PIM_NET_INADDR_ANY;
+       rp_info->rp.source_nexthop.mrib_metric_preference =
+               router->infinite_assert_metric.metric_preference;
+       rp_info->rp.source_nexthop.mrib_route_metric =
+               router->infinite_assert_metric.route_metric;
+}
+
 /* Update RP nexthop info based on Nexthop update received from Zebra.*/
 static void pim_update_rp_nh(struct pim_instance *pim,
                             struct pim_nexthop_cache *pnc)
@@ -220,48 +256,11 @@ static void pim_update_rp_nh(struct pim_instance *pim,
                        continue;
 
                // Compute PIM RPF using cached nexthop
-               pim_ecmp_nexthop_search(pim, pnc, &rp_info->rp.source_nexthop,
-                                       &rp_info->rp.rpf_addr, &rp_info->group,
-                                       1);
-       }
-}
-
-/* This API is used to traverse nexthop cache of RPF addr
-   of upstream entry whose IPv4 nexthop address is in
-   unresolved state and due to event like pim neighbor
-   UP event if it can be resolved.
-*/
-void pim_resolve_upstream_nh(struct pim_instance *pim, struct prefix *nht_p)
-{
-       struct nexthop *nh_node = NULL;
-       struct pim_nexthop_cache pnc;
-       struct pim_neighbor *nbr = NULL;
-
-       memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
-       if (!pim_find_or_track_nexthop(pim, nht_p, NULL, NULL, &pnc))
-               return;
-
-       for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
-               if (nh_node->gate.ipv4.s_addr != 0)
-                       continue;
-
-               struct interface *ifp1 =
-                       if_lookup_by_index(nh_node->ifindex, pim->vrf_id);
-               nbr = pim_neighbor_find_if(ifp1);
-               if (!nbr)
-                       continue;
-
-               nh_node->gate.ipv4 = nbr->source_addr;
-               if (PIM_DEBUG_PIM_NHT) {
-                       char str[PREFIX_STRLEN];
-                       char str1[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<nht_nbr?>", nbr->source_addr, str1,
-                                      sizeof(str1));
-                       pim_addr_dump("<nht_addr?>", nht_p, str, sizeof(str));
-                       zlog_debug(
-                               "%s: addr %s new nexthop addr %s interface %s",
-                               __PRETTY_FUNCTION__, str, str1, ifp1->name);
-               }
+               if (!pim_ecmp_nexthop_search(pim, pnc,
+                   &rp_info->rp.source_nexthop,
+                   &rp_info->rp.rpf_addr, &rp_info->group,
+                   1))
+                       pim_rp_nexthop_del(rp_info);
        }
 }
 
@@ -278,12 +277,12 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
        old.source_nexthop.interface = up->rpf.source_nexthop.interface;
        rpf_result = pim_rpf_update(pim, up, &old, 0);
        if (rpf_result == PIM_RPF_FAILURE) {
-               pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+               pim_upstream_rpf_clear(pim, up);
                return HASHWALK_CONTINUE;
        }
 
        /* update kernel multicast forwarding cache (MFC) */
-       if (up->channel_oil) {
+       if (up->rpf.source_nexthop.interface) {
                ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
 
                vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex);
@@ -306,9 +305,10 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
 
        if (PIM_DEBUG_PIM_NHT) {
                zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s",
-                          __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
-                          old.source_nexthop.interface->name,
-                          up->rpf.source_nexthop.interface->name);
+                       __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
+                       old.source_nexthop.interface
+                       ? old.source_nexthop.interface->name : "Unknwon",
+                       up->rpf.source_nexthop.interface->name);
        }
 
        return HASHWALK_CONTINUE;
index 796fbf9731943f2ca58278527ba516341455d630..e3e9f578c9f151708ab4fca823ad2edf07afda6c 100644 (file)
@@ -65,7 +65,7 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
                            struct prefix *grp, int neighbor_needed);
 void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
                           struct pim_nexthop_cache *pnc, int command);
-void pim_resolve_upstream_nh(struct pim_instance *pim, struct prefix *nht_p);
 int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim,
                                     struct prefix *src, struct prefix *grp);
+void pim_rp_nexthop_del(struct rp_info *rp_info);
 #endif
index 2e12d728cfd4d68927ffc2420d0e0d296ec0d7ef..55d26113f7c51981729486117c00599589a6fb3d 100644 (file)
@@ -168,13 +168,15 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
                return c_oil;
        }
 
-       ifp = pim_if_find_by_vif_index(pim, input_vif_index);
-       if (!ifp) {
-               /* warning only */
-               zlog_warn(
-                       "%s: (S,G)=%s could not find input interface for input_vif_index=%d",
-                       __PRETTY_FUNCTION__, pim_str_sg_dump(sg),
-                       input_vif_index);
+       if (input_vif_index != MAXVIFS) {
+               ifp = pim_if_find_by_vif_index(pim, input_vif_index);
+               if (!ifp) {
+                       /* warning only */
+                       zlog_warn(
+                               "%s: (S,G)=%s could not find input interface for input_vif_index=%d",
+                               __PRETTY_FUNCTION__, pim_str_sg_dump(sg),
+                               input_vif_index);
+               }
        }
 
        c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil));
@@ -447,25 +449,31 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
        channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] =
                PIM_MROUTE_MIN_TTL;
 
-       if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
-               if (PIM_DEBUG_MROUTE) {
-                       char group_str[INET_ADDRSTRLEN];
-                       char source_str[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<group?>",
-                                      channel_oil->oil.mfcc_mcastgrp,
-                                      group_str, sizeof(group_str));
-                       pim_inet4_dump("<source?>",
-                                      channel_oil->oil.mfcc_origin, source_str,
-                                      sizeof(source_str));
-                       zlog_debug(
-                               "%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
-                               __FILE__, __PRETTY_FUNCTION__, oif->name,
-                               pim_ifp->mroute_vif_index, source_str,
-                               group_str);
-               }
+       /* channel_oil->oil.mfcc_parent != MAXVIFS indicate this entry is not
+        * valid to get installed in kernel.
+        */
+       if (channel_oil->oil.mfcc_parent != MAXVIFS) {
+               if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
+                       if (PIM_DEBUG_MROUTE) {
+                               char group_str[INET_ADDRSTRLEN];
+                               char source_str[INET_ADDRSTRLEN];
+                               pim_inet4_dump("<group?>",
+                                     channel_oil->oil.mfcc_mcastgrp,
+                                     group_str, sizeof(group_str));
+                               pim_inet4_dump("<source?>",
+                                     channel_oil->oil.mfcc_origin, source_str,
+                                     sizeof(source_str));
+                               zlog_debug(
+                                   "%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
+                                   __FILE__, __PRETTY_FUNCTION__, oif->name,
+                                   pim_ifp->mroute_vif_index, source_str,
+                                   group_str);
+                       }
 
-               channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
-               return -5;
+                       channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]
+                               = old_ttl;
+                       return -5;
+               }
        }
 
        channel_oil->oif_creation[pim_ifp->mroute_vif_index] =
index 94d3840e98db72aafa561e706620cac66f0ed399..8b95324142c23f4f5c2261228fb14b7d9a9e37cd 100644 (file)
@@ -64,6 +64,25 @@ struct channel_counts {
 
   Each channel_oil.oil is used to control an (S,G) entry in the Kernel
   Multicast Forwarding Cache.
+
+  There is a case when we create a channel_oil but don't install in the kernel
+
+  Case where (S, G) entry not installed in the kernel:
+    FRR receives IGMP/PIM (*, G) join and RP is not configured or
+    not-reachable, then create a channel_oil for the group G with the incoming
+    interface(channel_oil.oil.mfcc_parent) as invalid i.e "MAXVIF" and populate
+    the outgoing interface where join is received. Keep this entry in the stack,
+    but don't install in the kernel(channel_oil.installed = 0).
+
+  Case where (S, G) entry installed in the kernel:
+    When RP is configured and is reachable for the group G, and receiving a
+    join if channel_oil is already present then populate the incoming interface
+    and install the entry in the kernel, if channel_oil not present, then create
+    a new_channel oil(channel_oil.installed = 1).
+
+  is_valid: indicate if this entry is valid to get installed in kernel.
+  installed: indicate if this entry is installed in the kernel.
+
 */
 
 struct channel_oil {
@@ -78,6 +97,7 @@ struct channel_oil {
        uint32_t oif_flags[MAXVIFS];
        struct channel_counts cc;
        struct pim_upstream *up;
+       time_t mroute_creation;
 };
 
 extern struct list *pim_channel_oil_list;
index 4b402de6348e10f651b396ac3b2dd7fd9b2d3f5c..386ed1d4240775ffeab660e64fbd86d208734ef1 100644 (file)
@@ -97,7 +97,7 @@ void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg,
        pinfo = (struct pim_interface *)ifp->info;
        if (!pinfo) {
                if (PIM_DEBUG_PIM_TRACE)
-                       zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__);
+                       zlog_debug("%s: No pinfo!", __PRETTY_FUNCTION__);
                return;
        }
        if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer,
@@ -279,14 +279,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
 #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
        ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
 
-       if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, ip_hdr->ip_dst,
-                                          dest_addr)) {
+       if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, dest_addr)) {
                if (PIM_DEBUG_PIM_REG) {
                        char dest[INET_ADDRSTRLEN];
 
                        pim_inet4_dump("<dst?>", dest_addr, dest, sizeof(dest));
                        zlog_debug(
-                               "%s: Received Register message for %s that I do not own",
+                               "%s: Received Register message for destination address: %s that I do not own",
                                __func__, dest);
                }
                return 0;
@@ -330,9 +329,8 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
                char src_str[INET_ADDRSTRLEN];
 
                pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
-               zlog_debug(
-                       "Received Register message(%s) from %s on %s, rp: %d",
-                       pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp);
+               zlog_debug("Received Register message%s from %s on %s, rp: %d",
+                          pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp);
        }
 
        if (i_am_rp
index 08f2ffc4ea5396794b3d5ae46c41d83c11de8de4..4e285720a205694a237d6fe4326420deed052e7c 100644 (file)
@@ -45,7 +45,9 @@
 #include "pim_iface.h"
 #include "pim_msdp.h"
 #include "pim_nht.h"
-
+#include "pim_mroute.h"
+#include "pim_oil.h"
+#include "pim_zebra.h"
 
 /* Cleanup pim->rpf_hash each node data */
 void pim_rp_list_hash_clean(void *data)
@@ -65,8 +67,7 @@ void pim_rp_list_hash_clean(void *data)
 
 static void pim_rp_info_free(struct rp_info *rp_info)
 {
-       if (rp_info->plist)
-               XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
+       XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
 
        XFREE(MTYPE_PIM_RP, rp_info);
 }
@@ -201,7 +202,7 @@ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
 /*
  * Given a group, return the rp_info for that group
  */
-static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
+struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
                                               const struct prefix *group)
 {
        struct listnode *node;
@@ -334,6 +335,77 @@ static void pim_rp_check_interfaces(struct pim_instance *pim,
        }
 }
 
+void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
+{
+       struct pim_rpf old_rpf;
+       enum pim_rpf_result rpf_result;
+       struct in_addr old_upstream_addr;
+       struct in_addr new_upstream_addr;
+       struct prefix nht_p;
+
+       old_upstream_addr = up->upstream_addr;
+       pim_rp_set_upstream_addr(pim, &new_upstream_addr, up->sg.src,
+                                up->sg.grp);
+
+       if (PIM_DEBUG_TRACE)
+               zlog_debug("%s: pim upstream update for  old upstream %s",
+                          __PRETTY_FUNCTION__,
+                          inet_ntoa(old_upstream_addr));
+
+       if (old_upstream_addr.s_addr == new_upstream_addr.s_addr)
+               return;
+
+       /* Lets consider a case, where a PIM upstream has a better RP as a
+        * result of a new RP configuration with more precise group range.
+        * This upstream has to be added to the upstream hash of new RP's
+        * NHT(pnc) and has to be removed from old RP's NHT upstream hash
+        */
+       if (old_upstream_addr.s_addr != INADDR_ANY) {
+               /* Deregister addr with Zebra NHT */
+               nht_p.family = AF_INET;
+               nht_p.prefixlen = IPV4_MAX_BITLEN;
+               nht_p.u.prefix4 = old_upstream_addr;
+               if (PIM_DEBUG_TRACE) {
+                       char buf[PREFIX2STR_BUFFER];
+
+                       prefix2str(&nht_p, buf, sizeof(buf));
+                       zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
+                                  __PRETTY_FUNCTION__, up->sg_str, buf);
+               }
+               pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
+       }
+
+       /* Update the upstream address */
+       up->upstream_addr = new_upstream_addr;
+
+       old_rpf.source_nexthop.interface = up->rpf.source_nexthop.interface;
+
+       rpf_result = pim_rpf_update(pim, up, &old_rpf, 1);
+       if (rpf_result == PIM_RPF_FAILURE)
+               pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+
+       /* update kernel multicast forwarding cache (MFC) */
+       if (up->rpf.source_nexthop.interface && up->channel_oil) {
+               ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
+               int vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex);
+               /* Pass Current selected NH vif index to mroute download */
+               if (vif_index)
+                       pim_scan_individual_oil(up->channel_oil, vif_index);
+               else {
+                       if (PIM_DEBUG_PIM_NHT)
+                               zlog_debug(
+                                 "%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
+                                 __PRETTY_FUNCTION__, up->sg_str,
+                                 up->rpf.source_nexthop.interface->name);
+               }
+       }
+
+       if (rpf_result == PIM_RPF_CHANGED)
+               pim_zebra_upstream_rpf_changed(pim, up, &old_rpf);
+
+       pim_zebra_update_all_interfaces(pim);
+}
+
 int pim_rp_new(struct pim_instance *pim, const char *rp,
               const char *group_range, const char *plist)
 {
@@ -348,6 +420,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
        struct prefix temp;
        struct pim_nexthop_cache pnc;
        struct route_node *rn;
+       struct pim_upstream *up;
+       struct listnode *upnode;
 
        rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
 
@@ -469,6 +543,27 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
                                        "%s: NHT Register rp_all addr %s grp %s ",
                                        __PRETTY_FUNCTION__, buf, buf1);
                        }
+
+                       for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode,
+                                                 up)) {
+                               /* Find (*, G) upstream whose RP is not
+                                * configured yet
+                                */
+                               if ((up->upstream_addr.s_addr == INADDR_ANY)
+                                   && (up->sg.src.s_addr == INADDR_ANY)) {
+                                       struct prefix grp;
+                                       struct rp_info *trp_info;
+
+                                       grp.family = AF_INET;
+                                       grp.prefixlen = IPV4_MAX_BITLEN;
+                                       grp.u.prefix4 = up->sg.grp;
+                                       trp_info = pim_rp_find_match_group(pim,
+                                                                         &grp);
+                                       if (trp_info == rp_all)
+                                               pim_upstream_update(pim, up);
+                               }
+                       }
+
                        memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
                        if (pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all,
                                                      &pnc)) {
@@ -536,6 +631,21 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
                           rn->lock);
        }
 
+       for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
+               if (up->sg.src.s_addr == INADDR_ANY) {
+                       struct prefix grp;
+                       struct rp_info *trp_info;
+
+                       grp.family = AF_INET;
+                       grp.prefixlen = IPV4_MAX_BITLEN;
+                       grp.u.prefix4 = up->sg.grp;
+                       trp_info = pim_rp_find_match_group(pim, &grp);
+
+                       if (trp_info == rp_info)
+                               pim_upstream_update(pim, up);
+               }
+       }
+
        /* Register addr with Zebra NHT */
        nht_p.family = AF_INET;
        nht_p.prefixlen = IPV4_MAX_BITLEN;
@@ -578,6 +688,9 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
        struct prefix nht_p;
        struct route_node *rn;
        bool was_plist = false;
+       struct rp_info *trp_info;
+       struct pim_upstream *up;
+       struct listnode *upnode;
 
        if (group_range == NULL)
                result = str2prefix("224.0.0.0/4", &group);
@@ -622,6 +735,23 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
        rp_all = pim_rp_find_match_group(pim, &g_all);
 
        if (rp_all == rp_info) {
+               for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
+                       /* Find the upstream (*, G) whose upstream address is
+                        * same as the deleted RP
+                        */
+                       if ((up->upstream_addr.s_addr == rp_addr.s_addr) &&
+                           (up->sg.src.s_addr == INADDR_ANY)) {
+                               struct prefix grp;
+                               grp.family = AF_INET;
+                               grp.prefixlen = IPV4_MAX_BITLEN;
+                               grp.u.prefix4 = up->sg.grp;
+                               trp_info = pim_rp_find_match_group(pim, &grp);
+                               if (trp_info == rp_all) {
+                                       pim_upstream_rpf_clear(pim, up);
+                                       up->upstream_addr.s_addr = INADDR_ANY;
+                               }
+                       }
+               }
                rp_all->rp.rpf_addr.family = AF_INET;
                rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
                rp_all->i_am_rp = 0;
@@ -656,6 +786,34 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
 
        pim_rp_refresh_group_to_rp_mapping(pim);
 
+       for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) {
+               /* Find the upstream (*, G) whose upstream address is same as
+                * the deleted RP
+                */
+               if ((up->upstream_addr.s_addr == rp_addr.s_addr) &&
+                   (up->sg.src.s_addr == INADDR_ANY)) {
+                       struct prefix grp;
+
+                       grp.family = AF_INET;
+                       grp.prefixlen = IPV4_MAX_BITLEN;
+                       grp.u.prefix4 = up->sg.grp;
+
+                       trp_info = pim_rp_find_match_group(pim, &grp);
+
+                       /* RP not found for the group grp */
+                       if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) {
+                               pim_upstream_rpf_clear(pim, up);
+                               pim_rp_set_upstream_addr(pim,
+                                       &up->upstream_addr,
+                                       up->sg.src, up->sg.grp);
+                       }
+
+                       /* RP found for the group grp */
+                       else
+                               pim_upstream_update(pim, up);
+               }
+       }
+
        XFREE(MTYPE_PIM_RP, rp_info);
        return PIM_SUCCESS;
 }
@@ -682,6 +840,7 @@ void pim_rp_setup(struct pim_instance *pim)
                else {
                        if (PIM_DEBUG_PIM_NHT_RP) {
                                char buf[PREFIX2STR_BUFFER];
+
                                prefix2str(&nht_p, buf, sizeof(buf));
                                zlog_debug(
                                        "%s: NHT Local Nexthop not found for RP %s ",
@@ -870,7 +1029,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
  * the rp configured and the source address
  *
  * If we have don't have a RP configured and the source address is *
- * then return failure.
+ * then set the upstream addr as INADDR_ANY and return failure.
  *
  */
 int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
@@ -891,6 +1050,7 @@ int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
                if (PIM_DEBUG_PIM_NHT_RP)
                        zlog_debug("%s: Received a (*,G) with no RP configured",
                                   __PRETTY_FUNCTION__);
+               up->s_addr = INADDR_ANY;
                return 0;
        }
 
@@ -931,34 +1091,13 @@ int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
        return count;
 }
 
-int pim_rp_check_is_my_ip_address(struct pim_instance *pim,
-                                 struct in_addr group,
-                                 struct in_addr dest_addr)
+bool pim_rp_check_is_my_ip_address(struct pim_instance *pim,
+                                  struct in_addr dest_addr)
 {
-       struct rp_info *rp_info;
-       struct prefix g;
-
-       memset(&g, 0, sizeof(g));
-       g.family = AF_INET;
-       g.prefixlen = 32;
-       g.u.prefix4 = group;
-
-       rp_info = pim_rp_find_match_group(pim, &g);
-       /*
-        * See if we can short-cut some?
-        * This might not make sense if we ever leave a static RP
-        * type of configuration.
-        * Note - Premature optimization might bite our patooeys' here.
-        */
-       if (I_am_RP(pim, group)) {
-               if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr)
-                       return 1;
-       }
-
        if (if_lookup_exact_address(&dest_addr, AF_INET, pim->vrf_id))
-               return 1;
+               return true;
 
-       return 0;
+       return false;
 }
 
 void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
@@ -975,7 +1114,7 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
                json = json_object_new_object();
        else
                vty_out(vty,
-                       "RP address       group/prefix-list   OIF         I am RP\n");
+                       "RP address       group/prefix-list   OIF               I am RP\n");
 
        for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
                if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) {
@@ -1038,11 +1177,11 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
                                                           48));
 
                                if (rp_info->rp.source_nexthop.interface)
-                                       vty_out(vty, "%-10s  ",
+                                       vty_out(vty, "%-16s  ",
                                                rp_info->rp.source_nexthop
                                                        .interface->name);
                                else
-                                       vty_out(vty, "%-10s  ", "(Unknown)");
+                                       vty_out(vty, "%-16s  ", "(Unknown)");
 
                                if (rp_info->i_am_rp)
                                        vty_out(vty, "yes\n");
@@ -1067,14 +1206,13 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
        }
 }
 
-void pim_resolve_rp_nh(struct pim_instance *pim)
+void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr)
 {
        struct listnode *node = NULL;
        struct rp_info *rp_info = NULL;
        struct nexthop *nh_node = NULL;
        struct prefix nht_p;
        struct pim_nexthop_cache pnc;
-       struct pim_neighbor *nbr = NULL;
 
        for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
                if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
@@ -1094,8 +1232,8 @@ void pim_resolve_rp_nh(struct pim_instance *pim)
 
                        struct interface *ifp1 = if_lookup_by_index(
                                nh_node->ifindex, pim->vrf_id);
-                       nbr = pim_neighbor_find_if(ifp1);
-                       if (!nbr)
+
+                       if (nbr->interface != ifp1)
                                continue;
 
                        nh_node->gate.ipv4 = nbr->source_addr;
index 672a69631907c0d12ae4375e2b4d36eca7d8deb7..402ec30aba270167bdc4500dcbe81e5a54eba8dc 100644 (file)
@@ -55,9 +55,8 @@ int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group);
 void pim_rp_check_on_if_add(struct pim_interface *pim_ifp);
 void pim_i_am_rp_re_evaluate(struct pim_instance *pim);
 
-int pim_rp_check_is_my_ip_address(struct pim_instance *pim,
-                                 struct in_addr group,
-                                 struct in_addr dest_addr);
+bool pim_rp_check_is_my_ip_address(struct pim_instance *pim,
+                                  struct in_addr dest_addr);
 
 int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
                             struct in_addr source, struct in_addr group);
@@ -69,6 +68,9 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group);
 
 void pim_rp_show_information(struct pim_instance *pim, struct vty *vty,
                             bool uj);
-void pim_resolve_rp_nh(struct pim_instance *pim);
+void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr);
 int pim_rp_list_cmp(void *v1, void *v2);
+struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
+                                       const struct prefix *group);
+void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up);
 #endif
index 814d2e076bb0f581d5d20770432aed962166b024..55f788b5bb8db373295f5a9a3f77c5209f1d2483 100644 (file)
@@ -48,8 +48,8 @@ void pim_rpf_set_refresh_time(struct pim_instance *pim)
                           pim->last_route_change_time);
 }
 
-int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
-                      struct in_addr addr, int neighbor_needed)
+bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
+                       struct in_addr addr, int neighbor_needed)
 {
        struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
        struct pim_neighbor *nbr = NULL;
@@ -65,7 +65,7 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
         * it will never work
         */
        if (addr.s_addr == INADDR_NONE)
-               return -1;
+               return false;
 
        if ((nexthop->last_lookup.s_addr == addr.s_addr)
            && (nexthop->last_lookup_time > pim->last_route_change_time)) {
@@ -83,7 +83,7 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
                                pim->last_route_change_time, nexthop_str);
                }
                pim->nexthop_lookups_avoided++;
-               return 0;
+               return true;
        } else {
                if (PIM_DEBUG_TRACE) {
                        char addr_str[INET_ADDRSTRLEN];
@@ -107,7 +107,7 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
                zlog_warn(
                        "%s %s: could not find nexthop ifindex for address %s",
                        __FILE__, __PRETTY_FUNCTION__, addr_str);
-               return -1;
+               return false;
        }
 
        while (!found && (i < num_ifindex)) {
@@ -179,9 +179,9 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
                nexthop->last_lookup = addr;
                nexthop->last_lookup_time = pim_time_monotonic_usec();
                nexthop->nbr = nbr;
-               return 0;
+               return true;
        } else
-               return -1;
+               return false;
 }
 
 static int nexthop_mismatch(const struct pim_nexthop *nh1,
@@ -205,6 +205,12 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
        struct prefix src, grp;
        bool neigh_needed = true;
 
+       if (up->upstream_addr.s_addr == INADDR_ANY) {
+               zlog_debug("%s: RP is not configured yet for %s",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return PIM_RPF_OK;
+       }
+
        saved.source_nexthop = rpf->source_nexthop;
        saved.rpf_addr = rpf->rpf_addr;
 
@@ -307,6 +313,33 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
        return PIM_RPF_OK;
 }
 
+/*
+ * In the case of RP deletion and RP unreachablity,
+ * uninstall the mroute in the kernel and clear the
+ * rpf information in the pim upstream and pim channel
+ * oil data structure.
+ */
+void pim_upstream_rpf_clear(struct pim_instance *pim,
+                           struct pim_upstream *up)
+{
+       if (up->rpf.source_nexthop.interface) {
+               if (up->channel_oil) {
+                       up->channel_oil->oil.mfcc_parent = MAXVIFS;
+                       pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
+
+               }
+               pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED);
+               up->rpf.source_nexthop.interface = NULL;
+               up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr =
+                       PIM_NET_INADDR_ANY;
+               up->rpf.source_nexthop.mrib_metric_preference =
+                       router->infinite_assert_metric.metric_preference;
+               up->rpf.source_nexthop.mrib_route_metric =
+                       router->infinite_assert_metric.route_metric;
+               up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY;
+       }
+}
+
 /*
   RFC 4601: 4.1.6.  State Summarization Macros
 
index b9fe162f21c66714fca28cea618ff40d195c4ba4..57bb22674fa6209b64d9935b5c70b24f86e9b2ba 100644 (file)
@@ -59,12 +59,13 @@ struct pim_upstream;
 unsigned int pim_rpf_hash_key(void *arg);
 bool pim_rpf_equal(const void *arg1, const void *arg2);
 
-int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
-                      struct in_addr addr, int neighbor_needed);
+bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
+                       struct in_addr addr, int neighbor_needed);
 enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
                                   struct pim_upstream *up, struct pim_rpf *old,
                                   uint8_t is_new);
-
+void pim_upstream_rpf_clear(struct pim_instance *pim,
+                           struct pim_upstream *up);
 int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf);
 int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf);
 
index dfc7063fd0f6ad9f0121cccc3e6bae4fc55da869..6a70a73b4589caa253e1e6f7b0b636939f9d6870 100644 (file)
@@ -151,8 +151,7 @@ void pim_ssm_terminate(struct pim_ssm *ssm)
        if (!ssm)
                return;
 
-       if (ssm->plist_name)
-               XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);
+       XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);
 
        XFREE(MTYPE_PIM_SSM_INFO, ssm);
 }
index c6ab8f5a2af117a1f65fc012921f0b20cb041e4b..2a0804e10bc5707d85c1e86f33f17f22c9306352 100644 (file)
@@ -219,17 +219,25 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
                pim_msdp_up_del(pim, &up->sg);
        }
 
-       /* Deregister addr with Zebra NHT */
-       nht_p.family = AF_INET;
-       nht_p.prefixlen = IPV4_MAX_BITLEN;
-       nht_p.u.prefix4 = up->upstream_addr;
-       if (PIM_DEBUG_TRACE) {
-               char buf[PREFIX2STR_BUFFER];
-               prefix2str(&nht_p, buf, sizeof(buf));
-               zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
-                          __PRETTY_FUNCTION__, up->sg_str, buf);
+       /* When RP gets deleted, pim_rp_del() deregister addr with Zebra NHT
+        * and assign up->upstream_addr as INADDR_ANY.
+        * So before de-registering the upstream address, check if is not equal
+        * to INADDR_ANY. This is done in order to avoid de-registering for
+        * 255.255.255.255 which is maintained for some reason..
+        */
+       if (up->upstream_addr.s_addr != INADDR_ANY) {
+               /* Deregister addr with Zebra NHT */
+               nht_p.family = AF_INET;
+               nht_p.prefixlen = IPV4_MAX_BITLEN;
+               nht_p.u.prefix4 = up->upstream_addr;
+               if (PIM_DEBUG_TRACE) {
+                       char buf[PREFIX2STR_BUFFER];
+                       prefix2str(&nht_p, buf, sizeof(buf));
+                       zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT",
+                                  __PRETTY_FUNCTION__, up->sg_str, buf);
+               }
+               pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
        }
-       pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
 
        XFREE(MTYPE_PIM_UPSTREAM, up);
 
@@ -238,6 +246,13 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
 
 void pim_upstream_send_join(struct pim_upstream *up)
 {
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        if (PIM_DEBUG_TRACE) {
                char rpf_str[PREFIX_STRLEN];
                pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str,
@@ -263,6 +278,13 @@ static int on_join_timer(struct thread *t)
 
        up = THREAD_ARG(t);
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return 0;
+       }
+
        /*
         * In the case of a HFR we will not ahve anyone to send this to.
         */
@@ -284,12 +306,13 @@ static int on_join_timer(struct thread *t)
 
 static void join_timer_stop(struct pim_upstream *up)
 {
-       struct pim_neighbor *nbr;
+       struct pim_neighbor *nbr = NULL;
 
        THREAD_OFF(up->t_join_timer);
 
-       nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
-                               up->rpf.rpf_addr.u.prefix4);
+       if (up->rpf.source_nexthop.interface)
+               nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
+                                       up->rpf.rpf_addr.u.prefix4);
 
        if (nbr)
                pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
@@ -356,6 +379,13 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
        long t_joinsuppress_msec;
        long join_timer_remain_msec;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        t_joinsuppress_msec =
                MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface),
                    1000 * holdtime);
@@ -389,6 +419,13 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
        long join_timer_remain_msec;
        int t_override_msec;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer);
        t_override_msec =
                pim_if_t_override_msec(up->rpf.source_nexthop.interface);
@@ -511,6 +548,20 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
 {
        enum pim_upstream_state old_state = up->join_state;
 
+       if (up->upstream_addr.s_addr == INADDR_ANY) {
+               if (PIM_DEBUG_PIM_EVENTS)
+                       zlog_debug("%s: RPF not configured for %s",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
+       if (!up->rpf.source_nexthop.interface)  {
+               if (PIM_DEBUG_PIM_EVENTS)
+                       zlog_debug("%s: RP not reachable for %s",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        if (PIM_DEBUG_PIM_EVENTS) {
                zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s",
                           __PRETTY_FUNCTION__, up->sg_str,
@@ -558,11 +609,14 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                    && !I_am_RP(pim, up->sg.grp)) {
                        if (PIM_DEBUG_PIM_TRACE_DETAIL)
                                zlog_debug(
-                                       "%s: *,G IIF %s S,G IIF %s ",
-                                       __PRETTY_FUNCTION__,
-                                       up->parent->rpf.source_nexthop
-                                               .interface->name,
-                                       up->rpf.source_nexthop.interface->name);
+                                 "%s: *,G IIF %s S,G IIF %s ",
+                                 __PRETTY_FUNCTION__,
+                                 up->parent->rpf.source_nexthop.interface ?
+                                 up->parent->rpf.source_nexthop.interface->name
+                                 : "Unknown",
+                                 up->rpf.source_nexthop.interface ?
+                                 up->rpf.source_nexthop.interface->name :
+                                 "Unknown");
                        pim_jp_agg_single_upstream_send(&up->parent->rpf,
                                                        up->parent,
                                                        1 /* (W,G) Join */);
@@ -611,15 +665,14 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
                ch->upstream = up;
 
        up = hash_get(pim->upstream_hash, up, hash_alloc_intern);
+       /* Set up->upstream_addr as INADDR_ANY, if RP is not
+        * configured and retain the upstream data structure
+        */
        if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src,
                                      sg->grp)) {
                if (PIM_DEBUG_TRACE)
                        zlog_debug("%s: Received a (*,G) with no RP configured",
                                   __PRETTY_FUNCTION__);
-
-               hash_release(pim->upstream_hash, up);
-               XFREE(MTYPE_PIM_UPSTREAM, up);
-               return NULL;
        }
 
        up->parent = pim_upstream_find_parent(pim, up);
@@ -659,45 +712,34 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
        if (up->sg.src.s_addr != INADDR_ANY)
                wheel_add_item(pim->upstream_sg_wheel, up);
 
-       rpf_result = pim_rpf_update(pim, up, NULL, 1);
-       if (rpf_result == PIM_RPF_FAILURE) {
-               struct prefix nht_p;
-
-               if (PIM_DEBUG_TRACE)
-                       zlog_debug(
-                               "%s: Attempting to create upstream(%s), Unable to RPF for source",
-                               __PRETTY_FUNCTION__, up->sg_str);
-
-               nht_p.family = AF_INET;
-               nht_p.prefixlen = IPV4_MAX_BITLEN;
-               nht_p.u.prefix4 = up->upstream_addr;
-               pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
+       if (up->upstream_addr.s_addr == INADDR_ANY)
+               /* Create a dummmy channel oil with incoming ineterface MAXVIFS,
+                * since RP is not configured
+                */
+               up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS);
 
-               if (up->parent) {
-                       listnode_delete(up->parent->sources, up);
-                       up->parent = NULL;
+       else {
+               rpf_result = pim_rpf_update(pim, up, NULL, 1);
+               if (rpf_result == PIM_RPF_FAILURE) {
+                       if (PIM_DEBUG_TRACE)
+                               zlog_debug(
+                                       "%s: Attempting to create upstream(%s), Unable to RPF for source",
+                                       __PRETTY_FUNCTION__, up->sg_str);
+                       /* Create a dummmy channel oil with incoming ineterface
+                        * MAXVIFS, since RP is not reachable
+                        */
+                       up->channel_oil = pim_channel_oil_add(
+                               pim, &up->sg, MAXVIFS);
                }
 
-               if (up->sg.src.s_addr != INADDR_ANY)
-                       wheel_remove_item(pim->upstream_sg_wheel, up);
-
-               pim_upstream_remove_children(pim, up);
-               if (up->sources)
-                       list_delete(&up->sources);
-
-               list_delete(&up->ifchannels);
-
-               hash_release(pim->upstream_hash, up);
-               XFREE(MTYPE_PIM_UPSTREAM, up);
-               return NULL;
+               if (up->rpf.source_nexthop.interface) {
+                       pim_ifp = up->rpf.source_nexthop.interface->info;
+                       if (pim_ifp)
+                               up->channel_oil = pim_channel_oil_add(pim,
+                                       &up->sg, pim_ifp->mroute_vif_index);
+               }
        }
 
-       if (up->rpf.source_nexthop.interface) {
-               pim_ifp = up->rpf.source_nexthop.interface->info;
-               if (pim_ifp)
-                       up->channel_oil = pim_channel_oil_add(
-                               pim, &up->sg, pim_ifp->mroute_vif_index);
-       }
        listnode_add_sort(pim->upstream_list, up);
 
        if (PIM_DEBUG_TRACE) {
@@ -783,7 +825,7 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
                        zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d",
                   __PRETTY_FUNCTION__, name,
                   up->sg_str, buf, up->rpf.source_nexthop.interface ?
-                   up->rpf.source_nexthop.interface->name : "NIL" ,
+                   up->rpf.source_nexthop.interface->name : "Unknown" ,
                   found, up->ref_count);
                } else
                        zlog_debug("%s(%s): (%s) failure to create",
@@ -896,7 +938,7 @@ void pim_upstream_update_join_desired(struct pim_instance *pim,
                PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags);
 
        /* switched from false to true */
-       if (is_join_desired && !was_join_desired) {
+       if (is_join_desired && (up->join_state == PIM_UPSTREAM_NOTJOINED)) {
                pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
                return;
        }
@@ -973,7 +1015,9 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
                                (old_rpf_ifp == ch->interface) &&
                                /* RPF_interface(S) stopped being I */
                                (ch->upstream->rpf.source_nexthop
-                                        .interface != ch->interface)) {
+                                       .interface) &&
+                               (ch->upstream->rpf.source_nexthop
+                                       .interface != ch->interface)) {
                                assert_action_a5(ch);
                        }
                } /* PIM_IFASSERT_I_AM_LOSER */
@@ -1339,6 +1383,13 @@ static int pim_upstream_register_stop_timer(struct thread *t)
        case PIM_REG_JOIN:
                break;
        case PIM_REG_PRUNE:
+               if (!up->rpf.source_nexthop.interface) {
+                       if (PIM_DEBUG_TRACE)
+                               zlog_debug("%s: up %s RPF is not present",
+                                       __PRETTY_FUNCTION__, up->sg_str);
+                       return 0;
+               }
+
                pim_ifp = up->rpf.source_nexthop.interface->info;
                if (!pim_ifp) {
                        if (PIM_DEBUG_TRACE)
@@ -1515,11 +1566,19 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
         * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
         */
        for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
+               if (up->upstream_addr.s_addr == INADDR_ANY) {
+                       if (PIM_DEBUG_TRACE)
+                               zlog_debug(
+                                   "%s: RP not configured for Upstream %s",
+                                   __PRETTY_FUNCTION__, up->sg_str);
+                       continue;
+               }
+
                if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
                        if (PIM_DEBUG_TRACE)
                                zlog_debug(
-                                       "Upstream %s without a path to send join, checking",
-                                       up->sg_str);
+                                       "%s: Upstream %s without a path to send join, checking",
+                                       __PRETTY_FUNCTION__, up->sg_str);
                        pim_rpf_update(pim, up, NULL, 1);
                }
        }
@@ -1586,7 +1645,8 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
 
        /* "iif == RPF_interface(S)" check has to be done by the kernel or hw
         * so we will skip that here */
-       if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
+       if (up->rpf.source_nexthop.interface &&
+               pim_if_connected_to_source(up->rpf.source_nexthop.interface,
                                       up->sg.src)) {
                return true;
        }
@@ -1622,7 +1682,7 @@ static void pim_upstream_sg_running(void *arg)
        // No packet can have arrived here if this is the case
        if (!up->channel_oil->installed) {
                if (PIM_DEBUG_TRACE)
-                       zlog_debug("%s: %s[%s] is not installed in mroute",
+                       zlog_debug("%s: %s%s is not installed in mroute",
                                   __PRETTY_FUNCTION__, up->sg_str,
                                   pim->vrf->name);
                return;
@@ -1679,7 +1739,8 @@ static void pim_upstream_sg_running(void *arg)
        } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
                pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
 
-       if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
+       if ((up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) &&
+           (up->rpf.source_nexthop.interface)) {
                pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
        }
        return;
index f44b95c81105095774f6c080330e846ca6dc70a7..70e70140d19b0c2838c7af9465b275efafee1784 100644 (file)
@@ -88,10 +88,30 @@ enum pim_upstream_sptbit {
 
 /*
   Upstream (S,G) channel in Joined state
-
   (S,G) in the "Not Joined" state is not represented
-
   See RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Message
+
+  upstream_addr : Who we are talking to.
+  For (*, G), upstream_addr is RP address or INADDR_ANY(if RP not configured)
+  For (S, G), upstream_addr is source address
+
+  rpf: contains the nexthop information to whom we are talking to.
+
+  join_state: JOINED/NOTJOINED
+
+  In the case when FRR receives IGMP/PIM (*, G) join for group G and RP is not
+  configured, then create a pim_upstream with the below information.
+  pim_upstream->upstream address: INADDR_ANY
+  pim_upstream->rpf: Unknown
+  pim_upstream->state: NOTJOINED
+
+  When a new RP gets configured for G, find the corresponding pim upstream (*,G)
+  entries and update the upstream address as new RP address if it the better one
+  for the group G.
+
+  When RP becomes reachable, populate the nexthop information in
+  pim_upstream->rpf and update the state to JOINED.
+
 */
 struct pim_upstream {
        struct pim_upstream *parent;
index 11ca6e8a108010bba7a44ff19fca425c5b6af770..70f099b0d78d2c73b24bf53efd9b04ceb736d079 100644 (file)
@@ -150,6 +150,8 @@ static int pim_zebra_if_del(int command, struct zclient *zclient,
        if (!if_is_operative(ifp))
                pim_if_addr_del_all(ifp);
 
+       if_set_index(ifp, IFINDEX_INTERNAL);
+
        return 0;
 }
 
@@ -472,99 +474,84 @@ void pim_zebra_upstream_rpf_changed(struct pim_instance *pim,
                                    struct pim_upstream *up,
                                    struct pim_rpf *old)
 {
-       struct pim_neighbor *nbr;
+       if (old->source_nexthop.interface) {
+               struct pim_neighbor *nbr;
 
-       nbr = pim_neighbor_find(old->source_nexthop.interface,
-                               old->rpf_addr.u.prefix4);
-       if (nbr)
-               pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
+               nbr = pim_neighbor_find(old->source_nexthop.interface,
+                                       old->rpf_addr.u.prefix4);
+               if (nbr)
+                       pim_jp_agg_remove_group(nbr->upstream_jp_agg, up);
 
-       /*
-        * We have detected a case where we might need
-        * to rescan the inherited o_list so do it.
-        */
-       if (up->channel_oil->oil_inherited_rescan) {
-               pim_upstream_inherited_olist_decide(pim, up);
-               up->channel_oil->oil_inherited_rescan = 0;
-       }
-
-       if (up->join_state == PIM_UPSTREAM_JOINED) {
                /*
-                * If we come up real fast we can be here
-                * where the mroute has not been installed
-                * so install it.
+                * We have detected a case where we might need
+                * to rescan the inherited o_list so do it.
                 */
-               if (!up->channel_oil->installed)
-                       pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
+               if (up->channel_oil->oil_inherited_rescan) {
+                       pim_upstream_inherited_olist_decide(pim, up);
+                       up->channel_oil->oil_inherited_rescan = 0;
+               }
+
+               if (up->join_state == PIM_UPSTREAM_JOINED) {
+                       /*
+                        * If we come up real fast we can be here
+                        * where the mroute has not been installed
+                        * so install it.
+                        */
+                       if (!up->channel_oil->installed)
+                               pim_mroute_add(up->channel_oil,
+                                       __PRETTY_FUNCTION__);
+
+                       /*
+                        * RFC 4601: 4.5.7.  Sending (S,G)
+                        * Join/Prune Messages
+                        *
+                        * Transitions from Joined State
+                        *
+                        * RPF'(S,G) changes not due to an Assert
+                        *
+                        * The upstream (S,G) state machine remains
+                        * in Joined state. Send Join(S,G) to the new
+                        * upstream neighbor, which is the new value
+                        * of RPF'(S,G).  Send Prune(S,G) to the old
+                        * upstream neighbor, which is the old value
+                        * of RPF'(S,G).  Set the Join Timer (JT) to
+                        * expire after t_periodic seconds.
+                        */
+                       pim_jp_agg_switch_interface(old, &up->rpf, up);
+
+                       pim_upstream_join_timer_restart(up, old);
+               } /* up->join_state == PIM_UPSTREAM_JOINED */
+       }
 
+       else {
                /*
-                * RFC 4601: 4.5.7.  Sending (S,G)
-                * Join/Prune Messages
-                *
-                * Transitions from Joined State
-                *
-                * RPF'(S,G) changes not due to an Assert
-                *
-                * The upstream (S,G) state machine remains
-                * in Joined state. Send Join(S,G) to the new
-                * upstream neighbor, which is the new value
-                * of RPF'(S,G).  Send Prune(S,G) to the old
-                * upstream neighbor, which is the old value
-                * of RPF'(S,G).  Set the Join Timer (JT) to
-                * expire after t_periodic seconds.
+                * We have detected a case where we might need
+                * to rescan the inherited o_list so do it.
                 */
-               pim_jp_agg_switch_interface(old, &up->rpf, up);
+               if (up->channel_oil->oil_inherited_rescan) {
+                       pim_upstream_inherited_olist_decide(pim, up);
+                       up->channel_oil->oil_inherited_rescan = 0;
+               }
 
-               pim_upstream_join_timer_restart(up, old);
-       } /* up->join_state == PIM_UPSTREAM_JOINED */
+               if (!up->channel_oil->installed)
+                       pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
+       }
 
-       /* FIXME can join_desired actually be changed by
-          pim_rpf_update()
-          returning PIM_RPF_CHANGED ? */
+       /* FIXME can join_desired actually be changed by pim_rpf_update()
+        * returning PIM_RPF_CHANGED ?
+        */
        pim_upstream_update_join_desired(pim, up);
 }
 
-static void scan_upstream_rpf_cache(struct pim_instance *pim)
-{
-       struct listnode *up_node;
-       struct listnode *up_nextnode;
-       struct pim_upstream *up;
-
-       for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
-               enum pim_rpf_result rpf_result;
-               struct pim_rpf old;
-               struct prefix nht_p;
-
-               nht_p.family = AF_INET;
-               nht_p.prefixlen = IPV4_MAX_BITLEN;
-               nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
-               pim_resolve_upstream_nh(pim, &nht_p);
-
-               old.source_nexthop.interface = up->rpf.source_nexthop.interface;
-               old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
-               rpf_result = pim_rpf_update(pim, up, &old, 0);
-
-               if (rpf_result == PIM_RPF_FAILURE)
-                       continue;
-
-               if (rpf_result == PIM_RPF_CHANGED)
-                       pim_zebra_upstream_rpf_changed(pim, up, &old);
-
-       } /* for (qpim_upstream_list) */
-
-       pim_zebra_update_all_interfaces(pim);
-}
-
 void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
 {
        struct in_addr vif_source;
        int input_iface_vif_index;
        int old_vif_index;
 
-       if (!pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
+       pim_rp_set_upstream_addr(c_oil->pim, &vif_source,
                                      c_oil->oil.mfcc_origin,
-                                     c_oil->oil.mfcc_mcastgrp))
-               return;
+                                     c_oil->oil.mfcc_mcastgrp);
 
        if (in_vif_index)
                input_iface_vif_index = in_vif_index;
@@ -719,9 +706,6 @@ static int on_rpf_cache_refresh(struct thread *t)
 {
        struct pim_instance *pim = THREAD_ARG(t);
 
-       /* update PIM protocol state */
-       scan_upstream_rpf_cache(pim);
-
        /* update kernel multicast forwarding cache (MFC) */
        pim_scan_oil(pim);
 
@@ -950,112 +934,141 @@ void igmp_source_forward_start(struct pim_instance *pim,
                struct pim_upstream *up = NULL;
 
                if (!pim_rp_set_upstream_addr(pim, &vif_source,
-                                             source->source_addr, sg.grp))
-                       return;
-
-               /* Register addr with Zebra NHT */
-               nht_p.family = AF_INET;
-               nht_p.prefixlen = IPV4_MAX_BITLEN;
-               nht_p.u.prefix4 = vif_source;
-               memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
+                                             source->source_addr, sg.grp)) {
+                       /*Create a dummy channel oil */
+                       source->source_channel_oil =
+                           pim_channel_oil_add(pim, &sg, MAXVIFS);
 
-               src.family = AF_INET;
-               src.prefixlen = IPV4_MAX_BITLEN;
-               src.u.prefix4 = vif_source; // RP or Src address
-               grp.family = AF_INET;
-               grp.prefixlen = IPV4_MAX_BITLEN;
-               grp.u.prefix4 = sg.grp;
+                       if (!source->source_channel_oil) {
+                               if (PIM_DEBUG_IGMP_TRACE) {
+                                       zlog_debug(
+                                       "%s %s: could not create OIL for channel (S,G)=%s",
+                                       __FILE__, __PRETTY_FUNCTION__,
+                                       pim_str_sg_dump(&sg));
+                               }
+                               return;
+                       }
+               }
 
-               if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
+               else {
+                       /* Register addr with Zebra NHT */
+                       nht_p.family = AF_INET;
+                       nht_p.prefixlen = IPV4_MAX_BITLEN;
+                       nht_p.u.prefix4 = vif_source;
+                       memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache));
+
+                       src.family = AF_INET;
+                       src.prefixlen = IPV4_MAX_BITLEN;
+                       src.u.prefix4 = vif_source; // RP or Src address
+                       grp.family = AF_INET;
+                       grp.prefixlen = IPV4_MAX_BITLEN;
+                       grp.u.prefix4 = sg.grp;
+
+                       if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
                                              &out_pnc)) {
-                       if (out_pnc.nexthop_num) {
-                               up = pim_upstream_find(pim, &sg);
-                               memset(&nexthop, 0, sizeof(nexthop));
-                               if (up)
-                                       memcpy(&nexthop,
-                                              &up->rpf.source_nexthop,
-                                              sizeof(struct pim_nexthop));
-                               pim_ecmp_nexthop_search(pim, &out_pnc, &nexthop,
-                                                       &src, &grp, 0);
-                               if (nexthop.interface)
-                                       input_iface_vif_index =
+                               if (out_pnc.nexthop_num) {
+                                       up = pim_upstream_find(pim, &sg);
+                                       memset(&nexthop, 0, sizeof(nexthop));
+                                       if (up)
+                                               memcpy(&nexthop,
+                                                   &up->rpf.source_nexthop,
+                                                   sizeof(struct pim_nexthop));
+                                       pim_ecmp_nexthop_search(pim, &out_pnc,
+                                                               &nexthop,
+                                                               &src, &grp, 0);
+                                       if (nexthop.interface)
+                                               input_iface_vif_index =
                                                pim_if_find_vifindex_by_ifindex(
-                                                       pim,
-                                                       nexthop.interface->ifindex);
-                       } else {
-                               if (PIM_DEBUG_ZEBRA) {
-                                       char buf1[INET_ADDRSTRLEN];
-                                       char buf2[INET_ADDRSTRLEN];
-                                       pim_inet4_dump("<source?>",
+                                                   pim,
+                                                   nexthop.interface->ifindex);
+                               } else {
+                                       if (PIM_DEBUG_ZEBRA) {
+                                               char buf1[INET_ADDRSTRLEN];
+                                               char buf2[INET_ADDRSTRLEN];
+
+                                               pim_inet4_dump("<source?>",
                                                       nht_p.u.prefix4, buf1,
                                                       sizeof(buf1));
-                                       pim_inet4_dump("<source?>",
+                                               pim_inet4_dump("<source?>",
                                                       grp.u.prefix4, buf2,
                                                       sizeof(buf2));
-                                       zlog_debug(
+                                               zlog_debug(
                                                "%s: NHT Nexthop not found for addr %s grp %s",
                                                __PRETTY_FUNCTION__, buf1,
                                                buf2);
+                                       }
                                }
-                       }
-               } else
-                       input_iface_vif_index =
-                               pim_ecmp_fib_lookup_if_vif_index(pim, &src,
+                       } else
+                               input_iface_vif_index =
+                                   pim_ecmp_fib_lookup_if_vif_index(pim, &src,
                                                                 &grp);
 
-               if (PIM_DEBUG_ZEBRA) {
-                       char buf2[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<source?>", vif_source, buf2,
-                                      sizeof(buf2));
-                       zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
-                                  __PRETTY_FUNCTION__, pim_str_sg_dump(&sg),
-                                  buf2, input_iface_vif_index);
-               }
-
-               if (input_iface_vif_index < 1) {
-                       if (PIM_DEBUG_IGMP_TRACE) {
-                               char source_str[INET_ADDRSTRLEN];
-                               pim_inet4_dump("<source?>", source->source_addr,
-                                              source_str, sizeof(source_str));
-                               zlog_debug(
-                                       "%s %s: could not find input interface for source %s",
-                                       __FILE__, __PRETTY_FUNCTION__,
-                                       source_str);
-                       }
-                       return;
-               }
+                       if (PIM_DEBUG_ZEBRA) {
+                               char buf2[INET_ADDRSTRLEN];
 
-               /*
-                 Protect IGMP against adding looped MFC entries created by both
-                 source and receiver attached to the same interface. See TODO
-                 T22.
-               */
-               if (input_iface_vif_index == pim_oif->mroute_vif_index) {
-                       /* ignore request for looped MFC entry */
-                       if (PIM_DEBUG_IGMP_TRACE) {
-                               zlog_debug(
-                                       "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
+                               pim_inet4_dump("<source?>", vif_source, buf2,
+                                              sizeof(buf2));
+                               zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
                                        __PRETTY_FUNCTION__,
                                        pim_str_sg_dump(&sg),
-                                       source->source_group->group_igmp_sock
-                                               ->fd,
-                                       source->source_group->group_igmp_sock
-                                               ->interface->name,
-                                       input_iface_vif_index);
+                                       buf2, input_iface_vif_index);
                        }
-                       return;
-               }
 
-               source->source_channel_oil =
-                       pim_channel_oil_add(pim, &sg, input_iface_vif_index);
-               if (!source->source_channel_oil) {
-                       if (PIM_DEBUG_IGMP_TRACE) {
-                               zlog_debug(
-                                       "%s %s: could not create OIL for channel (S,G)=%s",
-                                       __FILE__, __PRETTY_FUNCTION__,
-                                       pim_str_sg_dump(&sg));
+                       if (input_iface_vif_index < 1) {
+                               if (PIM_DEBUG_IGMP_TRACE) {
+                                       char source_str[INET_ADDRSTRLEN];
+                                       pim_inet4_dump("<source?>",
+                                               source->source_addr,
+                                               source_str, sizeof(source_str));
+                                       zlog_debug(
+                                           "%s %s: could not find input interface for source %s",
+                                           __FILE__, __PRETTY_FUNCTION__,
+                                           source_str);
+                               }
+                               source->source_channel_oil =
+                                   pim_channel_oil_add(pim, &sg, MAXVIFS);
+                       }
+
+                       else {
+                               /*
+                                * Protect IGMP against adding looped MFC
+                                * entries created by both source and receiver
+                                * attached to the same interface. See TODO
+                                * T22.
+                                */
+                               if (input_iface_vif_index ==
+                                   pim_oif->mroute_vif_index) {
+                                       /* ignore request for looped MFC entry
+                                        */
+                                       if (PIM_DEBUG_IGMP_TRACE) {
+                                               zlog_debug(
+                                                   "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
+                                                   __PRETTY_FUNCTION__,
+                                                   pim_str_sg_dump(&sg),
+                                                   source->source_group
+                                                   ->group_igmp_sock->fd,
+                                                   source->source_group
+                                                   ->group_igmp_sock
+                                                   ->interface->name,
+                                                   input_iface_vif_index);
+                                       }
+                                       return;
+                               }
+
+                               source->source_channel_oil =
+                                   pim_channel_oil_add(pim, &sg,
+                                       input_iface_vif_index);
+                               if (!source->source_channel_oil) {
+                                       if (PIM_DEBUG_IGMP_TRACE) {
+                                               zlog_debug(
+                                                   "%s %s: could not create OIL for channel (S,G)=%s",
+                                                   __FILE__,
+                                                   __PRETTY_FUNCTION__,
+                                                   pim_str_sg_dump(&sg));
+                                       }
+                                       return;
+                               }
                        }
-                       return;
                }
        }
 
@@ -1188,15 +1201,13 @@ void pim_forward_start(struct pim_ifchannel *ch)
                               sizeof(upstream_str));
                zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__,
                           source_str, group_str, ch->interface->name,
-                          upstream_str);
+                          inet_ntoa(up->upstream_addr));
        }
 
        /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
           as part of mroute_del called by pim_forward_stop.
        */
-       if (!up->channel_oil
-           || (up->channel_oil
-               && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) {
+       if ((up->upstream_addr.s_addr != INADDR_ANY) && (!up->channel_oil)) {
                struct prefix nht_p, src, grp;
                struct pim_nexthop_cache out_pnc;
 
@@ -1267,17 +1278,33 @@ void pim_forward_start(struct pim_ifchannel *ch)
                                        __FILE__, __PRETTY_FUNCTION__,
                                        source_str);
                        }
-                       return;
+                       up->channel_oil = pim_channel_oil_add(pim, &up->sg,
+                                                               MAXVIFS);
                }
+
+               else {
+                       up->channel_oil = pim_channel_oil_add(pim, &up->sg,
+                                                       input_iface_vif_index);
+                       if (!up->channel_oil) {
+                               if (PIM_DEBUG_PIM_TRACE)
+                                       zlog_debug(
+                                           "%s %s: could not create OIL for channel (S,G)=%s",
+                                           __FILE__, __PRETTY_FUNCTION__,
+                                           up->sg_str);
+                               return;
+                       }
+               }
+
                if (PIM_DEBUG_TRACE) {
                        struct interface *in_intf = pim_if_find_by_vif_index(
                                pim, input_iface_vif_index);
                        zlog_debug(
                                "%s: Update channel_oil IIF %s VIFI %d entry %s ",
                                __PRETTY_FUNCTION__,
-                               in_intf ? in_intf->name : "NIL",
+                               in_intf ? in_intf->name : "Unknown",
                                input_iface_vif_index, up->sg_str);
                }
+
                up->channel_oil = pim_channel_oil_add(pim, &up->sg,
                                                      input_iface_vif_index);
                if (!up->channel_oil) {
index 0ffe313c17adccf826ad2d96a4fcbce2093bdbfb..6d93a40b913d95c0cdd63b60f189ef0e4890f504 100644 (file)
@@ -499,7 +499,7 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
                more.src = c_oil->oil.mfcc_origin;
                more.grp = c_oil->oil.mfcc_mcastgrp;
                zlog_debug(
-                       "Sending Request for New Channel Oil Information(%s) VIIF %d(%s)",
+                       "Sending Request for New Channel Oil Information%s VIIF %d(%s)",
                        pim_str_sg_dump(&more), c_oil->oil.mfcc_parent,
                        c_oil->pim->vrf->name);
        }
index 656b000579f380d73d633b27e9c7f79e2b2e49aa..889a83a136bdaec25bc9bf9214c2e3f34b368f18 100644 (file)
@@ -127,8 +127,6 @@ void pim_terminate(void)
 {
        struct zclient *zclient;
 
-       pim_free();
-
        /* reverse prefix_list_init */
        prefix_list_add_hook(NULL);
        prefix_list_delete_hook(NULL);
@@ -142,6 +140,8 @@ void pim_terminate(void)
                zclient_free(zclient);
        }
 
+       pim_free();
        pim_router_terminate();
+
        frr_fini();
 }
diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md
deleted file mode 100644 (file)
index a3f0957..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-Building your own FRRouting RPM
-======================================
-(Tested on CentOS 6, CentOS 7 and Fedora 24.)
-
-1. On CentOS 6 (which doesn't provide a bison/automake/autoconf of a recent enough version):
-    - Check out ../doc/developer/building-frr-for-centos6.rst for details on installing
-    a bison/automake/autoconf to support frr building.
-
-    Newer automake/autoconf/bison is only needed to build the rpm and is
-    **not** needed to install the binary rpm package
-
-2. Install the build packages as documented in doc/developer/building-frr-for-xxxxx.rst and the following additional packages:
-
-        yum install rpm-build net-snmp-devel pam-devel libcap-devel
-
-    Additionally, on systems with systemd (CentOS 7, Fedora)
-
-        yum install systemd-devel
-
-    (use `dnf install` on new Fedora instead of `yum install`)
-
-3. Checkout FRR under a **unpriviledged** user account
-
-        git clone https://github.com/frrouting/frr.git frr
-
-4. Run Bootstrap and make distribution tar.gz
-
-        cd frr
-        ./bootstrap.sh
-        ./configure --with-pkg-extra-version=-MyRPMVersion \
-            SPHINXBUILD=sphinx-build2.7
-        make dist
-            
-    Note: configure parameters are not important for the RPM building - except the `with-pkg-extra-version` if you want to give the RPM a specific name to
-    mark your own unoffical build
-
-5. Create RPM directory structure and populate with sources
-
-        mkdir rpmbuild
-        mkdir rpmbuild/SOURCES
-        mkdir rpmbuild/SPECS
-        cp redhat/*.spec rpmbuild/SPECS/
-        cp frr*.tar.gz rpmbuild/SOURCES/
-
-6. Edit rpm/SPECS/frr.spec with configuration as needed
-    Look at the beginning of the file and adjust the following parameters to enable or disable features as required:
-    
-        ############### FRRouting (FRR) configure options #################
-        # with-feature options
-        %{!?with_pam:           %global  with_pam           0 }
-        %{!?with_ospfclient:    %global  with_ospfclient    1 }
-        %{!?with_ospfapi:       %global  with_ospfapi       1 }
-        %{!?with_irdp:          %global  with_irdp          1 }
-        %{!?with_rtadv:         %global  with_rtadv         1 }
-        %{!?with_ldpd:          %global  with_ldpd          1 }
-        %{!?with_nhrpd:         %global  with_nhrpd         1 }
-        %{!?with_eigrp:         %global  with_eigrpd        1 }
-        %{!?with_shared:        %global  with_shared        1 }
-        %{!?with_multipath:     %global  with_multipath     256 }
-        %{!?frr_user:           %global  frr_user           frr }
-        %{!?vty_group:          %global  vty_group          frrvty }
-        %{!?with_fpm:           %global  with_fpm           0 }
-        %{!?with_watchfrr:      %global  with_watchfrr      1 }
-        %{!?with_bgp_vnc:       %global  with_bgp_vnc       0 }
-        %{!?with_pimd:          %global  with_pimd          1 }
-        %{!?with_rpki:          %global  with_rpki          0 }
-
-7. Build the RPM
-
-        rpmbuild --define "_topdir `pwd`/rpmbuild" -ba rpmbuild/SPECS/frr.spec
-
-   If building with RPKI, then download and install the additional RPKI
-   packages from
-        https://ci1.netdef.org/browse/RPKI-RTRLIB/latestSuccessful/artifact
-
-DONE.
-
-If all works correctly, then you should end up with the RPMs under 
-`rpmbuild/RPMS` and the Source RPM under `rpmbuild/SRPMS`
-
-
-Enabling daemons after installation of the package:
----------------------------------------------------
-
-### init.d based systems (ie CentOS 6):
-
-1. Edit /etc/frr/daemons and enable required routing daemons (Zebra is probably needed for most deployments, so make sure to enable it.)
-
-2. Enable the daemons as needed to run after boot (Zebra is mandatory)
-    
-        chkconfig frr on
-
-3. Check your firewall / IPtables to make sure the routing protocols are
-allowed.
-        
-5. Start the FRR daemons (or reboot)
-
-        service frr start
-            
-Configuration is stored in `/etc/frr/*.conf` files and daemon selection is stored in `/etc/frr/daemons`.
-
-
-### systemd based systems (ie CentOS 7, Fedora 24)
-
-1. Edit /etc/frr/daemons and enable required routing daemons (Zebra is probably needed for most deployments, so make sure to enable it.)
-2. Enable the frr daemons to run after boot.
-    
-        systemctl enable frr
-
-2. Check your firewall / IPtables to make sure the routing protocols are
-allowed.
-        
-3. Start the daemons (or reboot)
-
-        systemctl start frr
-            
-Configuration is stored in `/etc/frr/*.conf` files and daemon selection is stored in `/etc/frr/daemons`.
-
diff --git a/redhat/daemons b/redhat/daemons
deleted file mode 100644 (file)
index 7f3ff36..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-# This file tells the frr package which daemons to start.
-#
-# Entries are in the format: <daemon>=(yes|no|priority)
-#   0, "no"  = disabled
-#   1, "yes" = highest priority
-#   2 .. 10  = lower priorities
-#
-# For daemons which support multiple instances, a 2nd line listing
-# the instances can be added. Eg for ospfd:
-#   ospfd=yes
-#   ospfd_instances="1,2"
-#
-# Priorities were suggested by Dancer <dancer@zeor.simegen.com>.
-# They're used to start the FRR daemons in more than one step
-# (for example start one or two at network initialization and the
-# rest later). The number of FRR daemons being small, priorities
-# must be between 1 and 9, inclusive (or the initscript has to be
-# changed). /etc/init.d/frr then can be started as
-#
-#   /etc/init.d/frr <start|stop|restart|<priority>>
-#
-# where priority 0 is the same as 'stop', priority 10 or 'start'
-# means 'start all'
-#
-# Sample configurations for these daemons can be found in
-# /usr/share/doc/frr/examples/.
-#
-# ATTENTION:
-#
-# When activation a daemon at the first time, a config file, even if it is
-# empty, has to be present *and* be owned by the user and group "frr", else
-# the daemon will not be started by /etc/init.d/frr. The permissions should
-# be u=rw,g=r,o=.
-# When using "vtysh" such a config file is also needed. It should be owned by
-# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
-#
-watchfrr_enable=yes
-watchfrr_options="-r '/usr/lib/frr/frr restart %s' -s '/usr/lib/frr/frr start %s' -k '/usr/lib/frr/frr stop %s'"
-#
-zebra=no
-bgpd=no
-ospfd=no
-ospf6d=no
-ripd=no
-ripngd=no
-isisd=no
-ldpd=no
-pimd=no
-nhrpd=no
-eigrpd=no
-babeld=no
-sharpd=no
-pbrd=no
-staticd=no
-bfdd=no
-fabricd=no
-
-#
-# Command line options for the daemons
-#
-zebra_options=("-A 127.0.0.1")
-bgpd_options=("-A 127.0.0.1")
-ospfd_options=("-A 127.0.0.1")
-ospf6d_options=("-A ::1")
-ripd_options=("-A 127.0.0.1")
-ripngd_options=("-A ::1")
-isisd_options=("-A 127.0.0.1")
-ldpd_options=("-A 127.0.0.1")
-pimd_options=("-A 127.0.0.1")
-nhrpd_options=("-A 127.0.0.1")
-eigrpd_options=("-A 127.0.0.1")
-babeld_options=("-A 127.0.0.1")
-sharpd_options=("-A 127.0.0.1")
-pbrd_options=("-A 127.0.0.1")
-staticd_options=("-A 127.0.0.1")
-bfdd_options=("-A 127.0.0.1")
-fabricd_options=("-A 127.0.0.1")
-
-#
-# If the vtysh_enable is yes, then the unified config is read
-# and applied if it exists.  If no unified frr.conf exists
-# then the per-daemon <daemon>.conf files are used)
-# If vtysh_enable is no or non-existant, the frr.conf is ignored.
-# it is highly suggested to have this set to yes
-vtysh_enable=yes
-
diff --git a/redhat/frr.init b/redhat/frr.init
deleted file mode 100755 (executable)
index b59656a..0000000
+++ /dev/null
@@ -1,577 +0,0 @@
-#!/bin/bash
-#
-#   /etc/rc.d/init.d/frr
-#
-#   Start/Stop the FRR Routing daemons
-#   <any general comments about this init script>
-#
-# chkconfig: 2345 15 85
-#
-# description: FRRouting (FRR) is a routing suite for IP routing protocols
-#              like BGP, OSPF, RIP and others. This script contols the main
-#              daemon "frr" as well as the individual protocol daemons.
-#
-### BEGIN INIT INFO
-# Provides: frr
-# Required-Start: $local_fs $network $syslog
-# Required-Stop: $local_fs $syslog
-# Should-Start: $syslog
-# Should-Stop: $network $syslog
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Start/Stop the FRR Routing daemons
-# Description: FRRouting (FRR) is a routing suite for IP routing protocols
-#              like BGP, OSPF, RIP and others. This script contols the main
-#              daemon "frr" as well as the individual protocol daemons.
-### END INIT INFO
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-D_PATH=/usr/lib/frr
-C_PATH=/etc/frr
-V_PATH=/var/run/frr
-
-# 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 pimd pbrd ldpd nhrpd eigrpd babeld staticd sharpd bfdd fabricd"
-MAX_INSTANCES=5
-RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
-
-. /etc/init.d/functions
-
-# Print the name of the pidfile.
-pidfile()
-{
-    echo "$V_PATH/$1.pid"
-}
-
-# Print the name of the vtysh.
-vtyfile()
-{
-    echo "$V_PATH/$1.vty"
-}
-
-# Check if daemon is started by using the pidfile.
-started()
-{
-    [ ! -e `pidfile $1` ] && return 3
-    if [ -n "$2" ] && [ "$2" == "log" ]; then
-        status -p `pidfile $1` $1 && return 0 || return $?
-    else
-        kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
-        return 0
-    fi
-}
-
-# Loads the config via vtysh -b if configured to do so.
-vtysh_b ()
-{
-        # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
-        if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then
-                /usr/bin/vtysh -b -n
-        fi
-}
-
-# Check if the daemon is activated and if its executable and config files
-# are in place.
-# params:       daemon name
-# returns:      0=ok, 1=error
-check_daemon()
-{
-    # If the integrated config file is used the others are not checked.
-    if [ -r "$C_PATH/frr.conf" ]; then
-        return 0
-    fi
-
-    # vtysh_enable has no config file nor binary so skip check.
-    # (Not sure why vtysh_enable is in this list but does not hurt)
-    if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
-        # check for daemon binary
-        if [ ! -x "$D_PATH/$1" ]; then return 1; fi
-
-        # check for config file
-        if [ -n "$2" ]; then
-            if [ ! -r "$C_PATH/$1-$2.conf" ]; then
-                touch "$C_PATH/$1-$2.conf"
-                chown frr:frr "$C_PATH/$1-$2.conf"
-            fi
-        elif [ ! -r "$C_PATH/$1.conf" ]; then
-            touch "$C_PATH/$1.conf"
-            chown frr:frr "$C_PATH/$1.conf"
-        fi
-    fi
-    return 0
-}
-
-# Starts the server if it's not already running according to the pid file.
-# The Frr daemons creates the pidfile when starting.
-start()
-{
-    local dmn inst
-    dmn="$1"
-    inst="$2"
-
-    ulimit -n $MAX_FDS > /dev/null 2> /dev/null
-    if [ "$dmn" = "watchfrr" ]; then
-
-        # We may need to restart watchfrr if new daemons are added and/or
-        # removed
-        if started "$dmn" ; then
-            stop watchfrr
-        else
-            # Echo only once. watchfrr is printed in the stop above
-            echo -n " $dmn"
-        fi
-
-        if [ -e /var/run/frr/watchfrr.started ] ; then
-            rm /var/run/frr/watchfrr.started
-        fi
-        # redhat /etc/init.d/functions daemon() re-expands args :(
-        # eval "set - $watchfrr_options"
-        daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d "$watchfrr_options"
-        RETVAL=$?
-        [ $RETVAL -ne 0 ] && break
-        for i in `seq 1 10`;
-        do
-            if [ -e /var/run/frr/watchfrr.started ] ; then
-                RETVAL=0
-                break
-            else
-                sleep 1
-            fi
-        done
-        RETVAL=1
-    elif [ -n "$inst" ]; then
-        echo -n " $dmn-$inst"
-        if ! check_daemon $dmn $inst ; then
-            echo -n " (binary does not exist)"
-            return;
-        fi
-        daemon --pidfile=`pidfile $dmn-$inst` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"` -n "$inst"
-        RETVAL=$?
-    else
-        echo -n " $dmn "
-        if ! check_daemon $dmn; then
-            echo " (binary does not exist)"
-            return;
-        fi
-        daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"`
-        RETVAL=$?
-    fi
-    echo
-    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$dmn
-    return $RETVAL
-}
-
-# Stop the daemon given in the parameter, printing its name to the terminal.
-stop()
-{
-    local inst
-
-    if [ -n "$2" ]; then
-       inst="$1-$2"
-    else
-       inst="$1"
-    fi
-
-    if ! started "$inst" ; then
-        # echo -n " ($inst)"
-        return 0
-    else
-        echo -n " $inst"
-        PIDFILE=`pidfile $inst`
-        PID=`cat $PIDFILE 2>/dev/null`
-        killproc -p "$PIDFILE" "$D_PATH/$1"
-        RETVAL=$?
-        [ $RETVAL -eq 0 ] && rm -f $lockfile
-        rm -f `pidfile $inst`
-        rm -f `vtyfile $inst`
-        echo
-        return $RETVAL
-    fi
-}
-
-# Converts values from /etc/frr/daemons to all-numeric values.
-convert_daemon_prios()
-{
-    for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do
-        # First, assign the value set by the user to $value
-        eval value=\${${name}:0:3}
-
-        # Daemon not activated or entry missing?
-        if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
-
-        # These strings parsed for backwards compatibility.
-        if [ "$value" = "yes"  -o  "$value" = "true" ]; then
-            value=1;
-        fi
-
-        # Zebra is threatened special. It must be between 0=off and the first
-        # user assigned value "1" so we increase all other enabled daemons' values.
-        if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi
-
-        # If e.g. name is zebra then we set "zebra=yes".
-        eval $name=$value
-    done
-}
-
-# Starts watchfrr for all wanted daemons.
-start_watchfrr()
-{
-    local daemon_name
-    local daemon_prio
-    local found_one
-    local daemon_inst
-
-    # Start the monitor daemon only if desired.
-    if [ 0 -eq "$watchfrr_enable" ]; then
-        return
-    fi
-
-    # Check variable type
-    if declare -p watchfrr_options | grep -q '^declare \-a'; then
-        # old array support
-        watchfrr_options="${watchfrr_options[@]}"
-    fi
-
-    # Which daemons have been started?
-    found_one=0
-    for daemon_name in $DAEMONS; do
-        eval daemon_prio=\$$daemon_name
-        if [ "$daemon_prio" -gt 0 ]; then
-            eval "daemon_inst=\${${daemon_name}_instances//,/ }"
-            if [ -n "$daemon_inst" ]; then
-                for inst in ${daemon_inst}; do
-                    eval "inst_disable=\${${daemon_name}_${inst}}"
-                    if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then
-                        if check_daemon $daemon_name $inst; then
-                            watchfrr_options="$watchfrr_options ${daemon_name}-${inst}"
-                        fi
-                    fi
-                done
-            else
-                if check_daemon $daemon_name; then
-                    watchfrr_options="$watchfrr_options $daemon_name"
-                fi
-            fi
-            found_one=1
-        fi
-    done
-
-    # Start if at least one daemon is activated.
-    if [ $found_one -eq 1 ]; then
-        echo "Starting FRRouting monitor daemon:"
-        start watchfrr
-    fi
-}
-
-# Stopps watchfrr.
-stop_watchfrr()
-{
-    echo "Stopping FRRouting monitor daemon:"
-    stop watchfrr
-}
-
-# Stops all daemons that have a lower level of priority than the given.
-# (technically if daemon_prio >= wanted_prio)
-stop_prio()
-{
-    local wanted_prio
-    local daemon_prio
-    local daemon_list
-    local daemon_inst
-    local inst
-
-    if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
-        daemon=${BASH_REMATCH[1]}
-        inst=${BASH_REMATCH[2]}
-    else
-        daemon="$2"
-    fi
-
-    wanted_prio=$1
-    daemon_list=${daemon:-$DAEMONS}
-
-    echo "Stopping FRRouting daemons (prio:$wanted_prio):"
-
-    for prio_i in `seq 10 -1 $wanted_prio`; do
-        for daemon_name in $daemon_list; do
-            eval daemon_prio=\${${daemon_name}:0:3}
-            daemon_inst=""
-            if [ $daemon_prio -eq $prio_i ]; then
-                eval "daemon_inst=\${${daemon_name}_instances//,/ }"
-                if [ -n "$daemon_inst" ]; then
-                    for i in ${daemon_inst}; do
-                        if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
-                            stop "$daemon_name" "$inst"
-                        elif [ x"$inst"  == x ]; then
-                            stop "$daemon_name" "$i"
-                        fi
-                    done
-                else
-                    stop "$daemon_name"
-                fi
-            fi
-        done
-    done
-
-    if [ -z "$inst" ]; then
-    # Now stop other daemons that're prowling, coz the daemons file changed
-        echo "Stopping other FRRouting daemons"
-        if [ -n "$daemon" ]; then
-            eval "file_list_suffix="$V_PATH"/"$daemon*""
-        else
-            eval "file_list_suffix="$V_PATH/*""
-        fi
-        for pidfile in $file_list_suffix.pid; do
-            if [ -f "$pidfile" ]; then
-                filename=${pidfile##*/}
-                daemon=${filename%.*}
-                echo -n " $daemon"
-                killproc -p "$pidfile" "$daemon"
-                RETVAL=$?
-                [ $RETVAL -eq 0 ] && rm -f $lockfile
-                rm -f "$pidfile"
-                echo
-            fi
-        done
-        echo -n "Removing remaining .vty files"
-        for vtyfile in $file_list_suffix.vty; do
-            rm -rf "$vtyfile"
-        done
-        echo
-    fi
-}
-
-# Starts all daemons that have a higher level of priority than the given.
-# (technically if daemon_prio <= wanted_prio)
-start_prio()
-{
-    local wanted_prio
-    local daemon_prio
-    local daemon_list
-    local daemon_name
-    local daemon_inst
-    local inst
-
-    if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
-        daemon=${BASH_REMATCH[1]}
-        inst=${BASH_REMATCH[2]}
-    else
-        daemon="$2"
-    fi
-
-    wanted_prio=$1
-    daemon_list=${daemon:-$DAEMONS}
-
-    echo "Starting FRRouting daemons (prio:$wanted_prio):"
-
-    for prio_i in `seq 1 $wanted_prio`; do
-        for daemon_name in $daemon_list; do
-            eval daemon_prio=\$${daemon_name}
-            daemon_inst=""
-            if [ $daemon_prio -eq $prio_i ]; then
-                eval "daemon_inst=\${${daemon_name}_instances//,/ }"
-                if [ -n "$daemon_inst" ]; then
-                    if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
-                        echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
-                        exit 1
-                    fi
-                    # Check if we're starting again by switching from single instance
-                    # to MI version
-                    if started "$daemon_name"; then
-                        PIDFILE=`pidfile $daemon_name`
-                        killproc -p "$PIDFILE" "$daemon_name"
-                        rm -f `pidfile $1`
-                        rm -f `vtyfile $1`
-                    fi
-
-                    for i in ${daemon_inst}; do
-                        if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
-                            start "$daemon_name" "$inst"
-                        elif [ x"$inst" == x ]; then
-                            start "$daemon_name" "$i"
-                        fi
-                    done
-                else
-                    # Check if we're starting again by switching from
-                    # single instance to MI version
-                    eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
-                    for pidfile in $file_list_suffix.pid; do
-                        if [ -f "$pidfile" ]; then
-                            killproc -p "$pidfile" "$daemon_name"
-                            rm -rf "$pidfile"
-                        fi
-                    done
-                    for vtyfile in $file_list_suffix.vty; do
-                        rm -rf "$vtyfile"
-                    done
-
-                    start "$daemon_name"
-                fi
-            fi
-        done
-    done
-}
-
-check_status()
-{
-    local daemon_name
-    local daemon_prio
-    local daemon_inst
-    local failed_status=0
-
-    if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
-        daemon=${BASH_REMATCH[1]}
-        inst=${BASH_REMATCH[2]}
-    else
-        daemon="$1"
-    fi
-
-    daemon_list=${daemon:-$DAEMONS}
-
-    # Which daemons have been started?
-    for daemon_name in $daemon_list; do
-        eval daemon_prio=\$$daemon_name
-        if [ "$daemon_prio" -gt 0 ]; then
-            eval "daemon_inst=\${${daemon_name}_instances//,/ }"
-            if [ -n "$daemon_inst" ]; then
-                for i in ${daemon_inst}; do
-                    if [ -n "$inst" -a "$inst" = "$i" ]; then
-                        started "$1" "log" || failed_status=$?
-                    elif [ -z "$inst" ]; then
-                        started "$daemon_name-$i" "log" || failed_status=$?
-                    fi
-                done
-            else
-                started "$daemon_name" "log" || failed_status=$?
-            fi
-        fi
-    done
-
-    # All daemons that need to have been started are up and running
-    return $failed_status
-}
-
-#########################################################
-#               Main program                            #
-#########################################################
-
-# Config broken but script must exit silently.
-[ ! -r "$C_PATH/daemons" ] && exit 0
-
-# Load configuration
-. "$C_PATH/daemons"
-
-# Read configuration variable file if it is present
-[ -r /etc/sysconfig/frr ] && . /etc/sysconfig/frr
-
-MAX_INSTANCES=${MAX_INSTANCES:=5}
-
-# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
-convert_daemon_prios
-
-if [ ! -d $V_PATH ]; then
-    echo "Creating $V_PATH"
-    mkdir -p $V_PATH
-    chown frr:frr $V_PATH
-    chmod 755 /$V_PATH
-fi
-
-if [ -n "$3" ] && [ "$3" != "all" ]; then
-    dmn="$2"-"$3"
-elif [ -n "$2" ] && [ "$2" != "all" ]; then
-    dmn="$2"
-fi
-
-case "$1" in
-    start)
-        # Try to load this necessary (at least for 2.6) module.
-        if [ -d /lib/modules/`uname -r` ] ; then
-            echo "Loading capability module if not yet done."
-            LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"
-        fi
-
-        # Start all daemons
-        cd $C_PATH/
-        if [ "$2" != "watchfrr" ]; then
-          start_prio 10 $dmn
-        fi
-        start_watchfrr
-        vtysh_b
-        ;;
-
-    1|2|3|4|5|6|7|8|9|10)
-        # Stop/start daemons for the appropriate priority level
-        stop_prio $1
-        start_prio $1
-        vtysh_b
-        ;;
-
-    stop|0)
-        # Stop all daemons at level '0' or 'stop'
-        stop_watchfrr
-        if [ "$dmn" != "watchfrr" ]; then
-            [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
-            stop_prio 0 $dmn
-        fi
-
-        if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
-            echo "Removing all routes made by zebra."
-            ip route flush proto zebra
-            # At least in CentOS/RHEL 6, iproute2 doesn't know
-            # about the new protocol names, so we have to flush them
-            # by number (it also doesn't support rt_protos.d
-            ip route flush proto 186
-            ip route flush proto 187
-            ip route flush proto 188
-            ip route flush proto 189
-            ip route flush proto 190
-            ip route flush proto 191
-            ip route flush proto 192
-            ip route flush proto 193
-            ip route flush proto 194
-        else
-            [ -n "$dmn" ] && eval "${dmn/-/_}=0"
-            start_watchfrr
-        fi
-        ;;
-
-    reload)
-        # Just apply the commands that have changed, no restart necessary
-        if [ ! -x "$RELOAD_SCRIPT" ]; then
-            echo "frr-reload - reload not supported. Use restart or install frr-pythontools package"
-            exit 1
-        fi
-        NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
-        if [ ! -r $NEW_CONFIG_FILE ]; then
-            echo "Unable to read configuration file $NEW_CONFIG_FILE. Only supporting integrated config"
-            exit 1
-        fi
-        echo "Applying only incremental changes to running configuration from frr.conf"
-        "$RELOAD_SCRIPT" --reload /etc/frr/frr.conf
-        exit $?
-        ;;
-
-    status)
-        check_status $dmn
-        exit $?
-        ;;
-
-    restart|force-reload)
-        $0 stop $dmn
-        sleep 1
-        $0 start $dmn
-        ;;
-
-    *)
-        echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
-        echo "       E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
-        echo "       reload applies only modifications from the running config to all daemons."
-        echo "       reload neither restarts starts any daemon nor starts any new ones."
-        echo "       Read /usr/share/doc/frr/README.Debian for details."
-        exit 1
-        ;;
-esac
-
-exit 0
diff --git a/redhat/frr.service b/redhat/frr.service
deleted file mode 100644 (file)
index 01934a9..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-[Unit]
-Description=FRRouting (FRR)
-Wants=network.target
-After=network-pre.target systemd-sysctl.service
-Before=network.target
-OnFailure=heartbeat-failed@%n.service
-
-[Service]
-Nice=-5
-Type=forking
-NotifyAccess=all
-StartLimitInterval=3m
-StartLimitBurst=3
-TimeoutSec=2m
-WatchdogSec=60s
-RestartSec=5
-Restart=on-abnormal
-LimitNOFILE=1024
-ExecStart=/usr/lib/frr/frr start
-ExecStop=/usr/lib/frr/frr stop
-ExecReload=/usr/lib/frr/frr reload
-
-[Install]
-WantedBy=multi-user.target
index 78b1f7c87c2bfc3979969fb54f184a714d818474..36f92598651c6ff50add9c19190365c91850df9b 100644 (file)
@@ -376,15 +376,13 @@ rm -vf %{buildroot}%{_libdir}/frr/libyang_plugins/*.la
 # install /etc sources
 %if "%{initsystem}" == "systemd"
 mkdir -p %{buildroot}%{_unitdir}
-install -m644 %{zeb_rh_src}/frr.service %{buildroot}%{_unitdir}/frr.service
-install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr
+install -m644 %{zeb_src}/tools/frr.service %{buildroot}%{_unitdir}/frr.service
 %else
 mkdir -p %{buildroot}%{_initddir}
-install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr
-ln -s %{_sbindir}/frr %{buildroot}%{_initddir}/frr
+ln -s %{_sbindir}/frrinit.sh %{buildroot}%{_initddir}/frr
 %endif
 
-install %{zeb_rh_src}/daemons %{buildroot}%{_sysconfdir}/frr
+install %{zeb_src}/tools/etc/frr/daemons %{buildroot}%{_sysconfdir}/frr
 # add rpki module to daemon
 %if %{with_rpki}
     sed -i -e 's/^\(bgpd_options=\)\(.*\)\(".*\)/\1\2 -M rpki\3/' %{buildroot}%{_sysconfdir}/frr/daemons
@@ -474,7 +472,7 @@ zebra_spec_add_service fabricd      2618/tcp "Fabricd vty"
 
 # Fix bad path in previous config files
 #  Config files won't get replaced by default, so we do this ugly hack to fix it
-%__sed -i 's|/etc/init.d/|%{_sbindir}/|g' %{configdir}/daemons 2> /dev/null || true
+%__sed -i 's|watchfrr_options=|#watchfrr_options=|g' %{configdir}/daemons 2> /dev/null || true
 
 # With systemd, watchfrr is mandatory. Fix config to make sure it's enabled if
 # we install or upgrade to a frr built with systemd
@@ -632,7 +630,6 @@ fi
 %else
     %{_initddir}/frr
 %endif
-%{_sbindir}/frr
 %config(noreplace) %{_sysconfdir}/pam.d/frr
 %config(noreplace) %{_sysconfdir}/logrotate.d/frr
 %{_sbindir}/frr-reload
index 6fbcdc059be0f87e900f9b344585d6834c4027f4..62aaad5d97030eb23d8e6c22077515f57aa19ba8 100644 (file)
@@ -378,10 +378,19 @@ DEFPY (rip_passive_interface,
        "Suppress routing updates on an interface\n"
        "Interface name\n")
 {
-       nb_cli_enqueue_change(vty, "./passive-interface",
-                             no ? NB_OP_DESTROY : NB_OP_CREATE, ifname);
-       nb_cli_enqueue_change(vty, "./non-passive-interface",
-                             no ? NB_OP_CREATE : NB_OP_DESTROY, ifname);
+       bool passive_default =
+               yang_dnode_get_bool(vty->candidate_config->dnode, "%s%s",
+                                   VTY_CURR_XPATH, "/passive-default");
+
+       if (passive_default) {
+               nb_cli_enqueue_change(vty, "./non-passive-interface",
+                                     no ? NB_OP_CREATE : NB_OP_DESTROY,
+                                     ifname);
+       } else {
+               nb_cli_enqueue_change(vty, "./passive-interface",
+                                     no ? NB_OP_DESTROY : NB_OP_CREATE,
+                                     ifname);
+       }
 
        return nb_cli_apply_changes(vty, NULL);
 }
index 9575f6b8a8d466c80176177e4f35354909618f84..8bad6b8b1456ee1a464b12daec3ce16bc1af2a56 100644 (file)
@@ -510,11 +510,9 @@ static void rip_interface_reset(struct rip_interface *ri)
        ri->ri_receive = yang_get_default_enum("%s/version-receive", RIP_IFACE);
        ri->v2_broadcast = yang_get_default_bool("%s/v2-broadcast", RIP_IFACE);
 
-       if (ri->auth_str)
-               XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
+       XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
 
-       if (ri->key_chain)
-               XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
+       XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
 
        ri->list[RIP_FILTER_IN] = NULL;
        ri->list[RIP_FILTER_OUT] = NULL;
index 1e5f86eff80950eb22609b675fe25bea2d6a0bf9..f3b5dc2dc3f746b090a5d254b963345295acc7f8 100644 (file)
@@ -937,8 +937,7 @@ lib_interface_rip_authentication_password_modify(enum nb_event event,
 
        ifp = yang_dnode_get_entry(dnode, true);
        ri = ifp->info;
-       if (ri->auth_str)
-               XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
+       XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
        ri->auth_str = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
                               yang_dnode_get_string(dnode, NULL));
 
@@ -978,8 +977,7 @@ lib_interface_rip_authentication_key_chain_modify(enum nb_event event,
 
        ifp = yang_dnode_get_entry(dnode, true);
        ri = ifp->info;
-       if (ri->key_chain)
-               XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
+       XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
        ri->key_chain = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
                                yang_dnode_get_string(dnode, NULL));
 
index e5dc6e6af69ccefb906185ca3804b0d623c13a90..ea32b622a6ac530720b4b31ebb18bc0175f44931 100644 (file)
@@ -90,7 +90,7 @@ static int ripng_multicast_join(struct interface *ifp)
                         * group on
                         * an interface that has just gone down.
                         */
-                       zlog_warn("ripng join on %s EADDRINUSE (ignoring)\n",
+                       zlog_warn("ripng join on %s EADDRINUSE (ignoring)",
                                  ifp->name);
                        return 0; /* not an error */
                }
@@ -124,7 +124,7 @@ static int ripng_multicast_leave(struct interface *ifp)
                ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
                                 (char *)&mreq, sizeof(mreq));
                if (ret < 0)
-                       zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s\n",
+                       zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s",
                                  safe_strerror(errno));
 
                if (IS_RIPNG_DEBUG_EVENT)
index 28a57f25d007bbbcf6814d82e733df6d92b50f98..c68c066f0cbee94da2864475911740ab460a1d3b 100644 (file)
@@ -126,6 +126,9 @@ static int ripng_zebra_read_route(int command, struct zclient *zclient,
        if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
                return 0;
 
+       if (IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
+               return 0;
+
        nexthop = api.nexthops[0].gate.ipv6;
        ifindex = api.nexthops[0].ifindex;
 
index 065fb092d4e8f6dcc2e2c9d5fd7f2d45377ab521..4e5c933667acd367b501f029fe1aae0457b4c100 100644 (file)
@@ -38,6 +38,7 @@ struct sharp_routes {
        int32_t repeat;
 
        uint8_t inst;
+       vrf_id_t vrf_id;
 
        struct timeval t_start;
        struct timeval t_end;
index 9018cfb359986db22f9dadcbb05afcff15f1c249..fbcbbe3fdca7119f940b168a69e12b4c4cc4111f 100644 (file)
 #endif
 
 DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
-      "sharp watch <nexthop$n|import$import> X:X::X:X$nhop [connected$connected]",
+      "sharp watch [vrf NAME$name] <nexthop$n|import$import> X:X::X:X$nhop [connected$connected]",
       "Sharp routing Protocol\n"
       "Watch for changes\n"
+      "The vrf we would like to watch if non-default\n"
+      "The NAME of the vrf\n"
       "Watch for nexthop changes\n"
       "Watch for import check changes\n"
       "The v6 nexthop to signal for watching\n"
       "Should the route be connected\n")
 {
+       struct vrf *vrf;
        struct prefix p;
        bool type_import;
 
+       if (!name)
+               name = VRF_DEFAULT_NAME;
+       vrf = vrf_lookup_by_name(name);
+       if (!vrf) {
+               vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+                       name);
+               return CMD_WARNING;
+       }
 
        if (n)
                type_import = false;
@@ -63,23 +74,36 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
        p.family = AF_INET6;
 
        sharp_nh_tracker_get(&p);
-       sharp_zebra_nexthop_watch(&p, type_import, true, !!connected);
+       sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
+                                 true, !!connected);
 
        return CMD_SUCCESS;
 }
 
 DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
-      "sharp watch <nexthop$n|import$import> A.B.C.D$nhop [connected$connected]",
+      "sharp watch [vrf NAME$name] <nexthop$n|import$import> A.B.C.D$nhop [connected$connected]",
       "Sharp routing Protocol\n"
       "Watch for changes\n"
+      "The vrf we would like to watch if non-default\n"
+      "The NAME of the vrf\n"
       "Watch for nexthop changes\n"
       "Watch for import check changes\n"
       "The v4 nexthop to signal for watching\n"
       "Should the route be connected\n")
 {
+       struct vrf *vrf;
        struct prefix p;
        bool type_import;
 
+       if (!name)
+               name = VRF_DEFAULT_NAME;
+       vrf = vrf_lookup_by_name(name);
+       if (!vrf) {
+               vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+                       name);
+               return CMD_WARNING;
+       }
+
        memset(&p, 0, sizeof(p));
 
        if (n)
@@ -92,7 +116,8 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
        p.family = AF_INET;
 
        sharp_nh_tracker_get(&p);
-       sharp_zebra_nexthop_watch(&p, type_import, true, !!connected);
+       sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
+                                 true, !!connected);
 
        return CMD_SUCCESS;
 }
@@ -132,10 +157,12 @@ DEFPY (install_routes_data_dump,
 
 DEFPY (install_routes,
        install_routes_cmd,
-       "sharp install routes <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
+       "sharp install routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
        "Sharp routing Protocol\n"
        "install some routes\n"
        "Routes to install\n"
+       "The vrf we would like to install into if non-default\n"
+       "The NAME of the vrf\n"
        "v4 Address to start /32 generation at\n"
        "v6 Address to start /32 generation at\n"
        "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
@@ -149,6 +176,7 @@ DEFPY (install_routes,
        "Should we repeat this command\n"
        "How many times to repeat this command\n")
 {
+       struct vrf *vrf;
        struct prefix prefix;
        uint32_t rts;
 
@@ -176,6 +204,16 @@ DEFPY (install_routes,
        }
        sg.r.orig_prefix = prefix;
 
+       if (!name)
+               name = VRF_DEFAULT_NAME;
+
+       vrf = vrf_lookup_by_name(name);
+       if (!vrf) {
+               vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+                       name);
+               return CMD_WARNING;
+       }
+
        if (nexthop_group) {
                struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
                if (!nhgc) {
@@ -195,12 +233,15 @@ DEFPY (install_routes,
                        sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
                }
 
+               sg.r.nhop.vrf_id = vrf->vrf_id;
                sg.r.nhop_group.nexthop = &sg.r.nhop;
        }
 
        sg.r.inst = instance;
+       sg.r.vrf_id = vrf->vrf_id;
        rts = routes;
-       sharp_install_routes_helper(&prefix, sg.r.inst, &sg.r.nhop_group, rts);
+       sharp_install_routes_helper(&prefix, sg.r.vrf_id,
+                                   sg.r.inst, &sg.r.nhop_group, rts);
 
        return CMD_SUCCESS;
 }
@@ -237,16 +278,19 @@ DEFPY(vrf_label, vrf_label_cmd,
 
 DEFPY (remove_routes,
        remove_routes_cmd,
-       "sharp remove routes <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
+       "sharp remove routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
        "Sharp Routing Protocol\n"
        "Remove some routes\n"
        "Routes to remove\n"
+       "The vrf we would like to remove from if non-default\n"
+       "The NAME of the vrf\n"
        "v4 Starting spot\n"
        "v6 Starting spot\n"
        "Routes to uninstall\n"
        "instance to use\n"
        "Value of instance\n")
 {
+       struct vrf *vrf;
        struct prefix prefix;
 
        sg.r.total_routes = routes;
@@ -265,9 +309,18 @@ DEFPY (remove_routes,
                prefix.u.prefix6 = start6;
        }
 
+       vrf = vrf_lookup_by_name(name ? name : VRF_DEFAULT_NAME);
+       if (!vrf) {
+               vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+                       name ? name : VRF_DEFAULT_NAME);
+               return CMD_WARNING;
+       }
+
        sg.r.inst = instance;
+       sg.r.vrf_id = vrf->vrf_id;
        rts = routes;
-       sharp_remove_routes_helper(&prefix, sg.r.inst, rts);
+       sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
+                                  sg.r.inst, rts);
 
        return CMD_SUCCESS;
 }
index 4682dbc73a4fd3e4e73602d880b9ef7765eb92b2..f1e83628c2ee5876eccb17fc1804f6ab281108d7 100644 (file)
@@ -131,8 +131,8 @@ static int interface_state_down(int command, struct zclient *zclient,
        return 0;
 }
 
-void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
-                                struct nexthop_group *nhg,
+void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+                                uint8_t instance, struct nexthop_group *nhg,
                                 uint32_t routes)
 {
        uint32_t temp, i;
@@ -148,7 +148,7 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
 
        monotime(&sg.r.t_start);
        for (i = 0; i < routes; i++) {
-               route_add(p, (uint8_t)instance, nhg);
+               route_add(p, vrf_id, (uint8_t)instance, nhg);
                if (v4)
                        p->u.prefix4.s_addr = htonl(++temp);
                else
@@ -156,8 +156,8 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
        }
 }
 
-void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
-                               uint32_t routes)
+void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+                               uint8_t instance, uint32_t routes)
 {
        uint32_t temp, i;
        bool v4 = false;
@@ -172,7 +172,7 @@ void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
 
        monotime(&sg.r.t_start);
        for (i = 0; i < routes; i++) {
-               route_delete(p, (uint8_t)instance);
+               route_delete(p, vrf_id, (uint8_t)instance);
                if (v4)
                        p->u.prefix4.s_addr = htonl(++temp);
                else
@@ -190,12 +190,14 @@ static void handle_repeated(bool installed)
 
        if (installed) {
                sg.r.removed_routes = 0;
-               sharp_remove_routes_helper(&p, sg.r.inst, sg.r.total_routes);
+               sharp_remove_routes_helper(&p, sg.r.vrf_id,
+                                          sg.r.inst, sg.r.total_routes);
        }
 
        if (installed) {
                sg.r.installed_routes = 0;
-               sharp_install_routes_helper(&p, sg.r.inst, &sg.r.nhop_group,
+               sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
+                                           &sg.r.nhop_group,
                                            sg.r.total_routes);
        }
 }
@@ -255,7 +257,8 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
        zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
 }
 
-void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
+void route_add(struct prefix *p, vrf_id_t vrf_id,
+              uint8_t instance, struct nexthop_group *nhg)
 {
        struct zapi_route api;
        struct zapi_nexthop *api_nh;
@@ -263,7 +266,7 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
        int i = 0;
 
        memset(&api, 0, sizeof(api));
-       api.vrf_id = VRF_DEFAULT;
+       api.vrf_id = vrf_id;
        api.type = ZEBRA_ROUTE_SHARP;
        api.instance = instance;
        api.safi = SAFI_UNICAST;
@@ -274,7 +277,7 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
 
        for (ALL_NEXTHOPS_PTR(nhg, nh)) {
                api_nh = &api.nexthops[i];
-               api_nh->vrf_id = VRF_DEFAULT;
+               api_nh->vrf_id = nh->vrf_id;
                api_nh->type = nh->type;
                switch (nh->type) {
                case NEXTHOP_TYPE_IPV4:
@@ -305,12 +308,12 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
        zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 }
 
-void route_delete(struct prefix *p, uint8_t instance)
+void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance)
 {
        struct zapi_route api;
 
        memset(&api, 0, sizeof(api));
-       api.vrf_id = VRF_DEFAULT;
+       api.vrf_id = vrf_id;
        api.type = ZEBRA_ROUTE_SHARP;
        api.safi = SAFI_UNICAST;
        api.instance = instance;
@@ -320,7 +323,7 @@ void route_delete(struct prefix *p, uint8_t instance)
        return;
 }
 
-void sharp_zebra_nexthop_watch(struct prefix *p, bool import,
+void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
                               bool watch, bool connected)
 {
        int command;
@@ -337,7 +340,7 @@ void sharp_zebra_nexthop_watch(struct prefix *p, bool import,
                        command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
        }
 
-       if (zclient_send_rnh(zclient, command, p, connected, VRF_DEFAULT) < 0)
+       if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0)
                zlog_warn("%s: Failure to send nexthop to zebra",
                          __PRETTY_FUNCTION__);
 }
index b219022f028cd481d6afb296806589705da5d685..57ffcc7690dabb7ecd0121d16c61b234911b4f83 100644 (file)
 extern void sharp_zebra_init(void);
 
 extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
-extern void route_add(struct prefix *p, uint8_t instance,
+extern void route_add(struct prefix *p, vrf_id_t, uint8_t instance,
                      struct nexthop_group *nhg);
-extern void route_delete(struct prefix *p, uint8_t instance);
-extern void sharp_zebra_nexthop_watch(struct prefix *p, bool import,
-                                     bool watch, bool connected);
+extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance);
+extern void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id,
+                                     bool import, bool watch, bool connected);
 
-extern void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
-                                        struct nexthop_group *nhg,
-                                        uint32_t routes);
-extern void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
-                                      uint32_t routes);
+extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+                                       uint8_t instance,
+                                       struct nexthop_group *nhg,
+                                       uint32_t routes);
+extern void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+                                      uint8_t instance, uint32_t routes);
 #endif
index 38fd53a1f2a75818dc4230d7cf5b892d0d19b7d9..9af30a587a4a17b4d63baeec80cd6cb89c83dd65 100644 (file)
@@ -52,13 +52,13 @@ static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
                reinstall = false;
                for (si = rn->info; si; si = si->next) {
                        if (si->nh_vrf_id != nh_vrf_id)
-                               return;
+                               continue;
 
                        if (si->type != STATIC_IPV4_GATEWAY
                            && si->type != STATIC_IPV4_GATEWAY_IFNAME
                            && si->type != STATIC_IPV6_GATEWAY
                            && si->type != STATIC_IPV6_GATEWAY_IFNAME)
-                               return;
+                               continue;
 
                        orig = si->nh_valid;
                        if (p->family == AF_INET
index f09c304359a76adf53ae0e3d2536eeb8f055bc2b..3a9e4e8fa4671c933c7464fef325a248e25991e0 100644 (file)
@@ -104,30 +104,18 @@ static int static_list_compare_helper(const char *s1, const char *s2)
 
 static void static_list_delete(struct static_hold_route *shr)
 {
-       if (shr->vrf_name)
-               XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
-       if (shr->nhvrf_name)
-               XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
-       if (shr->dest_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->dest_str);
-       if (shr->mask_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->mask_str);
-       if (shr->src_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->src_str);
-       if (shr->gate_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->gate_str);
-       if (shr->ifname)
-               XFREE(MTYPE_STATIC_ROUTE, shr->ifname);
-       if (shr->flag_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->flag_str);
-       if (shr->tag_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->tag_str);
-       if (shr->distance_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->distance_str);
-       if (shr->label_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->label_str);
-       if (shr->table_str)
-               XFREE(MTYPE_STATIC_ROUTE, shr->table_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
+       XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
+       XFREE(MTYPE_STATIC_ROUTE, shr->dest_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->mask_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->src_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->gate_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->ifname);
+       XFREE(MTYPE_STATIC_ROUTE, shr->flag_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->tag_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->distance_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->label_str);
+       XFREE(MTYPE_STATIC_ROUTE, shr->table_str);
 
        XFREE(MTYPE_STATIC_ROUTE, shr);
 }
index 73243dcacf00d24bffa42112b807f207a08d6f5c..7b38df5f66a27e092c4e1a96c301ec349f87e36c 100644 (file)
@@ -158,7 +158,7 @@ static void test_range_lookup(void)
                                  "1.16.160.0/19", "1.16.32.0/20",
                                  "1.16.32.0/21",  "16.0.0.0/16"};
 
-       int num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+       int num_prefixes = array_size(prefixes);
 
        for (int i = 0; i < num_prefixes; i++)
                add_node(table, prefixes[i]);
index 04fbda42ebde788e5e1416eaa78739333d8fc25a..0ecd0fdfec75f0df2674688de65d9c2386a97371 100644 (file)
@@ -205,7 +205,7 @@ struct peer test_mp_list_peer[] = {
        {.local_as = 1, .as = 2}, {.local_as = 1, .as = 2},
        {.local_as = 1, .as = 2},
 };
-int test_mp_list_peer_count = sizeof(test_mp_list_peer) / sizeof(struct peer);
+int test_mp_list_peer_count = array_size(test_mp_list_peer);
 struct attr test_mp_list_attr[4];
 struct bgp_path_info test_mp_list_info[] = {
        {.peer = &test_mp_list_peer[0], .attr = &test_mp_list_attr[0]},
@@ -214,8 +214,7 @@ struct bgp_path_info test_mp_list_info[] = {
        {.peer = &test_mp_list_peer[3], .attr = &test_mp_list_attr[2]},
        {.peer = &test_mp_list_peer[4], .attr = &test_mp_list_attr[3]},
 };
-int test_mp_list_info_count =
-       sizeof(test_mp_list_info) / sizeof(struct bgp_path_info);
+int test_mp_list_info_count = array_size(test_mp_list_info);
 
 static int setup_bgp_mp_list(testcase_t *t)
 {
@@ -370,7 +369,7 @@ testcase_t *all_tests[] = {
        &test_bgp_path_info_mpath_update,
 };
 
-int all_tests_count = (sizeof(all_tests) / sizeof(testcase_t *));
+int all_tests_count = array_size(all_tests);
 
 /*=========================================================
  * Test Driver Functions
index 530468642eb81ca45cf67b70f4a583c2fcb6dc7b..d10962993d219f1b8f0658b786f3d05a8f238ce1 100644 (file)
@@ -31,7 +31,6 @@
 #include "lib/csv.h"
 #include "lib/debug.h"
 #include "lib/distribute.h"
-#include "lib/event_counter.h"
 #include "lib/ferr.h"
 #include "lib/fifo.h"
 #include "lib/filter.h"
index e203da8f6e579603f549fd99cc930aa1adfddeaf..fc3d908661f34b6af16e3017a3d20f4f8c90aac0 100644 (file)
@@ -37,7 +37,7 @@ struct zebra_privs_t test_privs = {
        .vty_group = VTY_GROUP,
 #endif
        .caps_p = _caps_p,
-       .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]),
+       .cap_num_p = array_size(_caps_p),
        .cap_num_i = 0};
 
 struct option longopts[] = {{"help", no_argument, NULL, 'h'},
index 5c0e171778300740e63ec57a35e57ea1796df202..19a40b21841f964ac583c9121106191a980391a2 100644 (file)
@@ -105,7 +105,7 @@ static unsigned int log_key(void *data)
 static bool log_cmp(const void *a, const void *b)
 {
        if (a == NULL || b == NULL)
-               return 0;
+               return false;
 
        return !memcmp(a, b, 2 * sizeof(struct prefix));
 }
index 2b65040627610f674297f8687e4ea7499dd7e400..90d6c76bf1c26a9f7c3402a759a6eb89b37e2988 100644 (file)
@@ -478,7 +478,7 @@ static void test_iter_pause(void)
        const char *prefixes[] = {"1.0.1.0/24", "1.0.1.0/25", "1.0.1.128/25",
                                  "1.0.2.0/24", "2.0.0.0/8"};
 
-       num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+       num_prefixes = array_size(prefixes);
 
        printf("\n\nTesting that route_table_iter_pause() works as expected\n");
        table = route_table_init();
index 6777cd9fc3031ea4bfda92082df65db83beda5b6..85388c738d549f908f3849a9386267fdd7ef196d 100644 (file)
@@ -1,7 +1,7 @@
 BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0
 BGP table version 1
 RIB entries 1, using XXXX bytes of memory
-Peers 4, using XXXX KiB of memory
+Peers 2, using XXXX KiB of memory
 
 Neighbor         V         AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd
 fc00:0:0:8::1000 4        100       0       0        0    0    0    never       Active
diff --git a/tests/topotests/bfd-topo2/__init__.py b/tests/topotests/bfd-topo2/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bfd-topo2/r1/bfdd.conf b/tests/topotests/bfd-topo2/r1/bfdd.conf
new file mode 100644 (file)
index 0000000..5c2571b
--- /dev/null
@@ -0,0 +1,5 @@
+bfd
+ peer 2001:db8:4::1 multihop local-address 2001:db8:1::1
+  no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-topo2/r1/bgpd.conf b/tests/topotests/bfd-topo2/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..1623b45
--- /dev/null
@@ -0,0 +1,13 @@
+router bgp 101
+ bgp router-id 10.254.254.1
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r1-eth0 interface peer-group r2g
+ address-family ipv4 unicast
+  redistribute connected
+ exit-address-family
+ address-family ipv6 unicast
+  neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-topo2/r1/ipv4_routes.json b/tests/topotests/bfd-topo2/r1/ipv4_routes.json
new file mode 100644 (file)
index 0000000..8a2ec25
--- /dev/null
@@ -0,0 +1,68 @@
+{
+    "10.0.3.0/24": [
+        {
+            "distance": 20,
+            "protocol": "bgp",
+            "internalFlags": 8,
+            "metric": 0,
+            "selected": true,
+            "installed": true,
+            "prefix": "10.0.3.0/24",
+            "internalStatus": 34,
+            "nexthops": [
+                {
+                    "interfaceName": "r1-eth0",
+                    "interfaceIndex": 2,
+                    "fib": true,
+                    "flags": 3,
+                    "active": true,
+                    "afi": "ipv6"
+                }
+            ]
+        }
+    ],
+    "10.254.254.2/32": [
+        {
+            "distance": 20,
+            "protocol": "bgp",
+            "internalFlags": 8,
+            "metric": 0,
+            "selected": true,
+            "installed": true,
+            "prefix": "10.254.254.2/32",
+            "internalStatus": 34,
+            "nexthops": [
+                {
+                    "interfaceName": "r1-eth0",
+                    "interfaceIndex": 2,
+                    "fib": true,
+                    "flags": 3,
+                    "active": true,
+                    "afi": "ipv6"
+                }
+            ]
+        }
+    ],
+    "10.254.254.1/32": [
+        {
+            "distance": 0,
+            "protocol": "connected",
+            "internalFlags": 8,
+            "metric": 0,
+            "selected": true,
+            "installed": true,
+            "prefix": "10.254.254.1/32",
+            "internalStatus": 32,
+            "nexthops": [
+                {
+                    "directlyConnected": true,
+                    "interfaceName": "lo",
+                    "interfaceIndex": 1,
+                    "fib": true,
+                    "flags": 3,
+                    "active": true
+                }
+            ]
+        }
+    ]
+}
diff --git a/tests/topotests/bfd-topo2/r1/ipv6_routes.json b/tests/topotests/bfd-topo2/r1/ipv6_routes.json
new file mode 100644 (file)
index 0000000..618853b
--- /dev/null
@@ -0,0 +1,63 @@
+{
+  "2001:db8:4::/64": [
+    {
+      "distance": 20,
+      "protocol": "bgp",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "2001:db8:4::/64",
+      "internalStatus": 34,
+      "nexthops": [
+        {
+          "interfaceName": "r1-eth0",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true,
+          "afi": "ipv6"
+        }
+      ]
+    }
+  ],
+  "2001:db8:1::/64": [
+    {
+      "distance": 20,
+      "protocol": "bgp",
+      "internalFlags": 0,
+      "metric": 0,
+      "internalStatus": 2,
+      "prefix": "2001:db8:1::/64",
+      "nexthops": [
+        {
+          "interfaceName": "r1-eth0",
+          "interfaceIndex": 2,
+          "flags": 1,
+          "active": true,
+          "afi": "ipv6"
+        }
+      ]
+    },
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "2001:db8:1::/64",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "r1-eth0",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-topo2/r1/peers.json b/tests/topotests/bfd-topo2/r1/peers.json
new file mode 100644 (file)
index 0000000..b14351c
--- /dev/null
@@ -0,0 +1,29 @@
+[
+    {
+        "multihop":true,
+        "peer":"2001:db8:4::1",
+        "local":"2001:db8:1::1",
+        "status":"up",
+        "diagnostic":"ok",
+        "remote-diagnostic":"ok",
+        "receive-interval":300,
+        "transmit-interval":300,
+        "echo-interval":0,
+        "remote-receive-interval":300,
+        "remote-transmit-interval":300,
+        "remote-echo-interval":50
+    },
+    {
+        "multihop":false,
+        "interface":"r1-eth0",
+        "status":"up",
+        "diagnostic":"ok",
+        "remote-diagnostic":"ok",
+        "receive-interval":300,
+        "transmit-interval":300,
+        "echo-interval":0,
+        "remote-receive-interval":300,
+        "remote-transmit-interval":300,
+        "remote-echo-interval":50
+    }
+]
diff --git a/tests/topotests/bfd-topo2/r1/zebra.conf b/tests/topotests/bfd-topo2/r1/zebra.conf
new file mode 100644 (file)
index 0000000..7fe5eb2
--- /dev/null
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.1/32
+!
+interface r1-eth0
+ ipv6 address 2001:db8:1::1/64
+!
diff --git a/tests/topotests/bfd-topo2/r2/bgpd.conf b/tests/topotests/bfd-topo2/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..bf42d21
--- /dev/null
@@ -0,0 +1,16 @@
+router bgp 102
+ bgp router-id 10.254.254.2
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r2-eth0 interface peer-group r2g
+ !
+ address-family ipv4 unicast
+  redistribute connected
+ exit-address-family
+ !
+ address-family ipv6 unicast
+  redistribute connected
+  neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-topo2/r2/ipv4_routes.json b/tests/topotests/bfd-topo2/r2/ipv4_routes.json
new file mode 100644 (file)
index 0000000..b9d8afb
--- /dev/null
@@ -0,0 +1,108 @@
+{
+  "10.0.3.0/24": [
+    {
+      "distance": 110,
+      "protocol": "ospf",
+      "internalFlags": 0,
+      "metric": 10,
+      "internalStatus": 2,
+      "prefix": "10.0.3.0/24",
+      "nexthops": [
+        {
+          "active": true,
+          "directlyConnected": true,
+          "flags": 1,
+          "interfaceIndex": 3,
+          "interfaceName": "r2-eth1"
+        }
+      ]
+    },
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.0.3.0/24",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "r2-eth1",
+          "interfaceIndex": 3,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ],
+  "10.254.254.3/32": [
+    {
+      "distance": 110,
+      "protocol": "ospf",
+      "internalFlags": 8,
+      "metric": 20,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.254.254.3/32",
+      "internalStatus": 34,
+      "nexthops": [
+        {
+          "interfaceName": "r2-eth1",
+          "ip": "10.0.3.1",
+          "interfaceIndex": 3,
+          "fib": true,
+          "flags": 3,
+          "active": true,
+          "afi": "ipv4"
+        }
+      ]
+    }
+  ],
+  "10.254.254.2/32": [
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.254.254.2/32",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "lo",
+          "interfaceIndex": 1,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ],
+  "10.254.254.1/32": [
+    {
+      "distance": 20,
+      "protocol": "bgp",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.254.254.1/32",
+      "internalStatus": 34,
+      "nexthops": [
+        {
+          "interfaceName": "r2-eth0",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true,
+          "afi": "ipv6"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-topo2/r2/ipv6_routes.json b/tests/topotests/bfd-topo2/r2/ipv6_routes.json
new file mode 100644 (file)
index 0000000..004e758
--- /dev/null
@@ -0,0 +1,63 @@
+{
+  "2001:db8:4::/64": [
+    {
+      "distance": 110,
+      "protocol": "ospf6",
+      "internalFlags": 0,
+      "metric": 10,
+      "internalStatus": 2,
+      "prefix": "2001:db8:4::/64",
+      "nexthops": [
+        {
+          "active": true,
+          "directlyConnected": true,
+          "flags": 1,
+          "interfaceIndex": 4,
+          "interfaceName": "r2-eth2"
+        }
+      ]
+    },
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "2001:db8:4::/64",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "r2-eth2",
+          "interfaceIndex": 4,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ],
+  "2001:db8:1::/64": [
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "2001:db8:1::/64",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "r2-eth0",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-topo2/r2/ospf6d.conf b/tests/topotests/bfd-topo2/r2/ospf6d.conf
new file mode 100644 (file)
index 0000000..f1cdb50
--- /dev/null
@@ -0,0 +1,9 @@
+interface r2-eth2
+ ipv6 ospf6 bfd
+!
+router ospf6
+ ospf6 router-id 10.254.254.2
+ redistribute connected
+ redistribute bgp
+ interface r2-eth2 area 0.0.0.1
+!
diff --git a/tests/topotests/bfd-topo2/r2/ospfd.conf b/tests/topotests/bfd-topo2/r2/ospfd.conf
new file mode 100644 (file)
index 0000000..8e0c459
--- /dev/null
@@ -0,0 +1,9 @@
+interface r2-eth1
+ ip ospf area 0.0.0.1
+ ip ospf bfd
+!
+router ospf
+ ospf router-id 10.254.254.2
+ redistribute connected
+ redistribute bgp
+!
diff --git a/tests/topotests/bfd-topo2/r2/peers.json b/tests/topotests/bfd-topo2/r2/peers.json
new file mode 100644 (file)
index 0000000..29075fc
--- /dev/null
@@ -0,0 +1,42 @@
+[
+  {
+    "status": "up",
+    "transmit-interval": 300,
+    "remote-receive-interval": 300,
+    "echo-interval": 0,
+    "diagnostic": "ok",
+    "multihop": false,
+    "interface": "r2-eth0",
+    "remote-transmit-interval": 300,
+    "receive-interval": 300,
+    "remote-echo-interval": 50,
+    "remote-diagnostic": "ok"
+  },
+  {
+    "status": "up",
+    "transmit-interval": 300,
+    "remote-receive-interval": 300,
+    "echo-interval": 0,
+    "diagnostic": "ok",
+    "multihop": false,
+    "interface": "r2-eth2",
+    "remote-transmit-interval": 300,
+    "receive-interval": 300,
+    "remote-echo-interval": 50,
+    "remote-diagnostic": "ok"
+  },
+  {
+    "status": "up",
+    "transmit-interval": 300,
+    "remote-receive-interval": 300,
+    "echo-interval": 0,
+    "diagnostic": "ok",
+    "multihop": false,
+    "interface": "r2-eth1",
+    "remote-transmit-interval": 300,
+    "receive-interval": 300,
+    "remote-echo-interval": 50,
+    "remote-diagnostic": "ok",
+    "peer": "10.0.3.1"
+  }
+]
diff --git a/tests/topotests/bfd-topo2/r2/zebra.conf b/tests/topotests/bfd-topo2/r2/zebra.conf
new file mode 100644 (file)
index 0000000..cccbf65
--- /dev/null
@@ -0,0 +1,15 @@
+ip forwarding
+ipv6 forwarding
+!
+interface lo
+ ip address 10.254.254.2/32
+!
+interface r2-eth0
+ ipv6 address 2001:db8:1::2/64
+!
+interface r2-eth1
+ ip address 10.0.3.2/24
+!
+interface r2-eth2
+ ipv6 address 2001:db8:4::2/64
+!
diff --git a/tests/topotests/bfd-topo2/r3/ipv4_routes.json b/tests/topotests/bfd-topo2/r3/ipv4_routes.json
new file mode 100644 (file)
index 0000000..14dfc69
--- /dev/null
@@ -0,0 +1,109 @@
+{
+  "10.0.3.0/24": [
+    {
+      "distance": 110,
+      "protocol": "ospf",
+      "internalFlags": 0,
+      "metric": 10,
+      "internalStatus": 0,
+      "prefix": "10.0.3.0/24",
+      "nexthops": [
+        {
+          "active": true,
+          "directlyConnected": true,
+          "flags": 1,
+          "interfaceIndex": 2,
+          "interfaceName": "r3-eth0"
+        }
+      ]
+    },
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.0.3.0/24",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "r3-eth0",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ],
+  "10.254.254.3/32": [
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.254.254.3/32",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "lo",
+          "interfaceIndex": 1,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ],
+  "10.254.254.2/32": [
+    {
+      "distance": 110,
+      "protocol": "ospf",
+      "internalFlags": 8,
+      "metric": 20,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.254.254.2/32",
+      "internalStatus": 34,
+      "nexthops": [
+        {
+          "interfaceName": "r3-eth0",
+          "ip": "10.0.3.2",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true,
+          "afi": "ipv4"
+        }
+      ]
+    }
+  ],
+  "10.254.254.1/32": [
+    {
+      "distance": 110,
+      "protocol": "ospf",
+      "internalFlags": 8,
+      "metric": 20,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.254.254.1/32",
+      "internalStatus": 34,
+      "nexthops": [
+        {
+          "interfaceName": "r3-eth0",
+          "ip": "10.0.3.2",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true,
+          "afi": "ipv4"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-topo2/r3/ipv6_routes.json b/tests/topotests/bfd-topo2/r3/ipv6_routes.json
new file mode 100644 (file)
index 0000000..2c63c08
--- /dev/null
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/bfd-topo2/r3/ospfd.conf b/tests/topotests/bfd-topo2/r3/ospfd.conf
new file mode 100644 (file)
index 0000000..cf2a1bd
--- /dev/null
@@ -0,0 +1,8 @@
+interface r3-eth0
+ ip ospf area 0.0.0.1
+ ip ospf bfd
+!
+router ospf
+ ospf router-id 10.254.254.3
+ redistribute connected
+!
diff --git a/tests/topotests/bfd-topo2/r3/peers.json b/tests/topotests/bfd-topo2/r3/peers.json
new file mode 100644 (file)
index 0000000..6698bff
--- /dev/null
@@ -0,0 +1,16 @@
+[
+  {
+    "status": "up",
+    "transmit-interval": 300,
+    "remote-receive-interval": 300,
+    "echo-interval": 0,
+    "diagnostic": "ok",
+    "multihop": false,
+    "interface": "r3-eth0",
+    "remote-transmit-interval": 300,
+    "receive-interval": 300,
+    "remote-echo-interval": 50,
+    "remote-diagnostic": "ok",
+    "peer": "10.0.3.2"
+  }
+]
diff --git a/tests/topotests/bfd-topo2/r3/zebra.conf b/tests/topotests/bfd-topo2/r3/zebra.conf
new file mode 100644 (file)
index 0000000..96fd08c
--- /dev/null
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.3/32
+!
+interface r3-eth0
+ ip address 10.0.3.1/24
+!
diff --git a/tests/topotests/bfd-topo2/r4/bfdd.conf b/tests/topotests/bfd-topo2/r4/bfdd.conf
new file mode 100644 (file)
index 0000000..fdb4412
--- /dev/null
@@ -0,0 +1,5 @@
+bfd
+ peer 2001:db8:1::1 multihop local-address 2001:db8:4::1
+  no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-topo2/r4/ipv4_routes.json b/tests/topotests/bfd-topo2/r4/ipv4_routes.json
new file mode 100644 (file)
index 0000000..ae1e97b
--- /dev/null
@@ -0,0 +1,24 @@
+{
+  "10.254.254.4/32": [
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "10.254.254.4/32",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "lo",
+          "interfaceIndex": 1,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-topo2/r4/ipv6_routes.json b/tests/topotests/bfd-topo2/r4/ipv6_routes.json
new file mode 100644 (file)
index 0000000..33608b4
--- /dev/null
@@ -0,0 +1,63 @@
+{
+  "2001:db8:4::/64": [
+    {
+      "distance": 110,
+      "protocol": "ospf6",
+      "internalFlags": 0,
+      "metric": 10,
+      "internalStatus": 2,
+      "prefix": "2001:db8:4::/64",
+      "nexthops": [
+        {
+          "active": true,
+          "directlyConnected": true,
+          "flags": 1,
+          "interfaceIndex": 2,
+          "interfaceName": "r4-eth0"
+        }
+      ]
+    },
+    {
+      "distance": 0,
+      "protocol": "connected",
+      "internalFlags": 8,
+      "metric": 0,
+      "selected": true,
+      "installed": true,
+      "prefix": "2001:db8:4::/64",
+      "internalStatus": 32,
+      "nexthops": [
+        {
+          "directlyConnected": true,
+          "interfaceName": "r4-eth0",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ],
+  "2001:db8:1::/64": [
+    {
+      "distance": 110,
+      "protocol": "ospf6",
+      "internalFlags": 8,
+      "metric": 10,
+      "selected": true,
+      "installed": true,
+      "prefix": "2001:db8:1::/64",
+      "internalStatus": 34,
+      "nexthops": [
+        {
+          "interfaceName": "r4-eth0",
+          "interfaceIndex": 2,
+          "fib": true,
+          "flags": 3,
+          "active": true,
+          "afi": "ipv6"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-topo2/r4/ospf6d.conf b/tests/topotests/bfd-topo2/r4/ospf6d.conf
new file mode 100644 (file)
index 0000000..756597d
--- /dev/null
@@ -0,0 +1,8 @@
+interface r4-eth0
+ ipv6 ospf6 bfd
+!
+router ospf6
+ ospf6 router-id 10.254.254.4
+ redistribute connected
+ interface r4-eth0 area 0.0.0.1
+!
diff --git a/tests/topotests/bfd-topo2/r4/peers.json b/tests/topotests/bfd-topo2/r4/peers.json
new file mode 100644 (file)
index 0000000..83101eb
--- /dev/null
@@ -0,0 +1,29 @@
+[
+    {
+        "multihop":true,
+        "peer":"2001:db8:1::1",
+        "local":"2001:db8:4::1",
+        "status":"up",
+        "diagnostic":"ok",
+        "remote-diagnostic":"ok",
+        "receive-interval":300,
+        "transmit-interval":300,
+        "echo-interval":0,
+        "remote-receive-interval":300,
+        "remote-transmit-interval":300,
+        "remote-echo-interval":50
+    },
+    {
+        "multihop":false,
+        "interface":"r4-eth0",
+        "status":"up",
+        "diagnostic":"ok",
+        "remote-diagnostic":"ok",
+        "receive-interval":300,
+        "transmit-interval":300,
+        "echo-interval":0,
+        "remote-receive-interval":300,
+        "remote-transmit-interval":300,
+        "remote-echo-interval":50
+    }
+]
diff --git a/tests/topotests/bfd-topo2/r4/zebra.conf b/tests/topotests/bfd-topo2/r4/zebra.conf
new file mode 100644 (file)
index 0000000..e4f8fd8
--- /dev/null
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.4/32
+!
+interface r4-eth0
+ ipv6 address 2001:db8:4::1/64
+!
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.dot b/tests/topotests/bfd-topo2/test_bfd_topo2.dot
new file mode 100644 (file)
index 0000000..6b68fb3
--- /dev/null
@@ -0,0 +1,73 @@
+## Color coding:
+#########################
+##  Main FRR: #f08080  red
+##  Switches: #d0e0d0  gray
+##  RIP:      #19e3d9  Cyan
+##  RIPng:    #fcb314  dark yellow
+##  OSPFv2:   #32b835  Green
+##  OSPFv3:   #19e3d9  Cyan
+##  ISIS IPv4 #fcb314  dark yellow
+##  ISIS IPv6 #9a81ec  purple
+##  BGP IPv4  #eee3d3  beige
+##  BGP IPv6  #fdff00  yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+  label="bfd-topo2";
+
+  # Routers
+  r1 [
+    shape=doubleoctagon,
+    label="r1",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r2 [
+    shape=doubleoctagon
+    label="r2",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r3 [
+    shape=doubleoctagon
+    label="r3",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r4 [
+    shape=doubleoctagon
+    label="r4",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+
+  # Switches
+  sw1 [
+    shape=oval,
+    label="sw1\n2001:db8:1::/64",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw2 [
+    shape=oval,
+    label="sw2\n10.0.3.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw3 [
+    shape=oval,
+    label="sw3\n2001:db8:4::/64",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+
+  # Connections
+  r1 -- sw1 [label="eth0"];
+  r2 -- sw1 [label="eth0"];
+
+  r2 -- sw2 [label="eth1"];
+  r3 -- sw2 [label="eth0"];
+
+  r2 -- sw3 [label="eth2"];
+  r4 -- sw3 [label="eth0"];
+}
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.jpg b/tests/topotests/bfd-topo2/test_bfd_topo2.jpg
new file mode 100644 (file)
index 0000000..35fe562
Binary files /dev/null and b/tests/topotests/bfd-topo2/test_bfd_topo2.jpg differ
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.py b/tests/topotests/bfd-topo2/test_bfd_topo2.py
new file mode 100644 (file)
index 0000000..773db12
--- /dev/null
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+
+#
+# test_bfd_topo2.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_bfd_topo2.py: Test the FRR/Quagga BFD daemon with multihop and BGP
+unnumbered.
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class BFDTopo(Topo):
+    "Test topology builder"
+    def build(self, *_args, **_opts):
+        "Build function"
+        tgen = get_topogen(self)
+
+        # Create 4 routers.
+        for routern in range(1, 5):
+            tgen.add_router('r{}'.format(routern))
+
+        switch = tgen.add_switch('s1')
+        switch.add_link(tgen.gears['r1'])
+        switch.add_link(tgen.gears['r2'])
+
+        switch = tgen.add_switch('s2')
+        switch.add_link(tgen.gears['r2'])
+        switch.add_link(tgen.gears['r3'])
+
+        switch = tgen.add_switch('s3')
+        switch.add_link(tgen.gears['r2'])
+        switch.add_link(tgen.gears['r4'])
+
+
+def setup_module(mod):
+    "Sets up the pytest environment"
+    tgen = Topogen(BFDTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+    for rname, router in router_list.iteritems():
+        router.load_config(
+            TopoRouter.RD_ZEBRA,
+            os.path.join(CWD, '{}/zebra.conf'.format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_BFD,
+            os.path.join(CWD, '{}/bfdd.conf'.format(rname))
+        )
+        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_OSPF6,
+            os.path.join(CWD, '{}/ospf6d.conf'.format(rname))
+        )
+
+    # Initialize all routers.
+    tgen.start_router()
+
+    # Verify that we are using the proper version and that the BFD
+    # daemon exists.
+    for router in router_list.values():
+        # Check for Version
+        if router.has_version('<', '5.1'):
+            tgen.set_error('Unsupported FRR version')
+            break
+
+
+def teardown_module(_mod):
+    "Teardown the pytest environment"
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+def test_protocols_convergence():
+    """
+    Assert that all protocols have converged before checking for the BFD
+    statuses as they depend on it.
+    """
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # Check IPv4 routing tables.
+    logger.info("Checking IPv4 routes for convergence")
+    for router in tgen.routers().values():
+        json_file = '{}/{}/ipv4_routes.json'.format(CWD, router.name)
+        if not os.path.isfile(json_file):
+            logger.info('skipping file {}'.format(json_file))
+            continue
+
+        expected = json.loads(open(json_file).read())
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show ip route json', expected)
+        _, result = topotest.run_and_expect(test_func, None, count=160,
+                                            wait=0.5)
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert result is None, assertmsg
+
+    # Check IPv6 routing tables.
+    logger.info("Checking IPv6 routes for convergence")
+    for router in tgen.routers().values():
+        json_file = '{}/{}/ipv6_routes.json'.format(CWD, router.name)
+        if not os.path.isfile(json_file):
+            logger.info('skipping file {}'.format(json_file))
+            continue
+
+        expected = json.loads(open(json_file).read())
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show ipv6 route json', expected)
+        _, result = topotest.run_and_expect(test_func, None, count=160,
+                                            wait=0.5)
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert result is None, assertmsg
+
+
+def test_bfd_connection():
+    "Assert that the BFD peers can find themselves."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info('waiting for bfd peers to go up')
+
+    for router in tgen.routers().values():
+        json_file = '{}/{}/peers.json'.format(CWD, router.name)
+        expected = json.loads(open(json_file).read())
+
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show bfd peers json', expected)
+        _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+        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))
index 344fb2ffcba97958d52e8e152a8fad1752ec72f9..70ce2efe851667d176a382b91b0ec985a7e5d859 100755 (executable)
@@ -26,5 +26,5 @@ cd "$(dirname "$0")"/..
 
 exec docker build --pull \
                  --compress \
-                 -t frrouting/frr:topotests-latest \
+                 -t frrouting/topotests:latest \
                  .
index 6d8bea00022d93ad9b39083cdce5fa32368102be..ef916abcf3c7daefb480e33b7580c4fd6584e148 100755 (executable)
@@ -136,7 +136,7 @@ if [ -z "$TOPOTEST_BUILDCACHE" ]; then
 fi
 
 if [ "${TOPOTEST_PULL:-1}" = "1" ]; then
-       docker pull frrouting/frr:topotests-latest
+       docker pull frrouting/topotests:latest
 fi
 
 set -- --rm -i \
@@ -149,7 +149,7 @@ set -- --rm -i \
        -e "TOPOTEST_SANITIZER=$TOPOTEST_SANITIZER" \
        --privileged \
        $TOPOTEST_OPTIONS \
-       frrouting/frr:topotests-latest "$@"
+       frrouting/topotests:latest "$@"
 
 if [ -t 0 ]; then
        set -- -t "$@"
index d0ec9f5d75988210e2780389116b85f2686ed91c..edfa1780a946e42a38d7ef91d8cd30cab5457e8e 100644 (file)
@@ -2,10 +2,12 @@ log file zebra.log
 !
 hostname r1
 !
-debug zebra rib
+debug zebra kernel
+debug zebra rib detailed
+debug zebra dplane detailed
 debug zebra nht
 debug zebra pseudowires
-debug zebra packet
+debug zebra mpls
 !
 interface lo
  ip address 1.1.1.1/32
index 8bd800714c2a6af8e2f3f464e588bc44b881c05d..6b95efdce8c2e88eea4476a7fa6b4f4b6fbc5d60 100644 (file)
@@ -2,10 +2,11 @@ log file zebra.log
 !
 hostname r2
 !
-debug zebra rib
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
 debug zebra nht
 debug zebra pseudowires
-debug zebra packet
 !
 interface lo
  ip address 2.2.2.2/32
index 2ff61365b5e20084ebac6a1202d3e9d33542539e..85ec68ff32bbdbbda52f033e6aeb632f27aad24f 100644 (file)
@@ -2,10 +2,11 @@ log file zebra.log
 !
 hostname r3
 !
-debug zebra rib
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
 debug zebra nht
 debug zebra pseudowires
-debug zebra packet
 !
 interface lo
  ip address 3.3.3.3/32
index 8688a13aef16b8f0dfcd0508aa9b22f252a1f692..d989240a162ba91349620d5247cc36f4a90b9d6a 100644 (file)
@@ -586,9 +586,9 @@ class TopoRouter(TopoGear):
         os.system('chmod -R go+rw /tmp/topotests')
 
         # Open router log file
-        logfile = '{0}/{1}.log'.format(dir, name)
-
+        logfile = '{0}/{1}.log'.format(self.logdir, name)
         self.logger = logger_config.get_logger(name=name, target=logfile)
+
         self.tgen.topo.addNode(self.name, cls=self.cls, **params)
 
     def __str__(self):
index 84358b94bc2b29171f167308746b1a150f612966..e0da20e07f506d95d37479b422f7b497f3665c4c 100644 (file)
@@ -63,23 +63,6 @@ class json_cmp_result(object):
     def __str__(self):
         return '\n'.join(self.errors)
 
-def get_test_logdir(node=None, init=False):
-    """
-    Return the current test log directory based on PYTEST_CURRENT_TEST
-    environment variable.
-    Optional paramters:
-    node:  when set, adds the node specific log directory to the init dir
-    init:  when set, initializes the log directory and fixes path permissions
-    """
-    cur_test = os.environ['PYTEST_CURRENT_TEST']
-
-    ret = '/tmp/topotests/' + cur_test[0:cur_test.find(".py")].replace('/','.')
-    if node != None:
-        dir = ret + "/" + node
-    if init:
-        os.system('mkdir -p ' + dir)
-        os.system('chmod -R go+rw /tmp/topotests')
-    return ret
 
 def json_diff(d1, d2):
     """
@@ -612,7 +595,21 @@ class Router(Node):
 
     def __init__(self, name, **params):
         super(Router, self).__init__(name, **params)
-        self.logdir = params.get('logdir', get_test_logdir(name, True))
+        self.logdir = params.get('logdir')
+
+        # If this topology is using old API and doesn't have logdir
+        # specified, then attempt to generate an unique logdir.
+        if self.logdir is None:
+            cur_test = os.environ['PYTEST_CURRENT_TEST']
+            self.logdir = ('/tmp/topotests/' +
+                           cur_test[0:cur_test.find(".py")].replace('/', '.'))
+
+        # If the logdir is not created, then create it and set the
+        # appropriated permissions.
+        if not os.path.isdir(self.logdir):
+            os.system('mkdir -p ' + self.logdir + '/' + name)
+            os.system('chmod -R go+rw /tmp/topotests')
+
         self.daemondir = None
         self.hasmpls = False
         self.routertype = 'frr'
diff --git a/tests/topotests/pim-basic/mcast-rx.py b/tests/topotests/pim-basic/mcast-rx.py
new file mode 100755 (executable)
index 0000000..9e3484e
--- /dev/null
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+#
+# mcast-rx.py
+#
+# Copyright (c) 2018 Cumulus Networks, Inc.
+#
+# 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 Cumulus Networks 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.
+#
+"""
+Subscribe to a multicast group so that the kernel sends an IGMP JOIN
+for the multicast group we subscribed to.
+"""
+
+import argparse
+import logging
+import re
+import os
+import socket
+import subprocess
+import struct
+import sys
+import time
+
+
+def ifname_to_ifindex(ifname):
+    output = subprocess.check_output("ip link show %s" % ifname, shell=True)
+    first_line = output.split('\n')[0]
+    re_index = re.search('^(\d+):', first_line)
+
+    if re_index:
+        return int(re_index.group(1))
+
+    log.error("Could not parse the ifindex for %s out of\n%s" % (ifname, first_line))
+    return None
+
+
+# Thou shalt be root
+if os.geteuid() != 0:
+    sys.stderr.write('ERROR: You must have root privileges\n')
+    sys.exit(1)
+
+
+logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)5s: %(message)s')
+
+# Color the errors and warnings in red
+logging.addLevelName(logging.ERROR, "\033[91m  %s\033[0m" % logging.getLevelName(logging.ERROR))
+logging.addLevelName(logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING))
+log = logging.getLogger(__name__)
+
+parser = argparse.ArgumentParser(description='Multicast RX utility',
+                                 version='1.0.0')
+parser.add_argument('group', help='Multicast IP')
+parser.add_argument('ifname', help='Interface name')
+parser.add_argument('--port', help='UDP port', default=1000)
+parser.add_argument('--sleep', help='Time to sleep before we stop waiting',
+                    default = 5)
+args = parser.parse_args()
+
+# Create the datagram socket
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+sock.bind((args.group, args.port))
+
+newpid = os.fork()
+
+if newpid == 0:
+    ifindex = ifname_to_ifindex(args.ifname)
+    mreq = struct.pack("=4sLL", socket.inet_aton(args.group), socket.INADDR_ANY, ifindex)
+    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
+    time.sleep(float(args.sleep))
+    sock.close()
diff --git a/tests/topotests/pim-basic/mcast-tx.py b/tests/topotests/pim-basic/mcast-tx.py
new file mode 100755 (executable)
index 0000000..c469e47
--- /dev/null
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+#
+# mcast-tx.py
+#
+# Copyright (c) 2018 Cumulus Networks, Inc.
+#
+# 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 Cumulus Networks 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 argparse
+import logging
+import socket
+import struct
+import time
+
+
+logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)5s: %(message)s')
+
+# Color the errors and warnings in red
+logging.addLevelName(logging.ERROR, "\033[91m  %s\033[0m" % logging.getLevelName(logging.ERROR))
+logging.addLevelName(logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING))
+log = logging.getLogger(__name__)
+
+parser = argparse.ArgumentParser(description='Multicast packet generator', version='1.0.0')
+parser.add_argument('group', help='Multicast IP')
+parser.add_argument('ifname', help='Interface name')
+parser.add_argument('--port', type=int, help='UDP port number', default=1000)
+parser.add_argument('--ttl', type=int, help='time-to-live', default=20)
+parser.add_argument('--count', type=int, help='Packets to send', default=1)
+parser.add_argument('--interval', type=int, help='ms between packets', default=100)
+args = parser.parse_args()
+
+# Create the datagram socket
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+# IN.SO_BINDTODEVICE is not defined in some releases of python but it is 25
+# https://github.com/sivel/bonding/issues/10
+#
+# Bind our socket to ifname
+sock.setsockopt(socket.SOL_SOCKET,
+                25,
+                struct.pack("%ds" % len(args.ifname), args.ifname))
+
+# We need to make sure our sendto() finishes before we close the socket
+sock.setblocking(1)
+
+# Set the time-to-live
+sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, struct.pack('b', args.ttl))
+
+ms = args.interval / 1000.0
+
+# Send data to the multicast group
+for x in xrange(args.count):
+    log.info('TX multicast UDP packet to %s:%d on %s' % (args.group, args.port, args.ifname))
+    sent = sock.sendto('foobar %d' % x, (args.group, args.port))
+
+    if args.count > 1 and ms:
+        time.sleep(ms)
+
+sock.close()
diff --git a/tests/topotests/pim-basic/r1/pimd.conf b/tests/topotests/pim-basic/r1/pimd.conf
new file mode 100644 (file)
index 0000000..5740c66
--- /dev/null
@@ -0,0 +1,10 @@
+hostname r1
+!
+interface r1-eth0
+  ip igmp
+  ip pim sm
+!
+interface lo
+  ip pim sm
+!
+ip pim rp 10.254.0.1
diff --git a/tests/topotests/pim-basic/r1/zebra.conf b/tests/topotests/pim-basic/r1/zebra.conf
new file mode 100644 (file)
index 0000000..2bf7129
--- /dev/null
@@ -0,0 +1,8 @@
+hostname r1
+!
+interface r1-eth0
+ ip address 10.0.20.1/24
+!
+interface lo
+ ip address 10.254.0.1/32
+!
diff --git a/tests/topotests/pim-basic/r2/pimd.conf b/tests/topotests/pim-basic/r2/pimd.conf
new file mode 100644 (file)
index 0000000..932cff6
--- /dev/null
@@ -0,0 +1 @@
+hostname r2
diff --git a/tests/topotests/pim-basic/r2/zebra.conf b/tests/topotests/pim-basic/r2/zebra.conf
new file mode 100644 (file)
index 0000000..cb30858
--- /dev/null
@@ -0,0 +1,8 @@
+hostname r2
+!
+interface r2-eth0
+ ip address 10.0.20.2/24
+!
+interface lo
+ ip address 10.254.0.2/32
+!
diff --git a/tests/topotests/pim-basic/test_pim.py b/tests/topotests/pim-basic/test_pim.py
new file mode 100644 (file)
index 0000000..6d54b8f
--- /dev/null
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+
+#
+# test_pim.py
+#
+# Copyright (c) 2018 Cumulus Networks, Inc.
+#                    Donald Sharp
+#
+# 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 Cumulus Networks DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_pim.py: Test pim
+"""
+
+import os
+import sys
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from mininet.topo import Topo
+
+class PIMTopo(Topo):
+    def build(self, *_args, **_opts):
+        "Build function"
+        tgen = get_topogen(self)
+
+        for routern in range(1, 3):
+            tgen.add_router('r{}'.format(routern))
+
+        # r1 <- sw1 -> r2
+        sw = tgen.add_switch('sw1')
+        sw.add_link(tgen.gears['r1'])
+        sw.add_link(tgen.gears['r2'])
+
+
+def setup_module(mod):
+    "Sets up the pytest environment"
+    tgen = Topogen(PIMTopo, mod.__name__)
+    tgen.start_topology()
+
+    # For all registered routers, load the zebra configuration file
+    for rname, router in tgen.routers().iteritems():
+        router.load_config(
+            TopoRouter.RD_ZEBRA,
+            os.path.join(CWD, '{}/zebra.conf'.format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_PIM,
+            os.path.join(CWD, '{}/pimd.conf'.format(rname))
+        )
+
+    # After loading the configurations, this function loads configured daemons.
+    tgen.start_router()
+
+
+def teardown_module(mod):
+    "Teardown the pytest environment"
+    tgen = get_topogen()
+
+    # This function tears down the whole topology.
+    tgen.stop_topology()
+
+
+def test_pim_send_mcast_stream():
+    "Establish a Multicast stream from r2 -> r1 and then ensure S,G is created as appropriate"
+    logger.info("Establish a Mcast stream from r2->r1 and then ensure S,G created")
+
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    r2 = tgen.gears['r2']
+    r1 = tgen.gears['r1']
+
+    # Let's establish a S,G stream from r2 -> r1
+    CWD = os.path.dirname(os.path.realpath(__file__))
+    r2.run("{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r2-eth0 > /tmp/bar".format(CWD))
+
+    # Let's see that it shows up and we have established some basic state
+    out = r1.vtysh_cmd("show ip pim upstream json", isjson=True)
+    expected = {
+        '229.1.1.1': {
+            '10.0.20.2': {
+                'firstHopRouter': 1,
+                'joinState': 'NotJoined',
+                'regState': 'RegPrune',
+                'inboundInterface': 'r1-eth0',
+            }
+        }
+    }
+
+    assert topotest.json_cmp(out, expected) is None, 'failed to converge pim'
+
+
+def test_pim_igmp_report():
+    "Send a igmp report from r2->r1 and ensure that the *,G state is created on r1"
+    logger.info("Send a igmp report from r2-r1 and ensure *,G created")
+
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    r2 = tgen.gears['r2']
+    r1 = tgen.gears['r1']
+
+    # Let's send a igmp report from r2->r1
+    CWD = os.path.dirname(os.path.realpath(__file__))
+    r2.run("{}/mcast-rx.py 229.1.1.2 r2-eth0 &".format(CWD))
+
+    out = r1.vtysh_cmd("show ip pim upstream json", isjson=True)
+    expected = {
+        '229.1.1.2': {
+            '*': {
+                'sourceIgmp': 1,
+                'joinState': 'Joined',
+                'regState': 'RegNoInfo',
+                'sptBit': 0,
+            }
+        }
+    }
+
+    assert topotest.json_cmp(out, expected) is None, 'failed to converge pim'
+
+
+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/tools/coccinelle/alloc_cast.cocci b/tools/coccinelle/alloc_cast.cocci
new file mode 100644 (file)
index 0000000..b1497c7
--- /dev/null
@@ -0,0 +1,101 @@
+/// Remove casting the values returned by memory allocation functions
+/// like XMALLOC and XCALLOC.
+///
+// This makes an effort to find cases of casting of values returned by #
+// XMALLOC and XCALLOC and removes the casting as it is not required. The
+// result in the patch case may need some reformatting.
+//
+// Confidence: High
+// Copyright: (C) 2014 Himangi Saraogi GPLv2.
+// Copyright: (C) 2017 Himanshu Jha GPLv2.
+// Copyright: (C) 2019 Quentin Young GPLv2.
+// Comments:
+// Options: --no-includes --include-headers
+//
+
+virtual context
+virtual patch
+virtual org
+virtual report
+
+@initialize:python@
+@@
+import re
+pattern = '__'
+m = re.compile(pattern)
+
+@r1 depends on context || patch@
+type T;
+@@
+
+  (T *)
+  \(XMALLOC\|XCALLOC\)(...)
+
+//----------------------------------------------------------
+//  For context mode
+//----------------------------------------------------------
+
+@script:python depends on context@
+t << r1.T;
+@@
+
+if m.search(t) != None:
+        cocci.include_match(False)
+
+@depends on context && r1@
+type r1.T;
+@@
+
+* (T *)
+  \(XMALLOC\|XCALLOC\)(...)
+
+//----------------------------------------------------------
+//  For patch mode
+//----------------------------------------------------------
+
+@script:python depends on patch@
+t << r1.T;
+@@
+
+if m.search(t) != None:
+        cocci.include_match(False)
+
+@depends on patch && r1@
+type r1.T;
+@@
+
+- (T *)
+  \(XMALLOC\|XCALLOC\)(...)
+
+//----------------------------------------------------------
+//  For org and report mode
+//----------------------------------------------------------
+
+@r2 depends on org || report@
+type T;
+position p;
+@@
+
+ (T@p *)
+  \(XMALLOC\|XCALLOC\)(...)
+
+@script:python depends on org@
+p << r2.p;
+t << r2.T;
+@@
+
+if m.search(t) != None:
+       cocci.include_match(False)
+else:
+       coccilib.org.print_safe_todo(p[0], t)
+
+@script:python depends on report@
+p << r2.p;
+t << r2.T;
+@@
+
+if m.search(t) != None:
+       cocci.include_match(False)
+else:
+       msg="WARNING: casting value returned by memory allocation function to (%s *) is useless." % (t)
+       coccilib.report.print_report(p[0], msg)
diff --git a/tools/coccinelle/array_size.cocci b/tools/coccinelle/array_size.cocci
new file mode 100644 (file)
index 0000000..f977b8a
--- /dev/null
@@ -0,0 +1,83 @@
+/// Use array_size instead of dividing sizeof array with sizeof an element
+///
+//# This makes an effort to find cases where array_size can be used such as
+//# where there is a division of sizeof the array by the sizeof its first
+//# element or by any indexed element or the element type. It replaces the
+//# division of the two sizeofs by array_size.
+//
+// Confidence: High
+// Copyright: (C) 2014 Himangi Saraogi.  GPLv2.
+// Copyright: (C) 2019 Quentin Young.  GPLv2.
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+//----------------------------------------------------------
+//  For context mode
+//----------------------------------------------------------
+
+@depends on context@
+type T;
+T[] E;
+@@
+(
+* (sizeof(E)/sizeof(*E))
+|
+* (sizeof(E)/sizeof(E[...]))
+|
+* (sizeof(E)/sizeof(T))
+)
+
+//----------------------------------------------------------
+//  For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+type T;
+T[] E;
+@@
+(
+- (sizeof(E)/sizeof(*E))
++ array_size(E)
+|
+- (sizeof(E)/sizeof(E[...]))
++ array_size(E)
+|
+- (sizeof(E)/sizeof(T))
++ array_size(E)
+)
+
+//----------------------------------------------------------
+//  For org and report mode
+//----------------------------------------------------------
+
+@r depends on (org || report)@
+type T;
+T[] E;
+position p;
+@@
+(
+ (sizeof(E)@p /sizeof(*E))
+|
+ (sizeof(E)@p /sizeof(E[...]))
+|
+ (sizeof(E)@p /sizeof(T))
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING should use array_size")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg="WARNING: Use array_size"
+coccilib.report.print_report(p[0], msg)
+
diff --git a/tools/coccinelle/badty.cocci b/tools/coccinelle/badty.cocci
new file mode 100644 (file)
index 0000000..481cf30
--- /dev/null
@@ -0,0 +1,76 @@
+/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
+///
+//# This makes an effort to find cases where the argument to sizeof is wrong
+//# in memory allocation functions by checking the type of the allocated memory
+//# when it is a double pointer and ensuring the sizeof argument takes a pointer
+//# to the the memory being allocated. There are false positives in cases the
+//# sizeof argument is not used in constructing the return value. The result
+//# may need some reformatting.
+//
+// Confidence: Moderate
+// Copyright: (C) 2014 Himangi Saraogi.  GPLv2.
+// Comments:
+// Options:
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+//----------------------------------------------------------
+//  For context mode
+//----------------------------------------------------------
+
+@depends on context disable sizeof_type_expr@
+type T;
+T **x;
+@@
+
+  x =
+  <+...sizeof(
+* T
+  )...+>
+
+//----------------------------------------------------------
+//  For patch mode
+//----------------------------------------------------------
+
+@depends on patch disable sizeof_type_expr@
+type T;
+T **x;
+@@
+
+  x =
+  <+...sizeof(
+- T
++ *x
+  )...+>
+
+//----------------------------------------------------------
+//  For org and report mode
+//----------------------------------------------------------
+
+@r depends on (org || report) disable sizeof_type_expr@
+type T;
+T **x;
+position p;
+@@
+
+  x =
+  <+...sizeof(
+  T@p
+  )...+>
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING sizeof argument should be pointer type, not structure type")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg="WARNING: Use correct pointer type argument for sizeof"
+coccilib.report.print_report(p[0], msg)
+
diff --git a/tools/coccinelle/badzero.cocci b/tools/coccinelle/badzero.cocci
new file mode 100644 (file)
index 0000000..f597c80
--- /dev/null
@@ -0,0 +1,238 @@
+/// Compare pointer-typed values to NULL rather than 0
+///
+//# This makes an effort to choose between !x and x == NULL.  !x is used
+//# if it has previously been used with the function used to initialize x.
+//# This relies on type information.  More type information can be obtained
+//# using the option -all_includes and the option -I to specify an
+//# include path.
+//
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Requires: 1.0.0
+// Options:
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@initialize:ocaml@
+@@
+let negtable = Hashtbl.create 101
+
+@depends on patch@
+expression *E;
+identifier f;
+@@
+
+(
+  (E = f(...)) ==
+- 0
++ NULL
+|
+  (E = f(...)) !=
+- 0
++ NULL
+|
+- 0
++ NULL
+  == (E = f(...))
+|
+- 0
++ NULL
+  != (E = f(...))
+)
+
+
+@t1 depends on !patch@
+expression *E;
+identifier f;
+position p;
+@@
+
+(
+  (E = f(...)) ==
+* 0@p
+|
+  (E = f(...)) !=
+* 0@p
+|
+* 0@p
+  == (E = f(...))
+|
+* 0@p
+  != (E = f(...))
+)
+
+@script:python depends on org@
+p << t1.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
+
+@script:python depends on report@
+p << t1.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
+
+// Tests of returned values
+
+@s@
+identifier f;
+expression E,E1;
+@@
+
+ E = f(...)
+ ... when != E = E1
+ !E
+
+@script:ocaml depends on s@
+f << s.f;
+@@
+
+try let _ = Hashtbl.find negtable f in ()
+with Not_found -> Hashtbl.add negtable f ()
+
+@ r disable is_zero,isnt_zero exists @
+expression *E;
+identifier f;
+@@
+
+E = f(...)
+...
+(E == 0
+|E != 0
+|0 == E
+|0 != E
+)
+
+@script:ocaml@
+f << r.f;
+@@
+
+try let _ = Hashtbl.find negtable f in ()
+with Not_found -> include_match false
+
+// This rule may lead to inconsistent path problems, if E is defined in two
+// places
+@ depends on patch disable is_zero,isnt_zero @
+expression *E;
+expression E1;
+identifier r.f;
+@@
+
+E = f(...)
+<...
+(
+- E == 0
++ !E
+|
+- E != 0
++ E
+|
+- 0 == E
++ !E
+|
+- 0 != E
++ E
+)
+...>
+?E = E1
+
+@t2 depends on !patch disable is_zero,isnt_zero @
+expression *E;
+expression E1;
+identifier r.f;
+position p1;
+position p2;
+@@
+
+E = f(...)
+<...
+(
+* E == 0@p1
+|
+* E != 0@p2
+|
+* 0@p1 == E
+|
+* 0@p1 != E
+)
+...>
+?E = E1
+
+@script:python depends on org@
+p << t2.p1;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0, suggest !E")
+
+@script:python depends on org@
+p << t2.p2;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
+
+@script:python depends on report@
+p << t2.p1;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0, suggest !E")
+
+@script:python depends on report@
+p << t2.p2;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
+
+@ depends on patch disable is_zero,isnt_zero @
+expression *E;
+@@
+
+(
+  E ==
+- 0
++ NULL
+|
+  E !=
+- 0
++ NULL
+|
+- 0
++ NULL
+  == E
+|
+- 0
++ NULL
+  != E
+)
+
+@ t3 depends on !patch disable is_zero,isnt_zero @
+expression *E;
+position p;
+@@
+
+(
+* E == 0@p
+|
+* E != 0@p
+|
+* 0@p == E
+|
+* 0@p != E
+)
+
+@script:python depends on org@
+p << t3.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
+
+@script:python depends on report@
+p << t3.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
diff --git a/tools/coccinelle/boolconv.cocci b/tools/coccinelle/boolconv.cocci
new file mode 100644 (file)
index 0000000..33c464d
--- /dev/null
@@ -0,0 +1,90 @@
+/// Remove unneeded conversion to bool
+///
+//# Relational and logical operators evaluate to bool,
+//# explicit conversion is overly verbose and unneeded.
+//
+// Copyright: (C) 2016 Andrew F. Davis <afd@ti.com> GPLv2.
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+//----------------------------------------------------------
+//  For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+expression A, B;
+symbol true, false;
+@@
+
+(
+  A == B
+|
+  A != B
+|
+  A > B
+|
+  A < B
+|
+  A >= B
+|
+  A <= B
+|
+  A && B
+|
+  A || B
+)
+- ? true : false
+
+//----------------------------------------------------------
+//  For context mode
+//----------------------------------------------------------
+
+@r depends on !patch@
+expression A, B;
+symbol true, false;
+position p;
+@@
+
+(
+  A == B
+|
+  A != B
+|
+  A > B
+|
+  A < B
+|
+  A >= B
+|
+  A <= B
+|
+  A && B
+|
+  A || B
+)
+* ? true : false@p
+
+//----------------------------------------------------------
+//  For org mode
+//----------------------------------------------------------
+
+@script:python depends on r&&org@
+p << r.p;
+@@
+
+msg = "WARNING: conversion to bool not needed here"
+coccilib.org.print_todo(p[0], msg)
+
+//----------------------------------------------------------
+//  For report mode
+//----------------------------------------------------------
+
+@script:python depends on r&&report@
+p << r.p;
+@@
+
+msg = "WARNING: conversion to bool not needed here"
+coccilib.report.print_report(p[0], msg)
diff --git a/tools/coccinelle/boolinit.cocci b/tools/coccinelle/boolinit.cocci
new file mode 100644 (file)
index 0000000..aabb581
--- /dev/null
@@ -0,0 +1,194 @@
+/// Bool initializations should use true and false.  Bool tests don't need
+/// comparisons.  Based on contributions from Joe Perches, Rusty Russell
+/// and Bruce W Allan.
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Options: --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@boolok@
+symbol true,false;
+@@
+(
+true
+|
+false
+)
+
+@depends on patch@
+bool t;
+@@
+
+(
+- t == true
++ t
+|
+- true == t
++ t
+|
+- t != true
++ !t
+|
+- true != t
++ !t
+|
+- t == false
++ !t
+|
+- false == t
++ !t
+|
+- t != false
++ t
+|
+- false != t
++ t
+)
+
+@depends on patch disable is_zero, isnt_zero@
+bool t;
+@@
+
+(
+- t == 1
++ t
+|
+- t != 1
++ !t
+|
+- t == 0
++ !t
+|
+- t != 0
++ t
+)
+
+@depends on patch && boolok@
+bool b;
+@@
+(
+ b =
+- 0
++ false
+|
+ b =
+- 1
++ true
+)
+
+// ---------------------------------------------------------------------
+
+@r1 depends on !patch@
+bool t;
+position p;
+@@
+
+(
+* t@p == true
+|
+* true == t@p
+|
+* t@p != true
+|
+* true != t@p
+|
+* t@p == false
+|
+* false == t@p
+|
+* t@p != false
+|
+* false != t@p
+)
+
+@r2 depends on !patch disable is_zero, isnt_zero@
+bool t;
+position p;
+@@
+
+(
+* t@p == 1
+|
+* t@p != 1
+|
+* t@p == 0
+|
+* t@p != 0
+)
+
+@r3 depends on !patch && boolok@
+bool b;
+position p1;
+@@
+(
+*b@p1 = 0
+|
+*b@p1 = 1
+)
+
+@r4 depends on !patch@
+bool b;
+position p2;
+identifier i;
+constant c != {0,1};
+@@
+(
+ b = i
+|
+*b@p2 = c
+)
+
+@script:python depends on org@
+p << r1.p;
+@@
+
+cocci.print_main("WARNING: Comparison to bool",p)
+
+@script:python depends on org@
+p << r2.p;
+@@
+
+cocci.print_main("WARNING: Comparison of 0/1 to bool variable",p)
+
+@script:python depends on org@
+p1 << r3.p1;
+@@
+
+cocci.print_main("WARNING: Assignment of 0/1 to bool variable",p1)
+
+@script:python depends on org@
+p2 << r4.p2;
+@@
+
+cocci.print_main("ERROR: Assignment of non-0/1 constant to bool variable",p2)
+
+@script:python depends on report@
+p << r1.p;
+@@
+
+coccilib.report.print_report(p[0],"WARNING: Comparison to bool")
+
+@script:python depends on report@
+p << r2.p;
+@@
+
+coccilib.report.print_report(p[0],"WARNING: Comparison of 0/1 to bool variable")
+
+@script:python depends on report@
+p1 << r3.p1;
+@@
+
+coccilib.report.print_report(p1[0],"WARNING: Assignment of 0/1 to bool variable")
+
+@script:python depends on report@
+p2 << r4.p2;
+@@
+
+coccilib.report.print_report(p2[0],"ERROR: Assignment of non-0/1 constant to bool variable")
diff --git a/tools/coccinelle/boolreturn.cocci b/tools/coccinelle/boolreturn.cocci
new file mode 100644 (file)
index 0000000..29d2bf4
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/// Return statements in functions returning bool should use
+/// true/false instead of 1/0.
+//
+// Confidence: High
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual report
+virtual context
+
+@r1 depends on patch@
+identifier fn;
+typedef bool;
+symbol false;
+symbol true;
+@@
+
+bool fn ( ... )
+{
+<...
+return
+(
+- 0
++ false
+|
+- 1
++ true
+)
+  ;
+...>
+}
+
+@r2 depends on report || context@
+identifier fn;
+position p;
+@@
+
+bool fn ( ... )
+{
+<...
+return
+(
+* 0@p
+|
+* 1@p
+)
+  ;
+...>
+}
+
+
+@script:python depends on report@
+p << r2.p;
+fn << r2.fn;
+@@
+
+msg = "WARNING: return of 0/1 in function '%s' with return type bool" % fn
+coccilib.report.print_report(p[0], msg)
diff --git a/tools/coccinelle/cond_no_effect.cocci b/tools/coccinelle/cond_no_effect.cocci
new file mode 100644 (file)
index 0000000..8467dbd
--- /dev/null
@@ -0,0 +1,64 @@
+///Find conditions where if and else branch are functionally
+// identical.
+//
+// There can be false positives in cases where the positional
+// information is used (as with lockdep) or where the identity
+// is a placeholder for not yet handled cases.
+// Unfortunately there also seems to be a tendency to use
+// the last if else/else as a "default behavior" - which some
+// might consider a legitimate coding pattern. From discussion
+// on kernelnewbies though it seems that this is not really an
+// accepted pattern and if at all it would need to be commented
+//
+// In the Linux kernel it does not seem to actually report
+// false positives except for those that were documented as
+// being intentional.
+// the two known cases are:
+//   arch/sh/kernel/traps_64.c:read_opcode()
+//        } else if ((pc & 1) == 0) {
+//              /* SHcompact */
+//              /* TODO : provide handling for this.  We don't really support
+//                 user-mode SHcompact yet, and for a kernel fault, this would
+//                 have to come from a module built for SHcompact.  */
+//              return -EFAULT;
+//      } else {
+//              /* misaligned */
+//              return -EFAULT;
+//      }
+//   fs/kernfs/file.c:kernfs_fop_open()
+//       * Both paths of the branch look the same.  They're supposed to
+//       * look that way and give @of->mutex different static lockdep keys.
+//       */
+//      if (has_mmap)
+//              mutex_init(&of->mutex);
+//      else
+//              mutex_init(&of->mutex);
+//
+// All other cases look like bugs or at least lack of documentation
+//
+// Confidence: Moderate
+// Copyright: (C) 2016 Nicholas Mc Guire, OSADL.  GPLv2.
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@cond@
+statement S1;
+position p;
+@@
+
+* if@p (...) S1 else S1
+
+@script:python depends on org@
+p << cond.p;
+@@
+
+cocci.print_main("WARNING: possible condition with no effect (if == else)",p)
+
+@script:python depends on report@
+p << cond.p;
+@@
+
+coccilib.report.print_report(p[0],"WARNING: possible condition with no effect (if == else)")
diff --git a/tools/coccinelle/deref_null.cocci b/tools/coccinelle/deref_null.cocci
new file mode 100644 (file)
index 0000000..cbc6184
--- /dev/null
@@ -0,0 +1,282 @@
+///
+/// A variable is dereferenced under a NULL test.
+/// Even though it is known to be NULL.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: -I ... -all_includes can give more complete results
+// Options:
+
+virtual context
+virtual org
+virtual report
+
+// The following two rules are separate, because both can match a single
+// expression in different ways
+@pr1 expression@
+expression E;
+identifier f;
+position p1;
+@@
+
+ (E != NULL && ...) ? <+...E->f@p1...+> : ...
+
+@pr2 expression@
+expression E;
+identifier f;
+position p2;
+@@
+
+(
+  (E != NULL) && ... && <+...E->f@p2...+>
+|
+  (E == NULL) || ... || <+...E->f@p2...+>
+|
+ sizeof(<+...E->f@p2...+>)
+)
+
+@ifm@
+expression *E;
+statement S1,S2;
+position p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...) S1 else S2
+
+// For org and report modes
+
+@r depends on !context && (org || report) exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+  ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ E->f@p // bad use
+)
+  ... when any
+  return ...;
+}
+else S3
+
+@script:python depends on !context && !org && report@
+p << r.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+coccilib.report.print_report(p[0], msg)
+cocci.include_match(False)
+
+@script:python depends on !context && org && !report@
+p << r.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+cocci.print_main(msg_safe,p)
+cocci.include_match(False)
+
+@s depends on !context && (org || report) exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+  ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ E->f@p // bad use
+)
+  ... when any
+}
+else S3
+
+@script:python depends on !context && !org && report@
+p << s.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+coccilib.report.print_report(p[0], msg)
+
+@script:python depends on !context && org && !report@
+p << s.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+cocci.print_main(msg_safe,p)
+
+// For context mode
+
+@depends on context && !org && !report exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+  ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+* E->f@p // bad use
+)
+  ... when any
+  return ...;
+}
+else S3
+
+// The following three rules are duplicates of ifm, pr1 and pr2 respectively.
+// It is need because the previous rule as already made a "change".
+
+@pr11 depends on context && !org && !report expression@
+expression E;
+identifier f;
+position p1;
+@@
+
+ (E != NULL && ...) ? <+...E->f@p1...+> : ...
+
+@pr12 depends on context && !org && !report expression@
+expression E;
+identifier f;
+position p2;
+@@
+
+(
+  (E != NULL) && ... && <+...E->f@p2...+>
+|
+  (E == NULL) || ... || <+...E->f@p2...+>
+|
+ sizeof(<+...E->f@p2...+>)
+)
+
+@ifm1 depends on context && !org && !report@
+expression *E;
+statement S1,S2;
+position p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...) S1 else S2
+
+@depends on context && !org && !report exists@
+expression subE <= ifm1.E;
+expression *ifm1.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr11.p1,pr12.p2};
+position ifm1.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+  ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+* E->f@p // bad use
+)
+  ... when any
+}
+else S3
diff --git a/tools/coccinelle/double_lock.cocci b/tools/coccinelle/double_lock.cocci
new file mode 100644 (file)
index 0000000..002752f
--- /dev/null
@@ -0,0 +1,92 @@
+/// Find double locks.  False positives may occur when some paths cannot
+/// occur at execution, due to the values of variables, and when there is
+/// an intervening function call that releases the lock.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@locked@
+position p1;
+expression E1;
+position p;
+@@
+
+(
+mutex_lock@p1
+|
+mutex_trylock@p1
+|
+spin_lock@p1
+|
+spin_trylock@p1
+|
+read_lock@p1
+|
+read_trylock@p1
+|
+write_lock@p1
+|
+write_trylock@p1
+) (E1@p,...);
+
+@balanced@
+position p1 != locked.p1;
+position locked.p;
+identifier lock,unlock;
+expression x <= locked.E1;
+expression E,locked.E1;
+expression E2;
+@@
+
+if (E) {
+ <+... when != E1
+ lock(E1@p,...)
+ ...+>
+}
+... when != E1
+    when != \(x = E2\|&x\)
+    when forall
+if (E) {
+ <+... when != E1
+ unlock@p1(E1,...)
+ ...+>
+}
+
+@r depends on !balanced exists@
+expression x <= locked.E1;
+expression locked.E1;
+expression E2;
+identifier lock;
+position locked.p,p1,p2;
+@@
+
+lock@p1 (E1@p,...);
+... when != E1
+    when != \(x = E2\|&x\)
+lock@p2 (E1,...);
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+lock << r.lock;
+@@
+
+cocci.print_main(lock,p1)
+cocci.print_secs("second lock",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+lock << r.lock;
+@@
+
+msg = "second lock on line %s" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/tools/coccinelle/doublebitand.cocci b/tools/coccinelle/doublebitand.cocci
new file mode 100644 (file)
index 0000000..72f1572
--- /dev/null
@@ -0,0 +1,54 @@
+/// Find bit operations that include the same argument more than once
+//# One source of false positives is when the argument performs a side
+//# effect.  Another source of false positives is when a neutral value
+//# such as 0 for | is used to indicate no information, to maintain the
+//# same structure as other similar expressions
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual context
+virtual org
+virtual report
+
+@r expression@
+expression E;
+position p;
+@@
+
+(
+*        E@p
+         & ... & E
+|
+*        E@p
+         | ... | E
+|
+*        E@p
+         & ... & !E
+|
+*        E@p
+         | ... | !E
+|
+*        !E@p
+         & ... & E
+|
+*        !E@p
+         | ... | E
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("duplicated argument to & or |",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0],"duplicated argument to & or |")
diff --git a/tools/coccinelle/doubleinit.cocci b/tools/coccinelle/doubleinit.cocci
new file mode 100644 (file)
index 0000000..c0c3371
--- /dev/null
@@ -0,0 +1,53 @@
+/// Find duplicate field initializations.  This has a high rate of false
+/// positives due to #ifdefs, which Coccinelle is not aware of in a structure
+/// initialization.
+///
+// Confidence: Low
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@r@
+identifier I, s, fld;
+position p0,p;
+expression E;
+@@
+
+struct I s =@p0 { ..., .fld@p = E, ...};
+
+@s@
+identifier I, s, r.fld;
+position r.p0,p;
+expression E;
+@@
+
+struct I s =@p0 { ..., .fld@p = E, ...};
+
+@script:python depends on org@
+p0 << r.p0;
+fld << r.fld;
+ps << s.p;
+pr << r.p;
+@@
+
+if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
+  cocci.print_main(fld,p0)
+  cocci.print_secs("s",ps)
+  cocci.print_secs("r",pr)
+
+@script:python depends on report@
+p0 << r.p0;
+fld << r.fld;
+ps << s.p;
+pr << r.p;
+@@
+
+if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
+  msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line)
+  coccilib.report.print_report(p0[0],msg)
diff --git a/tools/coccinelle/doubletest.cocci b/tools/coccinelle/doubletest.cocci
new file mode 100644 (file)
index 0000000..7af2ce7
--- /dev/null
@@ -0,0 +1,58 @@
+/// Find &&/|| operations that include the same argument more than once
+//# A common source of false positives is when the expression, or
+//# another expresssion in the same && or || operation, performs a
+//# side effect.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU.  GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU.  GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual context
+virtual org
+virtual report
+
+@r expression@
+expression E;
+position p;
+@@
+
+(
+ E@p || ... || E
+|
+ E@p && ... && E
+)
+
+@bad@
+expression r.E,e1,e2,fn;
+position r.p;
+assignment operator op;
+@@
+
+(
+E@p
+&
+ <+... \(fn(...)\|e1 op e2\|e1++\|e1--\|++e1\|--e1\) ...+>
+)
+
+@depends on context && !bad@
+expression r.E;
+position r.p;
+@@
+
+*E@p
+
+@script:python depends on org && !bad@
+p << r.p;
+@@
+
+cocci.print_main("duplicated argument to && or ||",p)
+
+@script:python depends on report && !bad@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0],"duplicated argument to && or ||")
diff --git a/tools/coccinelle/ifaddr.cocci b/tools/coccinelle/ifaddr.cocci
new file mode 100644 (file)
index 0000000..c2663c6
--- /dev/null
@@ -0,0 +1,34 @@
+/// The address of a variable or field is likely always to be non-zero.
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+virtual context
+
+@r@
+expression x;
+statement S1,S2;
+position p;
+@@
+
+*if@p (&x)
+ S1 else S2
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("test of a variable/field address",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "ERROR: test of a variable/field address"
+coccilib.report.print_report(p[0],msg)
diff --git a/tools/coccinelle/ifnullxfree.cocci b/tools/coccinelle/ifnullxfree.cocci
new file mode 100644 (file)
index 0000000..85fc23e
--- /dev/null
@@ -0,0 +1,15 @@
+/// NULL check before some freeing functions is not needed.
+///
+// Copyright: (C) 2014 Fabian Frederick.  GPLv2.
+// Copyright: (C) 2019 Quentin Young.  GPLv2.
+// Comments: -
+// Options: --no-includes --include-headers
+
+virtual patch
+
+@r2 depends on patch@
+expression E;
+expression Y;
+@@
+- if (E != NULL)
+XFREE(Y, E);
diff --git a/tools/coccinelle/itnull.cocci b/tools/coccinelle/itnull.cocci
new file mode 100644 (file)
index 0000000..f58732b
--- /dev/null
@@ -0,0 +1,94 @@
+/// Many iterators have the property that the first argument is always bound
+/// to a real list element, never NULL.
+//# False positives arise for some iterators that do not have this property,
+//# or in cases when the loop cursor is reassigned.  The latter should only
+//# happen when the matched code is on the way to a loop exit (break, goto,
+//# or return).
+///
+// Confidence: Moderate
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@depends on patch@
+iterator I;
+expression x,E,E1,E2;
+statement S,S1,S2;
+@@
+
+I(x,...) { <...
+(
+- if (x == NULL && ...) S
+|
+- if (x != NULL || ...)
+  S
+|
+- (x == NULL) ||
+  E
+|
+- (x != NULL) &&
+  E
+|
+- (x == NULL && ...) ? E1 :
+  E2
+|
+- (x != NULL || ...) ?
+  E1
+- : E2
+|
+- if (x == NULL && ...) S1 else
+  S2
+|
+- if (x != NULL || ...)
+  S1
+- else S2
+|
++ BAD(
+  x == NULL
++ )
+|
++ BAD(
+  x != NULL
++ )
+)
+  ...> }
+
+@r depends on !patch exists@
+iterator I;
+expression x,E;
+position p1,p2;
+@@
+
+*I@p1(x,...)
+{ ... when != x = E
+(
+*  x@p2 == NULL
+|
+*  x@p2 != NULL
+)
+  ... when any
+}
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("iterator-bound variable",p1)
+cocci.print_secs("useless NULL test",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
diff --git a/tools/coccinelle/mini_lock.cocci b/tools/coccinelle/mini_lock.cocci
new file mode 100644 (file)
index 0000000..19c6ee5
--- /dev/null
@@ -0,0 +1,98 @@
+/// Find missing unlocks.  This semantic match considers the specific case
+/// where the unlock is missing from an if branch, and there is a lock
+/// before the if and an unlock after the if.  False positives are due to
+/// cases where the if branch represents a case where the function is
+/// supposed to exit with the lock held, or where there is some preceding
+/// function call that releases the lock.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual context
+virtual org
+virtual report
+
+@prelocked@
+position p1,p;
+expression E1;
+@@
+
+(
+mutex_lock@p1
+|
+mutex_trylock@p1
+|
+spin_lock@p1
+|
+spin_trylock@p1
+|
+read_lock@p1
+|
+read_trylock@p1
+|
+write_lock@p1
+|
+write_trylock@p1
+|
+read_lock_irq@p1
+|
+write_lock_irq@p1
+|
+read_lock_irqsave@p1
+|
+write_lock_irqsave@p1
+|
+spin_lock_irq@p1
+|
+spin_lock_irqsave@p1
+) (E1@p,...);
+
+@looped@
+position r;
+@@
+
+for(...;...;...) { <+... return@r ...; ...+> }
+
+@err exists@
+expression E1;
+position prelocked.p;
+position up != prelocked.p1;
+position r!=looped.r;
+identifier lock,unlock;
+@@
+
+*lock(E1@p,...);
+... when != E1
+    when any
+if (...) {
+  ... when != E1
+*  return@r ...;
+}
+... when != E1
+    when any
+*unlock@up(E1,...);
+
+@script:python depends on org@
+p << prelocked.p1;
+lock << err.lock;
+unlock << err.unlock;
+p2 << err.r;
+@@
+
+cocci.print_main(lock,p)
+cocci.print_secs(unlock,p2)
+
+@script:python depends on report@
+p << prelocked.p1;
+lock << err.lock;
+unlock << err.unlock;
+p2 << err.r;
+@@
+
+msg = "preceding lock on line %s" % (p[0].line)
+coccilib.report.print_report(p2[0],msg)
diff --git a/tools/coccinelle/noderef.cocci b/tools/coccinelle/noderef.cocci
new file mode 100644 (file)
index 0000000..ca289d5
--- /dev/null
@@ -0,0 +1,81 @@
+/// sizeof when applied to a pointer typed expression gives the size of
+/// the pointer
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+virtual context
+virtual patch
+
+@depends on patch@
+expression *x;
+expression f;
+expression i;
+type T;
+@@
+
+(
+x = <+... sizeof(
+- x
++ *x
+   ) ...+>
+|
+f(...,(T)(x),...,sizeof(
+- x
++ *x
+   ),...)
+|
+f(...,sizeof(
+- x
++ *x
+   ),...,(T)(x),...)
+|
+f(...,(T)(x),...,i*sizeof(
+- x
++ *x
+   ),...)
+|
+f(...,i*sizeof(
+- x
++ *x
+   ),...,(T)(x),...)
+)
+
+@r depends on !patch@
+expression *x;
+expression f;
+expression i;
+position p;
+type T;
+@@
+
+(
+*x = <+... sizeof@p(x) ...+>
+|
+*f(...,(T)(x),...,sizeof@p(x),...)
+|
+*f(...,sizeof@p(x),...,(T)(x),...)
+|
+*f(...,(T)(x),...,i*sizeof@p(x),...)
+|
+*f(...,i*sizeof@p(x),...,(T)(x),...)
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("application of sizeof to pointer",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "ERROR: application of sizeof to pointer"
+coccilib.report.print_report(p[0],msg)<Paste>
diff --git a/tools/coccinelle/replace-strncpy.cocci b/tools/coccinelle/replace-strncpy.cocci
new file mode 100644 (file)
index 0000000..18ff131
--- /dev/null
@@ -0,0 +1,8 @@
+@@
+type T;
+T[] E;
+expression buf, srclen;
+@@
+
+- strncpy(E, src, srclen)
++ strlcpy(E, src, sizeof(E))
diff --git a/tools/coccinelle/returnvar.cocci b/tools/coccinelle/returnvar.cocci
new file mode 100644 (file)
index 0000000..d8286ef
--- /dev/null
@@ -0,0 +1,66 @@
+///
+/// Remove unneeded variable used to store return value.
+///
+// Confidence: Moderate
+// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: Comments on code can be deleted if near code that is removed.
+//           "when strict" can be removed to get more hits, but adds false
+//           positives
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual report
+virtual context
+virtual org
+
+@depends on patch@
+type T;
+constant C;
+identifier ret;
+@@
+- T ret = C;
+... when != ret
+    when strict
+return
+- ret
++ C
+;
+
+@depends on context@
+type T;
+constant C;
+identifier ret;
+@@
+* T ret = C;
+... when != ret
+    when strict
+* return ret;
+
+@r1 depends on report || org@
+type T;
+constant C;
+identifier ret;
+position p1, p2;
+@@
+T ret@p1 = C;
+... when != ret
+    when strict
+return ret@p2;
+
+@script:python depends on report@
+p1 << r1.p1;
+p2 << r1.p2;
+C << r1.C;
+ret << r1.ret;
+@@
+coccilib.report.print_report(p1[0], "Unneeded variable: \"" + ret + "\". Return \"" + C + "\" on line " + p2[0].line)
+
+@script:python depends on org@
+p1 << r1.p1;
+p2 << r1.p2;
+C << r1.C;
+ret << r1.ret;
+@@
+cocci.print_main("unneeded \"" + ret + "\" variable", p1)
+cocci.print_sec("return " + C + " here", p2)
diff --git a/tools/coccinelle/semicolon.cocci b/tools/coccinelle/semicolon.cocci
new file mode 100644 (file)
index 0000000..6740c65
--- /dev/null
@@ -0,0 +1,83 @@
+///
+/// Remove unneeded semicolon.
+///
+// Confidence: Moderate
+// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: Some false positives on empty default cases in switch statements.
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual report
+virtual context
+virtual org
+
+@r_default@
+position p;
+@@
+switch (...)
+{
+default: ...;@p
+}
+
+@r_case@
+position p;
+@@
+(
+switch (...)
+{
+case ...:;@p
+}
+|
+switch (...)
+{
+case ...:...
+case ...:;@p
+}
+|
+switch (...)
+{
+case ...:...
+case ...:
+case ...:;@p
+}
+)
+
+@r1@
+statement S;
+position p1;
+position p != {r_default.p, r_case.p};
+identifier label;
+@@
+(
+label:;
+|
+S@p1;@p
+)
+
+@script:python@
+p << r1.p;
+p1 << r1.p1;
+@@
+if p[0].line != p1[0].line_end:
+       cocci.include_match(False)
+
+@depends on patch@
+position r1.p;
+@@
+-;@p
+
+@script:python depends on report@
+p << r1.p;
+@@
+coccilib.report.print_report(p[0],"Unneeded semicolon")
+
+@depends on context@
+position r1.p;
+@@
+*;@p
+
+@script:python depends on org@
+p << r1.p;
+@@
+cocci.print_main("Unneeded semicolon",p)
diff --git a/tools/coccinelle/strncpy_truncation.cocci b/tools/coccinelle/strncpy_truncation.cocci
new file mode 100644 (file)
index 0000000..28b5c2a
--- /dev/null
@@ -0,0 +1,41 @@
+/// Use strlcpy rather than strncpy(dest,..,sz) + dest[sz-1] = '\0'
+///
+// Confidence: High
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual context
+virtual report
+virtual org
+
+@r@
+expression dest, src, sz;
+position p;
+@@
+
+strncpy@p(dest, src, sz);
+dest[sz - 1] = '\0';
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("strncpy followed by truncation can be strlcpy",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "SUGGESTION: strncpy followed by truncation can be strlcpy"
+coccilib.report.print_report(p[0],msg)
+
+@ok depends on patch@
+expression r.dest, r.src, r.sz;
+position r.p;
+@@
+
+-strncpy@p(
++strlcpy(
+  dest, src, sz);
+-dest[sz - 1] = '\0';
diff --git a/tools/coccinelle/unsigned_lesser_than_zero.cocci b/tools/coccinelle/unsigned_lesser_than_zero.cocci
new file mode 100644 (file)
index 0000000..8fa5a3c
--- /dev/null
@@ -0,0 +1,75 @@
+/// Unsigned expressions cannot be lesser than zero. Presence of
+/// comparisons 'unsigned (<|<=|>|>=) 0' often indicates a bug,
+/// usually wrong type of variable.
+///
+/// To reduce number of false positives following tests have been added:
+/// - parts of range checks are skipped, eg. "if (u < 0 || u > 15) ...",
+///   developers prefer to keep such code,
+/// - comparisons "<= 0" and "> 0" are performed only on results of
+///   signed functions/macros,
+/// - hardcoded list of signed functions/macros with always non-negative
+///   result is used to avoid false positives difficult to detect by other ways
+///
+// Confidence: Average
+// Copyright: (C) 2015 Andrzej Hajda, Samsung Electronics Co., Ltd. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Options: --all-includes
+
+virtual context
+virtual org
+virtual report
+
+@r_cmp@
+position p;
+typedef bool, u8, u16, u32, u64;
+{unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long,
+       size_t, bool, u8, u16, u32, u64} v;
+expression e;
+@@
+
+       \( v = e \| &v \)
+       ...
+       (\( v@p < 0 \| v@p <= 0 \| v@p >= 0 \| v@p > 0 \))
+
+@r@
+position r_cmp.p;
+typedef s8, s16, s32, s64;
+{char, short, int, long, long long, ssize_t, s8, s16, s32, s64} vs;
+expression c, e, v;
+identifier f !~ "^(ata_id_queue_depth|btrfs_copy_from_user|dma_map_sg|dma_map_sg_attrs|fls|fls64|gameport_time|get_write_extents|nla_len|ntoh24|of_flat_dt_match|of_get_child_count|uart_circ_chars_pending|[A-Z0-9_]+)$";
+@@
+
+(
+       v = f(...)@vs;
+       ... when != v = e;
+*      (\( v@p <=@e 0 \| v@p >@e 0 \))
+       ... when any
+|
+(
+       (\( v@p < 0 \| v@p <= 0 \)) || ... || (\( v >= c \| v > c \))
+|
+       (\( v >= c \| v > c \)) || ... || (\( v@p < 0 \| v@p <= 0 \))
+|
+       (\( v@p >= 0 \| v@p > 0 \)) && ... && (\( v < c \| v <= c \))
+|
+       ((\( v < c \| v <= c \) && ... && \( v@p >= 0 \| v@p > 0 \)))
+|
+*      (\( v@p <@e 0 \| v@p >=@e 0 \))
+)
+)
+
+@script:python depends on org@
+p << r_cmp.p;
+e << r.e;
+@@
+
+msg = "WARNING: Unsigned expression compared with zero: %s" % (e)
+coccilib.org.print_todo(p[0], msg)
+
+@script:python depends on report@
+p << r_cmp.p;
+e << r.e;
+@@
+
+msg = "WARNING: Unsigned expression compared with zero: %s" % (e)
+coccilib.report.print_report(p[0], msg)
diff --git a/tools/coccinelle/vty_check.cocci b/tools/coccinelle/vty_check.cocci
new file mode 100644 (file)
index 0000000..7e5fcc4
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * VTY_DECLVAR_CONTEXT contains a built-in "if (!var) return;"
+ */
+@@
+identifier var, typ;
+statement S;
+@@
+
+  {
+    ...
+  \(
+    VTY_DECLVAR_CONTEXT(typ, var);
+  \|
+    VTY_DECLVAR_CONTEXT_SUB(typ, var);
+  \)
+    ...
+-   if (
+-         \(  !var  \|  var == NULL \)
+-      )
+-      S
+    ...
+  }
diff --git a/tools/coccinelle/vty_index.cocci b/tools/coccinelle/vty_index.cocci
new file mode 100644 (file)
index 0000000..eabbaa1
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * prep: strip off casts, they cause things to fail matching later.
+ */
+
+@@
+identifier casttarget;
+symbol vty;
+@@
+
+- (struct casttarget *)vty->index
++ vty->index
+
+/*
+ * variant 1:  local variable assigned from vty->index
+ */
+
+@@
+identifier sn, nn;
+identifier fn;
+@@
+
+  int fn(...)
+  {
++ VTY_DECLVAR_CONTEXT (sn, nn);
+  ...
+  \(
+-   struct sn *nn;
+    ...
+-   nn = vty->index;
+  \|
+-   struct sn *nn = vty->index;
+  \|
+-   struct sn *nn = vty->index;
+    ...
+-   nn = vty->index;
+  \)
+  ...
+  }
+
+@@
+identifier sn, nn;
+identifier fn;
+type Tr;
+@@
+
+  Tr *fn(...)
+  {
++   struct sn *nn = VTY_GET_CONTEXT(sn);
+  ...
+  \(
+-   struct sn *nn;
+    ...
+-   nn = vty->index;
++   if (!nn) {
++     return NULL;
++   }
+  \|
+-   struct sn *nn = vty->index;
++   if (!nn) {
++     return NULL;
++   }
+  \|
+-   struct sn *nn = vty->index;
+    ...
+-   nn = vty->index;
++   if (!nn) {
++     return NULL;
++   }
+  \)
+  ...
+  }
+
+/*
+ * variant 2:  vty wrapper func with (vty, vty->index, ...) signature
+ */
+
+/* find calls of this pattern first; arg will be dropped in rule3 */
+@rule1@
+identifier fn !~ "generic_(set|match)_";
+expression arg;
+@@
+ fn(arg, arg->index, ...)
+
+@ script:python @
+fn << rule1.fn;
+arg << rule1.arg;
+@@
+print "R01 removing vty-index argument on %s(%s, ...)" % (fn, arg)
+
+#/* strip arg on the vty wrapper func, add local handling */
+@ rule2 @
+identifier rule1.fn;
+identifier arg;
+identifier T;
+@@
+
+  static int fn (struct vty *vty,
+-                struct T * arg,
+                 ...)
+  {
++   VTY_DECLVAR_CONTEXT (T, arg);
+    ...
+  }
+
+/* drop argument on call sites identified earlier */
+@ rule3 @
+identifier rule1.fn;
+expression arg;
+@@
+
+  fn(arg,
+-    arg->index,
+     ...)
+
+
+/*
+ * variant 3:  function calls with "vty->index" argument (but no vty)
+ *
+ * a bit more complicated since we need to find the type from the header.
+ */
+
+/* find call sites first
+ * remember function name for later declvar insertion
+ */
+@ rule11 exists@
+identifier fn;
+identifier fparent;
+type Tr;
+@@
+  Tr fparent (...)
+  {
+    ...
+    fn(vty->index, ...)
+    ...
+  }
+
+@ script:python @
+fn << rule11.fn;
+@@
+print "R11 removing vty-index argument on %s(...)" % (fn)
+
+#/* find type of the argument - note args are mostly unnamed in FRR :( */
+@ rule12 @
+identifier rule11.fn;
+identifier T, argname;
+type Tr;
+@@
+
+(
+  Tr fn(struct T *, ...);
+|
+  Tr fn(struct T * argname, ...);
+)
+
+@ script:python @
+fn << rule11.fn;
+T << rule12.T;
+@@
+print "R12 removing vty-index type is %s for %s(...)" % (T, fn)
+
+#/* add declvar
+# * this is split from rule14 so we support multiple calls in one func */
+@ rule13a @
+identifier rule11.fparent;
+identifier rule12.T;
+@@
+
+  int fparent (...)
+  {
++   VTY_DECLVAR_CONTEXT(T, T);
+    ...
+  }
+
+@ rule13b @
+identifier rule11.fparent;
+identifier rule12.T;
+type Tr;
+@@
+
+  Tr *fparent (...)
+  {
++   struct T *T = VTY_GET_CONTEXT(T);
++   if (!T) {
++     return NULL;
++   }
+    ...
+  }
+
+/* now replace the argument in the call */
+@ rule14 exists @
+identifier rule11.fn;
+identifier rule12.T;
+@@
+
+  {
+    ...
+    \(
+    fn(
+-       vty->index,
++       T,
+        ...)
+    \|
+    fn(
+-       vty->index
++       T
+        )
+    \)
+    ...
+  }
+
+/* special case ... */
+@rule30@
+identifier fn =~ "generic_(set|match)_";
+expression arg;
+@@
+  fn(arg,
+-    arg->index,
++    VTY_GET_CONTEXT(route_map_index),
+     ...)
+
+/* and finally - PUSH_CONTEXT */
+@ rule99a exists @
+identifier tnode;
+identifier vexpr =~ "NULL";
+@@
+
+- vty->node = tnode;
+  ...
+- vty->index = vexpr;
++ VTY_PUSH_CONTEXT_NULL(tnode);
+
+@ rule99b exists @
+identifier tnode;
+expression vexpr;
+@@
+
+- vty->node = tnode;
+  ...
+- vty->index = vexpr;
++ VTY_PUSH_CONTEXT(tnode, vexpr);
+
diff --git a/tools/coccinelle/xcalloc-simple.cocci b/tools/coccinelle/xcalloc-simple.cocci
new file mode 100644 (file)
index 0000000..5be4daf
--- /dev/null
@@ -0,0 +1,52 @@
+///
+/// Use zeroing allocator rather than allocator followed by memset with 0
+///
+/// This considers some simple cases that are common and easy to validate
+/// Note in particular that there are no ...s in the rule, so all of the
+/// matched code has to be contiguous
+///
+// Confidence: High
+// Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU.  GPLv2.
+// Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2017 Himanshu Jha GPLv2.
+// Copyright: (C) 2019 Quentin Young.  GPLv2.
+// URL: http://coccinelle.lip6.fr/rules/kzalloc.html
+// Options: --no-includes --include-headers
+//
+// Keywords: XMALLOC, XCALLOC
+// Version min: < 2.6.12 kmalloc
+// Version min:   2.6.14 kzalloc
+//
+
+virtual context
+virtual patch
+
+//----------------------------------------------------------
+//  For context mode
+//----------------------------------------------------------
+
+@depends on context@
+type T, T2;
+expression x;
+expression E1;
+expression t;
+@@
+
+* x = (T)XMALLOC(t, E1);
+* memset((T2)x,0,E1);
+
+//----------------------------------------------------------
+//  For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+type T, T2;
+expression x;
+expression E1;
+expression t;
+@@
+
+- x = (T)XMALLOC(t, E1);
++ x = (T)XCALLOC(t, E1);
+- memset((T2)x,0,E1);
+
diff --git a/tools/coccinelle/xfree.cocci b/tools/coccinelle/xfree.cocci
new file mode 100644 (file)
index 0000000..eb38f0d
--- /dev/null
@@ -0,0 +1,122 @@
+/// Find a use after free.
+//# Values of variables may imply that some
+//# execution paths are not possible, resulting in false positives.
+//# Another source of false positives are macros such as
+//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
+///
+// Confidence: Moderate
+// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
+// Copyright: (C) 2019 Quentin Young.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@free@
+expression E, t;
+position p1;
+@@
+
+* XFREE@p1(t, E)
+
+@print expression@
+constant char [] c;
+expression free.E,E2;
+type T;
+position p;
+identifier f;
+@@
+
+(
+ f(...,c,...,(T)E@p,...)
+|
+ E@p == E2
+|
+ E@p != E2
+|
+ E2 == E@p
+|
+ E2 != E@p
+|
+ !E@p
+|
+ E@p || ...
+)
+
+@sz@
+expression free.E;
+position p;
+@@
+
+ sizeof(<+...E@p...+>)
+
+@loop exists@
+expression E, t;
+identifier l;
+position ok;
+@@
+
+while (1) { ...
+* XFREE@ok(t, E)
+  ... when != break;
+      when != goto l;
+      when forall
+}
+
+@r exists@
+expression free.E, subE<=free.E, E2;
+expression E1;
+iterator iter;
+statement S;
+position free.p1!=loop.ok,p2!={print.p,sz.p};
+@@
+
+* XFREE@p1(t, E)
+...
+(
+ iter(...,subE,...) S // no use
+|
+ list_remove_head(E1,subE,...)
+|
+ subE = E2
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ BUG(...)
+|
+ BUG_ON(...)
+|
+ return_VALUE(...)
+|
+ return_ACPI_STATUS(...)
+|
+ E@p2 // bad use
+)
+
+@script:python depends on org@
+p1 << free.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("kfree",p1)
+cocci.print_secs("ref",p2)
+
+@script:python depends on report@
+p1 << free.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
+coccilib.report.print_report(p2[0],msg)
diff --git a/tools/coccinelle/xfreeaddr.cocci b/tools/coccinelle/xfreeaddr.cocci
new file mode 100644 (file)
index 0000000..c99c7ac
--- /dev/null
@@ -0,0 +1,33 @@
+/// Free of a structure field
+///
+// Confidence: High
+// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6.  GPLv2.
+// Copyright: (C) 2019 Quentin Young.  GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+virtual context
+
+@r depends on context || report || org @
+expression e, t;
+identifier f;
+position p;
+@@
+
+* XFREE@p(t, &e->f)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("XFREE",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "ERROR: invalid free of structure field"
+coccilib.report.print_report(p[0],msg)
diff --git a/tools/coccinelle/xmalloc_returnval.cocci b/tools/coccinelle/xmalloc_returnval.cocci
new file mode 100644 (file)
index 0000000..8e0ad10
--- /dev/null
@@ -0,0 +1,37 @@
+/// XMALLOC, XCALLOC etc either return non-null, or abort the program.
+/// Never nullcheck these.
+//
+// Copyright: (C) 2019 Quentin Young.  GPLv2.
+
+virtual patch
+
+//----------------------------------------------------------
+//  For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+identifier alloc;
+@@
+
+alloc = XMALLOC(...);
+
+...
+
+- if (alloc == NULL)
+- {
+- ...
+- }
+
+@depends on patch@
+identifier alloc;
+@@
+
+alloc = XCALLOC(...);
+
+...
+
+- if (alloc == NULL)
+- {
+- ...
+- }
+
diff --git a/tools/coccinelle/zprivs.cocci b/tools/coccinelle/zprivs.cocci
new file mode 100644 (file)
index 0000000..76d13c3
--- /dev/null
@@ -0,0 +1,76 @@
+@@
+identifier change;
+identifier end;
+expression E, f, g;
+iterator name frr_elevate_privs;
+@@
+
+- if (E.change(ZPRIVS_RAISE))
+-   f;
++ frr_elevate_privs(&E) {
+  <+...
+-   goto end;
++   break;
+  ...+>
+- end:
+- if (E.change(ZPRIVS_LOWER))
+-   g;
++ }
+
+@@
+identifier change, errno, safe_strerror, exit;
+expression E, f1, f2, f3, ret, fn;
+iterator name frr_elevate_privs;
+@@
+
+  if (E.change(ZPRIVS_RAISE))
+    f1;
+  ...
+  if (...) {
+-   int save_errno = errno;
+    ...
+-   if (E.change(ZPRIVS_LOWER))
+-     f2;
+    ...
+-   safe_strerror(save_errno)
++   safe_strerror(errno)
+    ...
+    \( return ret; \| exit(ret); \)
+  }
+  ...
+  if (E.change(ZPRIVS_LOWER))
+    f3;
+
+@@
+identifier change;
+expression E, f1, f2, f3, ret;
+iterator name frr_elevate_privs;
+@@
+
+  if (E.change(ZPRIVS_RAISE))
+    f1;
+  ...
+  if (...) {
+    ...
+-   if (E.change(ZPRIVS_LOWER))
+-     f2;
+    ...
+    return ret;
+  }
+  ...
+  if (E.change(ZPRIVS_LOWER))
+    f3;
+
+@@
+identifier change;
+expression E, f, g;
+iterator name frr_elevate_privs;
+@@
+
+- if (E.change(ZPRIVS_RAISE))
+-   f;
++ frr_elevate_privs(&E) {
+  ...
+- if (E.change(ZPRIVS_LOWER))
+-   g;
++ }
index 0fca541137d51d0ccc9d5c0a00626103342650ae..2abff422c99b887c0738b8416a4111c5f03c6736 100644 (file)
@@ -5,7 +5,7 @@
 #
 # ATTENTION:
 #
-# When activation a daemon at the first time, a config file, even if it is
+# When activating a daemon for the first time, a config file, even if it is
 # empty, has to be present *and* be owned by the user and group "frr", else
 # the daemon will not be started by /etc/init.d/frr. The permissions should
 # be u=rw,g=r,o=.
diff --git a/tools/etc/frr/support_bundle_commands.conf b/tools/etc/frr/support_bundle_commands.conf
new file mode 100644 (file)
index 0000000..d52824f
--- /dev/null
@@ -0,0 +1,83 @@
+# FRR Support Bundle Command List
+# Do Not modify the lines that start with
+# PROC_NAME, CMD_LIST_START and CMD_LIST_END
+# Add the new command for each process between
+# CMD_LIST_START and CMD_LIST_END lines
+
+# BGP Support Bundle Command List
+PROC_NAME:bgp
+CMD_LIST_START
+show bgp summary
+show ip bgp
+show ip bgp neighbors
+show ip bgp summary
+show ip bgp statistics
+
+show ip bgp update-groups advertise-queue
+show ip bgp update-groups advertised-routes
+show ip bgp update-groups packet-queue
+show ip bgp update-groups statistics
+show ip bgp peer-group
+show ip bgp memory
+
+show bgp ipv6
+show bgp ipv6 neighbors
+show bgp ipv6 summary
+show bgp ipv6 update-groups advertise-queue
+show bgp ipv6 update-groups advertised-routes
+show bgp ipv6 update-groups packet-queue
+show bgp ipv6 update-groups statistics
+show ip bgp statistics
+
+show bgp evpn route
+CMD_LIST_END
+
+# Zebra Support Bundle Command List
+PROC_NAME:zebra
+CMD_LIST_START
+show zebra
+show zebra client summary
+show ip route
+
+show route-map
+show memory
+show interface
+show vrf
+show error all
+show work-queues
+show running-config
+show thread cpu
+show thread poll
+show daemons
+show version
+CMD_LIST_END
+
+# OSPF Support Bundle Command List
+# PROC_NAME:ospf
+# CMD_LIST_START
+# CMD_LIST_END
+
+# RIP Support Bundle Command List
+# PROC_NAME:rip
+# CMD_LIST_START
+# CMD_LIST_END
+
+# ISIS Support Bundle Command List
+# PROC_NAME:isis
+# CMD_LIST_START
+# CMD_LIST_END
+
+# BFD Support Bundle Command List
+# PROC_NAME:bfd
+# CMD_LIST_START
+# CMD_LIST_END
+
+# STATIC Support Bundle Command List
+# PROC_NAME:static
+# CMD_LIST_START
+# CMD_LIST_END
+
+# PIM Support Bundle Command List
+# PROC_NAME:pim
+# CMD_LIST_START
+# CMD_LIST_END
index a443191fd04122893ee200870f22b4f16440220b..2e3a094589cb4eb738f8bf1c24a75be31f47647c 100755 (executable)
@@ -504,7 +504,9 @@ check_status()
 
 # Load configuration
 . "$C_PATH/daemons"
-. "$C_PATH/daemons.conf"
+if [ -e "$C_PATH/daemons.conf" ]; then
+       . "$C_PATH/daemons.conf"
+fi
 
 # Read configuration variable file if it is present
 [ -r /etc/default/frr ] && . /etc/default/frr
index 76a0d617ba199616d2e158f158fb7e0b56fd0e49..897e6d65587d0b1e8f51e0c532606026109da4e3 100644 (file)
@@ -291,7 +291,7 @@ load_old_config "$C_PATH/daemons.conf"
 load_old_config "/etc/default/frr"
 load_old_config "/etc/sysconfig/frr"
 
-if declare -p watchfrr_options | grep -q '^declare \-a'; then
+if { declare -p watchfrr_options 2>/dev/null || true; } | grep -q '^declare \-a'; then
        log_warning_msg "watchfrr_options contains a bash array value." \
                "The configured value is intentionally ignored since it is likely wrong." \
                "Please remove or fix the setting."
diff --git a/tools/generate_support_bundle.py b/tools/generate_support_bundle.py
new file mode 100644 (file)
index 0000000..118ca11
--- /dev/null
@@ -0,0 +1,110 @@
+########################################################
+### Python Script to generate the FRR support bundle ###
+########################################################
+import os
+import subprocess
+import datetime
+
+TOOLS_DIR="tools/"
+ETC_DIR="/etc/frr/"
+LOG_DIR="/var/log/frr/"
+SUCCESS = 1
+FAIL = 0
+
+inputFile = ETC_DIR + "support_bundle_commands.conf"
+
+# Open support bundle configuration file
+def openConfFile(i_file):
+  try:
+    with open(i_file) as supportBundleConfFile:
+      lines = filter(None, (line.rstrip() for line in supportBundleConfFile))
+    return lines
+  except IOError:
+    return ([])
+
+# Create the output file name
+def createOutputFile(procName):
+  fileName = procName + "_support_bundle.log"
+  oldFile = LOG_DIR + fileName
+  cpFileCmd = "cp " + oldFile + " " + oldFile + ".prev"
+  rmFileCmd = "rm -rf " + oldFile
+  print "Making backup of " + oldFile
+  os.system(cpFileCmd)
+  print "Removing " + oldFile
+  os.system(rmFileCmd)
+  return fileName
+
+# Open the output file for this process
+def openOutputFile(fileName):
+  crt_file_cmd = LOG_DIR + fileName
+  print crt_file_cmd
+  try:
+    outputFile = open(crt_file_cmd, "w")
+    return outputFile
+  except IOError:
+    return ()
+
+# Close the output file for this process
+def closeOutputFile(file):
+  try:
+    file.close()
+    return SUCCESS
+  except IOError:
+    return FAIL
+
+# Execute the command over vtysh and store in the
+# output file
+def executeCommand(cmd, outputFile):
+  cmd_exec_str = "vtysh -c \"" + cmd + "\" "
+  try:
+    cmd_output = subprocess.check_output(cmd_exec_str, shell=True)
+    try:
+      dateTime = datetime.datetime.now()
+      outputFile.write(">>[" + str(dateTime) + "]" + cmd + "\n")
+      outputFile.write(cmd_output)
+      outputFile.write("########################################################\n")
+      outputFile.write('\n')
+    except:
+      print "Writing to ouptut file Failed"
+  except subprocess.CalledProcessError as e:
+    dateTime = datetime.datetime.now()
+    outputFile.write(">>[" + str(dateTime) + "]" + cmd + "\n")
+    outputFile.write(e.output)
+    outputFile.write("########################################################\n")
+    outputFile.write('\n')
+    print "Error:" + e.output
+
+
+# Process the support bundle configuration file
+# and call appropriate functions
+def processConfFile(lines):
+  for line in lines:
+    if line[0][0] == '#':
+      continue
+    cmd_line = line.split(':')
+    if cmd_line[0] == "PROC_NAME":
+      outputFileName = createOutputFile(cmd_line[1])
+      if outputFileName:
+        print outputFileName, "created for", cmd_line[1]
+    elif cmd_line[0] == "CMD_LIST_START":
+      outputFile = openOutputFile(outputFileName)
+      if outputFile:
+        print outputFileName, "opened"
+      else:
+        print outputFileName, "open failed"
+       return FAIL
+    elif cmd_line[0] == "CMD_LIST_END":
+      if closeOutputFile(outputFile):
+        print outputFileName, "closed"
+      else:
+        print outputFileName, "close failed"
+    else:
+      print "Execute:" , cmd_line[0]
+      executeCommand(cmd_line[0], outputFile)
+      
+# Main Function
+lines = openConfFile(inputFile)
+if not lines:
+  print "File support_bundle_commands.conf not present in /etc/frr/ directory"
+else:
+  processConfFile(lines)
diff --git a/tools/vty_check.cocci b/tools/vty_check.cocci
deleted file mode 100644 (file)
index 7e5fcc4..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * VTY_DECLVAR_CONTEXT contains a built-in "if (!var) return;"
- */
-@@
-identifier var, typ;
-statement S;
-@@
-
-  {
-    ...
-  \(
-    VTY_DECLVAR_CONTEXT(typ, var);
-  \|
-    VTY_DECLVAR_CONTEXT_SUB(typ, var);
-  \)
-    ...
--   if (
--         \(  !var  \|  var == NULL \)
--      )
--      S
-    ...
-  }
diff --git a/tools/vty_index.cocci b/tools/vty_index.cocci
deleted file mode 100644 (file)
index eabbaa1..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * prep: strip off casts, they cause things to fail matching later.
- */
-
-@@
-identifier casttarget;
-symbol vty;
-@@
-
-- (struct casttarget *)vty->index
-+ vty->index
-
-/*
- * variant 1:  local variable assigned from vty->index
- */
-
-@@
-identifier sn, nn;
-identifier fn;
-@@
-
-  int fn(...)
-  {
-+ VTY_DECLVAR_CONTEXT (sn, nn);
-  ...
-  \(
--   struct sn *nn;
-    ...
--   nn = vty->index;
-  \|
--   struct sn *nn = vty->index;
-  \|
--   struct sn *nn = vty->index;
-    ...
--   nn = vty->index;
-  \)
-  ...
-  }
-
-@@
-identifier sn, nn;
-identifier fn;
-type Tr;
-@@
-
-  Tr *fn(...)
-  {
-+   struct sn *nn = VTY_GET_CONTEXT(sn);
-  ...
-  \(
--   struct sn *nn;
-    ...
--   nn = vty->index;
-+   if (!nn) {
-+     return NULL;
-+   }
-  \|
--   struct sn *nn = vty->index;
-+   if (!nn) {
-+     return NULL;
-+   }
-  \|
--   struct sn *nn = vty->index;
-    ...
--   nn = vty->index;
-+   if (!nn) {
-+     return NULL;
-+   }
-  \)
-  ...
-  }
-
-/*
- * variant 2:  vty wrapper func with (vty, vty->index, ...) signature
- */
-
-/* find calls of this pattern first; arg will be dropped in rule3 */
-@rule1@
-identifier fn !~ "generic_(set|match)_";
-expression arg;
-@@
- fn(arg, arg->index, ...)
-
-@ script:python @
-fn << rule1.fn;
-arg << rule1.arg;
-@@
-print "R01 removing vty-index argument on %s(%s, ...)" % (fn, arg)
-
-#/* strip arg on the vty wrapper func, add local handling */
-@ rule2 @
-identifier rule1.fn;
-identifier arg;
-identifier T;
-@@
-
-  static int fn (struct vty *vty,
--                struct T * arg,
-                 ...)
-  {
-+   VTY_DECLVAR_CONTEXT (T, arg);
-    ...
-  }
-
-/* drop argument on call sites identified earlier */
-@ rule3 @
-identifier rule1.fn;
-expression arg;
-@@
-
-  fn(arg,
--    arg->index,
-     ...)
-
-
-/*
- * variant 3:  function calls with "vty->index" argument (but no vty)
- *
- * a bit more complicated since we need to find the type from the header.
- */
-
-/* find call sites first
- * remember function name for later declvar insertion
- */
-@ rule11 exists@
-identifier fn;
-identifier fparent;
-type Tr;
-@@
-  Tr fparent (...)
-  {
-    ...
-    fn(vty->index, ...)
-    ...
-  }
-
-@ script:python @
-fn << rule11.fn;
-@@
-print "R11 removing vty-index argument on %s(...)" % (fn)
-
-#/* find type of the argument - note args are mostly unnamed in FRR :( */
-@ rule12 @
-identifier rule11.fn;
-identifier T, argname;
-type Tr;
-@@
-
-(
-  Tr fn(struct T *, ...);
-|
-  Tr fn(struct T * argname, ...);
-)
-
-@ script:python @
-fn << rule11.fn;
-T << rule12.T;
-@@
-print "R12 removing vty-index type is %s for %s(...)" % (T, fn)
-
-#/* add declvar
-# * this is split from rule14 so we support multiple calls in one func */
-@ rule13a @
-identifier rule11.fparent;
-identifier rule12.T;
-@@
-
-  int fparent (...)
-  {
-+   VTY_DECLVAR_CONTEXT(T, T);
-    ...
-  }
-
-@ rule13b @
-identifier rule11.fparent;
-identifier rule12.T;
-type Tr;
-@@
-
-  Tr *fparent (...)
-  {
-+   struct T *T = VTY_GET_CONTEXT(T);
-+   if (!T) {
-+     return NULL;
-+   }
-    ...
-  }
-
-/* now replace the argument in the call */
-@ rule14 exists @
-identifier rule11.fn;
-identifier rule12.T;
-@@
-
-  {
-    ...
-    \(
-    fn(
--       vty->index,
-+       T,
-        ...)
-    \|
-    fn(
--       vty->index
-+       T
-        )
-    \)
-    ...
-  }
-
-/* special case ... */
-@rule30@
-identifier fn =~ "generic_(set|match)_";
-expression arg;
-@@
-  fn(arg,
--    arg->index,
-+    VTY_GET_CONTEXT(route_map_index),
-     ...)
-
-/* and finally - PUSH_CONTEXT */
-@ rule99a exists @
-identifier tnode;
-identifier vexpr =~ "NULL";
-@@
-
-- vty->node = tnode;
-  ...
-- vty->index = vexpr;
-+ VTY_PUSH_CONTEXT_NULL(tnode);
-
-@ rule99b exists @
-identifier tnode;
-expression vexpr;
-@@
-
-- vty->node = tnode;
-  ...
-- vty->index = vexpr;
-+ VTY_PUSH_CONTEXT(tnode, vexpr);
-
diff --git a/tools/zprivs.cocci b/tools/zprivs.cocci
deleted file mode 100644 (file)
index 76d13c3..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-@@
-identifier change;
-identifier end;
-expression E, f, g;
-iterator name frr_elevate_privs;
-@@
-
-- if (E.change(ZPRIVS_RAISE))
--   f;
-+ frr_elevate_privs(&E) {
-  <+...
--   goto end;
-+   break;
-  ...+>
-- end:
-- if (E.change(ZPRIVS_LOWER))
--   g;
-+ }
-
-@@
-identifier change, errno, safe_strerror, exit;
-expression E, f1, f2, f3, ret, fn;
-iterator name frr_elevate_privs;
-@@
-
-  if (E.change(ZPRIVS_RAISE))
-    f1;
-  ...
-  if (...) {
--   int save_errno = errno;
-    ...
--   if (E.change(ZPRIVS_LOWER))
--     f2;
-    ...
--   safe_strerror(save_errno)
-+   safe_strerror(errno)
-    ...
-    \( return ret; \| exit(ret); \)
-  }
-  ...
-  if (E.change(ZPRIVS_LOWER))
-    f3;
-
-@@
-identifier change;
-expression E, f1, f2, f3, ret;
-iterator name frr_elevate_privs;
-@@
-
-  if (E.change(ZPRIVS_RAISE))
-    f1;
-  ...
-  if (...) {
-    ...
--   if (E.change(ZPRIVS_LOWER))
--     f2;
-    ...
-    return ret;
-  }
-  ...
-  if (E.change(ZPRIVS_LOWER))
-    f3;
-
-@@
-identifier change;
-expression E, f, g;
-iterator name frr_elevate_privs;
-@@
-
-- if (E.change(ZPRIVS_RAISE))
--   f;
-+ frr_elevate_privs(&E) {
-  ...
-- if (E.change(ZPRIVS_LOWER))
--   g;
-+ }
index 91e49c45c122de51fa447459d3a89901e7f5524b..7ca3ed9c5ea5762f1689549952b675a88d58e5aa 100644 (file)
@@ -74,8 +74,7 @@ static int config_cmp(struct config *c1, struct config *c2)
 static void config_del(struct config *config)
 {
        list_delete(&config->line);
-       if (config->name)
-               XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name);
+       XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name);
        XFREE(MTYPE_VTYSH_CONFIG, config);
 }
 
index dcf8ca0470f7081038663d2a32daa35352445aeb..aaf70ab08b1d9917854b5cfb5c0da197979cbb97 100644 (file)
@@ -204,7 +204,7 @@ char *vtysh_get_home(void)
        struct passwd *passwd;
        char *homedir;
 
-       if ((homedir = getenv("HOME")) != 0)
+       if ((homedir = getenv("HOME")) != NULL)
                return homedir;
 
        /* Fallback if HOME is undefined */
index c449855f6dfb40901485e334a6b60a2544887ea9..7114a3286be1b3e36b7dca5584f1147f5b1d14d3 100644 (file)
@@ -272,7 +272,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
                                ifp->vrf_id, ifp->name,
                                prefix2str(&p, buf, sizeof(buf)));
                }
-               mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
+               mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id), &p);
        }
 }
 
@@ -437,7 +437,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
                                ifp->vrf_id, ifp->name,
                                prefix2str(&p, buf, sizeof(buf)));
                }
-               mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
+               mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id), &p);
        }
 }
 
@@ -471,7 +471,7 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p)
                                ifp->vrf_id, ifp->name,
                                prefix2str(p, buf, sizeof(buf)));
                }
-               mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
+               mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id), p);
        }
 }
 
@@ -594,5 +594,5 @@ int connected_is_unnumbered(struct interface *ifp)
                        return CHECK_FLAG(connected->flags,
                                          ZEBRA_IFA_UNNUMBERED);
        }
-       return 0;
+       return 1;
 }
index faba30b0d5c653a30a9e4208070cf9115295f905..7672bec0063fdaa2b266b1439f4fa35f72c4585a 100644 (file)
 #include "lib/if.h"
 #include "lib/prefix.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern struct connected *connected_check(struct interface *ifp,
                                         union prefixconstptr p);
 extern struct connected *connected_check_ptp(struct interface *ifp,
@@ -58,4 +62,7 @@ extern void connected_delete_ipv6(struct interface *ifp,
 
 extern int connected_is_unnumbered(struct interface *);
 
+#ifdef __cplusplus
+}
+#endif
 #endif /*_ZEBRA_CONNECTED_H */
index 87999a1bbce03e66976b66e967959e8ee7d42d11..8e5fb0ea103b8e4474a242753204b8665b6e2406 100644 (file)
@@ -87,7 +87,9 @@ DEFUN_NOSH (show_debugging_zebra,
 
        if (IS_ZEBRA_DEBUG_FPM)
                vty_out(vty, "  Zebra FPM debugging is on\n");
-       if (IS_ZEBRA_DEBUG_NHT)
+       if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+               vty_out(vty, "  Zebra detailed next-hop tracking debugging is on\n");
+       else if (IS_ZEBRA_DEBUG_NHT)
                vty_out(vty, "  Zebra next-hop tracking debugging is on\n");
        if (IS_ZEBRA_DEBUG_MPLS)
                vty_out(vty, "  Zebra MPLS debugging is on\n");
@@ -119,12 +121,19 @@ DEFUN (debug_zebra_events,
 
 DEFUN (debug_zebra_nht,
        debug_zebra_nht_cmd,
-       "debug zebra nht",
+       "debug zebra nht [detailed]",
        DEBUG_STR
        "Zebra configuration\n"
-       "Debug option set for zebra next hop tracking\n")
+       "Debug option set for zebra next hop tracking\n"
+       "Debug option set for detailed info\n")
 {
+       int idx = 0;
+
        zebra_debug_nht = ZEBRA_DEBUG_NHT;
+
+       if (argv_find(argv, argc, "detailed", &idx))
+               zebra_debug_nht |= ZEBRA_DEBUG_NHT_DETAILED;
+
        return CMD_SUCCESS;
 }
 
@@ -320,11 +329,12 @@ DEFUN (no_debug_zebra_events,
 
 DEFUN (no_debug_zebra_nht,
        no_debug_zebra_nht_cmd,
-       "no debug zebra nht",
+       "no debug zebra nht [detailed]",
        NO_STR
        DEBUG_STR
        "Zebra configuration\n"
-       "Debug option set for zebra next hop tracking\n")
+       "Debug option set for zebra next hop tracking\n"
+       "Debug option set for detailed info\n")
 {
        zebra_debug_nht = 0;
        return CMD_SUCCESS;
@@ -490,10 +500,15 @@ static int config_write_debug(struct vty *vty)
                vty_out(vty, "debug zebra fpm\n");
                write++;
        }
-       if (IS_ZEBRA_DEBUG_NHT) {
+
+       if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
+               vty_out(vty, "debug zebra nht detailed\n");
+               write++;
+       } else if (IS_ZEBRA_DEBUG_NHT) {
                vty_out(vty, "debug zebra nht\n");
                write++;
        }
+
        if (IS_ZEBRA_DEBUG_MPLS) {
                vty_out(vty, "debug zebra mpls\n");
                write++;
@@ -530,6 +545,7 @@ void zebra_debug_init(void)
        zebra_debug_pw = 0;
        zebra_debug_dplane = 0;
        zebra_debug_mlag = 0;
+       zebra_debug_nht = 0;
 
        install_node(&debug_node, config_write_debug);
 
index c79cd96c214d53e99c17f1e99c686df2a9da09f8..176226f7ae402b5ff0d10645ddc1a6d5b1dd8688 100644 (file)
 
 #include "lib/vty.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Debug flags. */
 #define ZEBRA_DEBUG_EVENT   0x01
 
@@ -40,7 +44,9 @@
 #define ZEBRA_DEBUG_RIB_DETAILED   0x02
 
 #define ZEBRA_DEBUG_FPM     0x01
-#define ZEBRA_DEBUG_NHT     0x01
+
+#define ZEBRA_DEBUG_NHT 0x01
+#define ZEBRA_DEBUG_NHT_DETAILED 0x02
 
 #define ZEBRA_DEBUG_MPLS    0x01
 
 #define IS_ZEBRA_DEBUG_RIB_DETAILED  (zebra_debug_rib & ZEBRA_DEBUG_RIB_DETAILED)
 
 #define IS_ZEBRA_DEBUG_FPM (zebra_debug_fpm & ZEBRA_DEBUG_FPM)
+
 #define IS_ZEBRA_DEBUG_NHT  (zebra_debug_nht & ZEBRA_DEBUG_NHT)
+#define IS_ZEBRA_DEBUG_NHT_DETAILED (zebra_debug_nht & ZEBRA_DEBUG_NHT_DETAILED)
+
 #define IS_ZEBRA_DEBUG_MPLS  (zebra_debug_mpls & ZEBRA_DEBUG_MPLS)
 #define IS_ZEBRA_DEBUG_VXLAN (zebra_debug_vxlan & ZEBRA_DEBUG_VXLAN)
 #define IS_ZEBRA_DEBUG_PW  (zebra_debug_pw & ZEBRA_DEBUG_PW)
@@ -99,4 +108,8 @@ extern void zebra_debug_init(void);
 
 DECLARE_HOOK(zebra_debug_show_debugging, (struct vty *vty), (vty));
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_DEBUG_H */
index 3583d63d31447a28473604f84fbb1afc65717807..b2f470bc8d9ba59565f45f0d97aeceb8f250a955 100644 (file)
@@ -1194,8 +1194,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        ifp = if_lookup_by_name_per_ns(zns, name);
 
        if (ifp) {
-               if (ifp->desc)
-                       XFREE(MTYPE_TMP, ifp->desc);
+               XFREE(MTYPE_TMP, ifp->desc);
                if (desc)
                        ifp->desc = XSTRDUP(MTYPE_TMP, desc);
        }
index 65a266a519f503b92970c2fca934f09123233ed2..710fd525587549dcc5e866ea1017a587492803e0 100644 (file)
 
 #ifdef HAVE_NETLINK
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id,
                                  int startup);
 extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);
 extern int interface_lookup_netlink(struct zebra_ns *zns);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* HAVE_NETLINK */
 
 #endif /* _ZEBRA_IF_NETLINK_H */
index 1dbcf33fad84eadf3e7d2b478ea4ace70a738d8e..ce404e82537269a49ced567519399c8de4c5b4fa 100644 (file)
 
 #include "zebra/zebra_l2.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* For interface multicast configuration. */
 #define IF_ZEBRA_MULTICAST_UNSPEC 0
 #define IF_ZEBRA_MULTICAST_ON     1
@@ -432,4 +436,8 @@ extern int interface_list_proc(void);
 extern int ifaddr_proc_ipv6(void);
 #endif /* HAVE_PROC_NET_IF_INET6 */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_INTERFACE_H */
index 2a8ea779092839c5b5308a8316e3c0b7967b683e..67ffd45a0818adec7e5dceaa9916e2b92bc55c70 100644 (file)
 #ifndef _ZEBRA_IOCTL_H
 #define _ZEBRA_IOCTL_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Prototypes. */
 extern void ifreq_set_name(struct ifreq *, struct interface *);
 extern int if_ioctl(unsigned long, caddr_t);
@@ -53,4 +57,8 @@ extern struct connected *if_lookup_linklocal(struct interface *);
 
 #endif /* SOLARIS_IPV6 */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_IOCTL_H */
index 3507e563cdcf2388c624de25ef04c4147fbb2260..363f38289656fba1b285efb9aeefb8a30de22945 100644 (file)
 #ifndef _ZEBRA_IF_IOCTL_SOLARIS_H
 #define _ZEBRA_IF_IOCTL_SOLARIS_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void lifreq_set_name(struct lifreq *, const char *);
 int if_get_flags_direct(const char *, uint64_t *, unsigned int af);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_IF_IOCTL_SOLARIS_H */
index fe9f2db9119ea690eb1bf987740f9957eb40267f..9884678c7a687b4198fa77b6af3d7e25aea08732 100644 (file)
 #ifndef _ZEBRA_IPFORWARD_H
 #define _ZEBRA_IPFORWARD_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern int ipforward(void);
 extern int ipforward_on(void);
 extern int ipforward_off(void);
@@ -29,4 +33,8 @@ extern int ipforward_ipv6(void);
 extern int ipforward_ipv6_on(void);
 extern int ipforward_ipv6_off(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_IPFORWARD_H */
index 4800e75be378213f162e24f64eabf7e1231ed468..3f4fa93460ac5f9ba743450d868f0748927a7501 100644 (file)
 
 #include "lib/vty.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define TRUE 1
 #define FALSE 0
 
@@ -150,5 +154,8 @@ extern int irdp_read_raw(struct thread *r);
 extern void send_packet(struct interface *ifp, struct stream *s, uint32_t dst,
                        struct prefix *p, uint32_t ttl);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* _IRDP_H */
index a9734056bc09e320387ef932b2d89b9c47498ef1..38d241eaa5b45c5624109281b878878096bc07a3 100644 (file)
@@ -241,7 +241,7 @@ int irdp_send_thread(struct thread *t_advert)
                timer = MAX_INITIAL_ADVERT_INTERVAL;
 
        if (irdp->flags & IF_DEBUG_MISC)
-               zlog_debug("IRDP: New timer for %s set to %u\n", ifp->name,
+               zlog_debug("IRDP: New timer for %s set to %u", ifp->name,
                           timer);
 
        irdp->t_advertise = NULL;
index 774d84d66d87bd1274029bb5755e5c32bdab8033..2804787620ab6ff8d9be38264fa1ae6969ea25e6 100644 (file)
@@ -166,7 +166,7 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp)
        case ICMP_ROUTERSOLICIT:
 
                if (irdp->flags & IF_DEBUG_MESSAGES)
-                       zlog_debug("IRDP: RX Solicit on %s from %s\n",
+                       zlog_debug("IRDP: RX Solicit on %s from %s",
                                   ifp->name, inet_ntoa(src));
 
                process_solicit(ifp);
@@ -253,7 +253,7 @@ int irdp_read_raw(struct thread *r)
        if (!(irdp->flags & IF_ACTIVE)) {
 
                if (irdp->flags & IF_DEBUG_MISC)
-                       zlog_debug("IRDP: RX ICMP for disabled interface %s\n",
+                       zlog_debug("IRDP: RX ICMP for disabled interface %s",
                                   ifp->name);
                return 0;
        }
index 2f850c6338d51a9fdf7916a6bf264896d171ee6a..fe37a333581ed12244f62acce217dba9adddbe7c 100644 (file)
@@ -606,53 +606,59 @@ const char *nl_rttype_to_str(uint8_t rttype)
        return lookup_msg(rttype_str, rttype, "");
 }
 
-#define NL_OK(nla, len)                                                        \
+#define NLA_OK(nla, len)                                                       \
        ((len) >= (int)sizeof(struct nlattr)                                   \
         && (nla)->nla_len >= sizeof(struct nlattr)                            \
         && (nla)->nla_len <= (len))
-#define NL_NEXT(nla, attrlen)                                                  \
-       ((attrlen) -= RTA_ALIGN((nla)->nla_len),                               \
-        (struct nlattr *)(((char *)(nla)) + RTA_ALIGN((nla)->nla_len)))
-#define NL_RTA(r)                                                              \
-       ((struct nlattr *)(((char *)(r))                                       \
-                          + NLMSG_ALIGN(sizeof(struct nlmsgerr))))
+#define NLA_NEXT(nla, attrlen)                                                 \
+       ((attrlen) -= NLA_ALIGN((nla)->nla_len),                               \
+        (struct nlattr *)(((char *)(nla)) + NLA_ALIGN((nla)->nla_len)))
+#define NLA_LENGTH(len) (NLA_ALIGN(sizeof(struct nlattr)) + (len))
+#define NLA_DATA(nla) ((struct nlattr *)(((char *)(nla)) + NLA_LENGTH(0)))
+
+#define ERR_NLA(err, inner_len)                                                \
+       ((struct nlattr *)(((char *)(err))                                     \
+                          + NLMSG_ALIGN(sizeof(struct nlmsgerr))              \
+                          + NLMSG_ALIGN((inner_len))))
 
 static void netlink_parse_nlattr(struct nlattr **tb, int max,
                                 struct nlattr *nla, int len)
 {
-       while (NL_OK(nla, len)) {
+       while (NLA_OK(nla, len)) {
                if (nla->nla_type <= max)
                        tb[nla->nla_type] = nla;
-               nla = NL_NEXT(nla, len);
+               nla = NLA_NEXT(nla, len);
        }
 }
 
 static void netlink_parse_extended_ack(struct nlmsghdr *h)
 {
-       struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
-       const struct nlmsgerr *err =
-               (const struct nlmsgerr *)((uint8_t *)h
-                                         + NLMSG_ALIGN(
-                                                   sizeof(struct nlmsghdr)));
+       struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
+       const struct nlmsgerr *err = (const struct nlmsgerr *)NLMSG_DATA(h);
        const struct nlmsghdr *err_nlh = NULL;
-       uint32_t hlen = sizeof(*err);
+       /* Length not including nlmsghdr */
+       uint32_t len = 0;
+       /* Inner error netlink message length */
+       uint32_t inner_len = 0;
        const char *msg = NULL;
        uint32_t off = 0;
 
        if (!(h->nlmsg_flags & NLM_F_CAPPED))
-               hlen += h->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
+               inner_len = (uint32_t)NLMSG_PAYLOAD(&err->msg, 0);
+
+       len = (uint32_t)(NLMSG_PAYLOAD(h, sizeof(struct nlmsgerr)) - inner_len);
 
-       memset(tb, 0, sizeof(tb));
-       netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, NL_RTA(h), hlen);
+       netlink_parse_nlattr(tb, NLMSGERR_ATTR_MAX, ERR_NLA(err, inner_len),
+                            len);
 
        if (tb[NLMSGERR_ATTR_MSG])
-               msg = (const char *)RTA_DATA(tb[NLMSGERR_ATTR_MSG]);
+               msg = (const char *)NLA_DATA(tb[NLMSGERR_ATTR_MSG]);
 
        if (tb[NLMSGERR_ATTR_OFFS]) {
-               off = *(uint32_t *)RTA_DATA(tb[NLMSGERR_ATTR_OFFS]);
+               off = *(uint32_t *)NLA_DATA(tb[NLMSGERR_ATTR_OFFS]);
 
                if (off > h->nlmsg_len) {
-                       zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS\n");
+                       zlog_err("Invalid offset for NLMSGERR_ATTR_OFFS");
                } else if (!(h->nlmsg_flags & NLM_F_CAPPED)) {
                        /*
                         * Header of failed message
index 9918729eb66adc959082f81b574a4c363dfb7451..076ca5c5c7579253eb07859d42ee15046cc99568 100644 (file)
 #ifndef _ZEBRA_KERNEL_NETLINK_H
 #define _ZEBRA_KERNEL_NETLINK_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef HAVE_NETLINK
 
 #define NL_RCV_PKT_BUF_SIZE     32768
@@ -68,4 +72,8 @@ extern int netlink_request(struct nlsock *nl, struct nlmsghdr *n);
 
 #endif /* HAVE_NETLINK */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_KERNEL_NETLINK_H */
index 792756efebdbaf161b5ea7a21e7d2ea8012fff51..13d2185b0fa04dfb26fcc337b567fa48b7b4a655 100644 (file)
@@ -148,7 +148,9 @@ const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"},
 #ifdef RTM_OLDDEL
                                       {RTM_OLDDEL, "RTM_OLDDEL"},
 #endif /* RTM_OLDDEL */
+#ifdef RTM_RESOLVE
                                       {RTM_RESOLVE, "RTM_RESOLVE"},
+#endif /* RTM_RESOLVE */
                                       {RTM_NEWADDR, "RTM_NEWADDR"},
                                       {RTM_DELADDR, "RTM_DELADDR"},
                                       {RTM_IFINFO, "RTM_IFINFO"},
@@ -278,8 +280,9 @@ size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf)
                }
 
                if (copylen > destlen) {
-                       zlog_warn("%s: destination buffer too small (%lu vs %lu)",
-                                 __func__, copylen, destlen);
+                       zlog_warn(
+                               "%s: destination buffer too small (%zu vs %zu)",
+                               __func__, copylen, destlen);
                        memcpy(dest, sap, destlen);
                } else
                        memcpy(dest, sap, copylen);
@@ -314,8 +317,9 @@ size_t rta_getsdlname(caddr_t sap, void *destp, short *destlen)
 
        if (copylen > 0 && dest != NULL && sdl->sdl_family == AF_LINK) {
                if (copylen > IFNAMSIZ) {
-                       zlog_warn("%s: destination buffer too small (%lu vs %d)",
-                                 __func__, copylen, IFNAMSIZ);
+                       zlog_warn(
+                               "%s: destination buffer too small (%zu vs %d)",
+                               __func__, copylen, IFNAMSIZ);
                        memcpy(dest, sdl->sdl_data, IFNAMSIZ);
                        dest[IFNAMSIZ] = 0;
                        *destlen = IFNAMSIZ;
@@ -622,7 +626,7 @@ int ifm_read(struct if_msghdr *ifm)
                 * RTA_IFP) is required.
                 */
                if (!ifnlen) {
-                       zlog_debug("Interface index %d (new) missing ifname\n",
+                       zlog_debug("Interface index %d (new) missing ifname",
                                   ifm->ifm_index);
                        return -1;
                }
index 096a21f78238cb8181fe6097f6ccab40639167f8..15079d796d624d16c484608d600bb562eb2e11e7 100644 (file)
 #ifndef __ZEBRA_KERNEL_SOCKET_H
 #define __ZEBRA_KERNEL_SOCKET_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Error codes of zebra. */
 #define ZEBRA_ERR_NOERROR                0
 #define ZEBRA_ERR_RTEXIST               -1
@@ -38,4 +42,8 @@ extern int rtm_write(int, union sockunion *, union sockunion *,
                     enum blackhole_type, int);
 extern const struct message rtm_type_str[];
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __ZEBRA_KERNEL_SOCKET_H */
index 3e3def5f98bbf47eaf7a18e11cc6da2a4786c65d..3ea89fbfc3ec928c25119909bf70cc8370a57aee 100644 (file)
 
 #include "zebra/zserv.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define NO_PROTO 0
 
 /*
@@ -74,4 +78,8 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,
 int release_daemon_label_chunks(struct zserv *client);
 void label_manager_close(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _LABEL_MANAGER_H */
index c605050c57fe37ae2e70665573bfebc0cd974c49..184e798bd070f1484804082a8df794dc14d46774 100644 (file)
@@ -153,7 +153,9 @@ static void sigint(void)
        for (ALL_LIST_ELEMENTS(zrouter.client_list, ln, nn, client))
                zserv_close_client(client);
 
+       zserv_close();
        list_delete_all_node(zrouter.client_list);
+
        zebra_ptm_finish();
 
        if (retain_mode)
index f0dc79574cc1518600a9a0cdf99ec3804e3ec385..74a593b2409a3aa4b4945b2170d87f09903147e1 100644 (file)
 #include "zebra/zserv.h"
 #include "zebra/rib.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* ZAPI command handlers */
 extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS);
 extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS);
@@ -73,4 +77,9 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id);
 extern int zebra_import_table_config(struct vty *);
 
 extern void zebra_import_table_rm_update(const char *rmap);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_REDISTRIBUTE_H */
index a478fffddb3dacb9bc43c0fbca053005f498e041..e26831e1a6427b7d4e2dda7f625aff06aa735d37 100644 (file)
 #include "mpls.h"
 #include "srcdest_table.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define DISTANCE_INFINITY  255
 #define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */
 
@@ -140,6 +144,15 @@ typedef struct rib_dest_t_ {
         */
        uint32_t flags;
 
+       /*
+        * The list of nht prefixes that have ended up
+        * depending on this route node.
+        * After route processing is returned from
+        * the data plane we will run evaluate_rnh
+        * on these prefixes.
+        */
+       struct list *nht;
+
        /*
         * Linkage to put dest on the FPM processing queue.
         */
@@ -168,6 +181,8 @@ typedef struct rib_dest_t_ {
  */
 #define RIB_DEST_UPDATE_FPM    (1 << (ZEBRA_MAX_QINDEX + 2))
 
+#define RIB_DEST_UPDATE_LSPS   (1 << (ZEBRA_MAX_QINDEX + 3))
+
 /*
  * Macro to iterate over each route for a destination (prefix).
  */
@@ -355,6 +370,8 @@ extern struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter);
 
 extern uint8_t route_distance(int type);
 
+extern void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq);
+
 /*
  * Inline functions.
  */
@@ -426,6 +443,11 @@ static inline struct zebra_vrf *rib_dest_vrf(rib_dest_t *dest)
        return rib_table_info(rib_dest_table(dest))->zvrf;
 }
 
+/*
+ * Create the rib_dest_t and attach it to the specified node
+ */
+extern rib_dest_t *zebra_rib_create_dest(struct route_node *rn);
+
 /*
  * rib_tables_iter_init
  */
@@ -464,4 +486,9 @@ extern void zebra_vty_init(void);
 extern pid_t pid;
 
 extern bool v6_rr_semantics;
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_ZEBRA_RIB_H */
index 6b15159fdba2ee0306df35fc369d7919467bb4d6..f7d16853f18e90ffe7103a4a85ca07882f05f3ed 100644 (file)
 #include "zclient.h"
 #include "if.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern void router_id_add_address(struct connected *);
 extern void router_id_del_address(struct connected *);
 extern void router_id_init(struct zebra_vrf *);
@@ -37,4 +41,8 @@ extern void router_id_cmd_init(void);
 extern void router_id_write(struct vty *);
 extern void router_id_get(struct prefix *, vrf_id_t);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index 4080b0ccb287e0fbec1439d1b10841f0c803558e..2c77af2aad9f12a9962956f83ad4bf13f4ff1309 100644 (file)
 #include "zebra/zebra_mpls.h"
 #include "zebra/zebra_dplane.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RSYSTEM_ROUTE(type)                                            \
+       ((type) == ZEBRA_ROUTE_KERNEL || (type) == ZEBRA_ROUTE_CONNECT)
+
 /*
  * Update or delete a route, LSP, or pseudowire from the kernel,
  * using info from a dataplane context.
@@ -91,4 +98,8 @@ extern void neigh_read_specific_ip(struct ipaddr *ip,
                                   struct interface *vlan_if);
 extern void route_read(struct zebra_ns *zns);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_RT_H */
index 18cf389d5e0001b83f2ade927c5d7dd29e3b4f63..289ed5a15b147acda0cfe996c384ba967cbeff29 100644 (file)
@@ -835,7 +835,7 @@ int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
 
        if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) {
                /* If this is not route add/delete message print warning. */
-               zlog_debug("Kernel message: %s NS %u\n",
+               zlog_debug("Kernel message: %s NS %u",
                           nl_msg_type_to_str(h->nlmsg_type), ns_id);
                return 0;
        }
@@ -927,7 +927,7 @@ static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
                                               uint8_t gw_family,
                                               struct nlmsghdr *nlmsg,
                                               size_t req_size, int bytelen,
-                                              struct nexthop *nexthop)
+                                              const struct nexthop *nexthop)
 {
        if (route_family == AF_MPLS) {
                struct gw_family_t gw_fam;
@@ -954,7 +954,7 @@ static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
                                                struct rtattr *rta,
                                                struct rtnexthop *rtnh,
                                                size_t req_size, int bytelen,
-                                               struct nexthop *nexthop)
+                                               const struct nexthop *nexthop)
 {
        if (route_family == AF_MPLS) {
                struct gw_family_t gw_fam;
@@ -990,7 +990,7 @@ static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
  * @param req_size: The size allocated for the message.
  */
 static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
-                                           struct nexthop *nexthop,
+                                           const struct nexthop *nexthop,
                                            struct nlmsghdr *nlmsg,
                                            struct rtmsg *rtmsg,
                                            size_t req_size, int cmd)
@@ -1009,7 +1009,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
        label_buf[0] = '\0';
 
        assert(nexthop);
-       for (struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
+       for (const struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
                char label_buf1[20];
 
                nh_label = nh->nh_label;
@@ -1175,11 +1175,11 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
  *             the prefsrc should be stored.
  */
 static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
-                                          struct nexthop *nexthop,
+                                          const struct nexthop *nexthop,
                                           struct rtattr *rta,
                                           struct rtnexthop *rtnh,
                                           struct rtmsg *rtmsg,
-                                          union g_addr **src)
+                                          const union g_addr **src)
 {
        struct mpls_label_stack *nh_label;
        mpls_lse_t out_lse[MPLS_MAX_LABELS];
@@ -1200,7 +1200,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
        label_buf[0] = '\0';
 
        assert(nexthop);
-       for (struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
+       for (const struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
                char label_buf1[20];
 
                nh_label = nh->nh_label;
@@ -1342,7 +1342,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
 }
 
 static inline void _netlink_mpls_build_singlepath(const char *routedesc,
-                                                 zebra_nhlfe_t *nhlfe,
+                                                 const zebra_nhlfe_t *nhlfe,
                                                  struct nlmsghdr *nlmsg,
                                                  struct rtmsg *rtmsg,
                                                  size_t req_size, int cmd)
@@ -1358,9 +1358,9 @@ static inline void _netlink_mpls_build_singlepath(const char *routedesc,
 
 
 static inline void
-_netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe,
+_netlink_mpls_build_multipath(const char *routedesc, const zebra_nhlfe_t *nhlfe,
                              struct rtattr *rta, struct rtnexthop *rtnh,
-                             struct rtmsg *rtmsg, union g_addr **src)
+                             struct rtmsg *rtmsg, const union g_addr **src)
 {
        int bytelen;
        uint8_t family;
@@ -1438,7 +1438,6 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
 static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
 {
        int bytelen;
-       struct sockaddr_nl snl;
        struct nexthop *nexthop = NULL;
        unsigned int nexthop_num;
        int family;
@@ -1656,7 +1655,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
                char buf[NL_PKT_BUF_SIZE];
                struct rtattr *rta = (void *)buf;
                struct rtnexthop *rtnh;
-               union g_addr *src1 = NULL;
+               const union g_addr *src1 = NULL;
 
                rta->rta_type = RTA_MULTIPATH;
                rta->rta_len = RTA_LENGTH(0);
@@ -1747,11 +1746,6 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
        }
 
 skip:
-
-       /* Destination netlink address. */
-       memset(&snl, 0, sizeof(snl));
-       snl.nl_family = AF_NETLINK;
-
        /* Talk to netlink socket. */
        return netlink_talk_info(netlink_talk_filter, &req.n,
                                 dplane_ctx_get_ns(ctx), 0);
@@ -1842,7 +1836,9 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
                         * of the route delete.  If that happens yeah we're
                         * screwed.
                         */
-                       (void)netlink_route_multipath(RTM_DELROUTE, ctx);
+                       if (!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx)))
+                               (void)netlink_route_multipath(RTM_DELROUTE,
+                                                             ctx);
                        cmd = RTM_NEWROUTE;
                }
 
@@ -1850,7 +1846,10 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
                return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
 
-       ret = netlink_route_multipath(cmd, ctx);
+       if (!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx)))
+               ret = netlink_route_multipath(cmd, ctx);
+       else
+               ret = 0;
        if ((cmd == RTM_NEWROUTE) && (ret == 0)) {
                /* Update installed nexthops to signal which have been
                 * installed.
@@ -1971,23 +1970,38 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
        /* The interface should exist. */
        ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
                                        ndm->ndm_ifindex);
-       if (!ifp || !ifp->info)
+       if (!ifp || !ifp->info) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("\t%s without associated interface: %u",
+                                  __PRETTY_FUNCTION__, ndm->ndm_ifindex);
                return 0;
+       }
 
        /* The interface should be something we're interested in. */
-       if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
+       if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("\t%s Not interested in %s, not a slave",
+                                  __PRETTY_FUNCTION__, ifp->name);
                return 0;
+       }
 
        /* Drop "permanent" entries. */
-       if (ndm->ndm_state & NUD_PERMANENT)
+       if (ndm->ndm_state & NUD_PERMANENT) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("\t%s Entry is PERMANENT, dropping",
+                                  __PRETTY_FUNCTION__);
                return 0;
+       }
 
        zif = (struct zebra_if *)ifp->info;
        if ((br_if = zif->brslave_info.br_if) == NULL) {
-               zlog_debug("%s family %s IF %s(%u) brIF %u - no bridge master",
-                          nl_msg_type_to_str(h->nlmsg_type),
-                          nl_family_to_str(ndm->ndm_family), ifp->name,
-                          ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug(
+                               "%s family %s IF %s(%u) brIF %u - no bridge master",
+                               nl_msg_type_to_str(h->nlmsg_type),
+                               nl_family_to_str(ndm->ndm_family), ifp->name,
+                               ndm->ndm_ifindex,
+                               zif->brslave_info.bridge_ifindex);
                return 0;
        }
 
@@ -1996,20 +2010,24 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
        netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
 
        if (!tb[NDA_LLADDR]) {
-               zlog_debug("%s family %s IF %s(%u) brIF %u - no LLADDR",
-                          nl_msg_type_to_str(h->nlmsg_type),
-                          nl_family_to_str(ndm->ndm_family), ifp->name,
-                          ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("%s family %s IF %s(%u) brIF %u - no LLADDR",
+                                  nl_msg_type_to_str(h->nlmsg_type),
+                                  nl_family_to_str(ndm->ndm_family), ifp->name,
+                                  ndm->ndm_ifindex,
+                                  zif->brslave_info.bridge_ifindex);
                return 0;
        }
 
        if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
-               zlog_debug(
-                       "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
-                       nl_msg_type_to_str(h->nlmsg_type),
-                       nl_family_to_str(ndm->ndm_family), ifp->name,
-                       ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex,
-                       (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug(
+                               "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
+                               nl_msg_type_to_str(h->nlmsg_type),
+                               nl_family_to_str(ndm->ndm_family), ifp->name,
+                               ndm->ndm_ifindex,
+                               zif->brslave_info.bridge_ifindex,
+                               (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
                return 0;
        }
 
@@ -2042,8 +2060,12 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
                           prefix_mac2str(&mac, buf, sizeof(buf)),
                           dst_present ? dst_buf : "");
 
-       if (filter_vlan && vid != filter_vlan)
+       if (filter_vlan && vid != filter_vlan) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("\tFiltered due to filter vlan: %d",
+                                  filter_vlan);
                return 0;
+       }
 
        /* If add or update, do accordingly if learnt on a "local" interface; if
         * the notification is over VxLAN, this has to be related to
@@ -2051,10 +2073,6 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
         * so perform an implicit delete of any local entry (if it exists).
         */
        if (h->nlmsg_type == RTM_NEWNEIGH) {
-               /* Drop "permanent" entries. */
-               if (ndm->ndm_state & NUD_PERMANENT)
-                       return 0;
-
                if (IS_ZEBRA_IF_VXLAN(ifp))
                        return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
                                                               vid);
@@ -2071,8 +2089,11 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
         * Ignore the notification from VxLan driver as it is also generated
         * when mac moves from remote to local.
         */
-       if (dst_present)
+       if (dst_present) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("\tNo Destination Present");
                return 0;
+       }
 
        if (IS_ZEBRA_IF_VXLAN(ifp))
                return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
@@ -2385,6 +2406,9 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
        /* if kernel deletes our rfc5549 neighbor entry, re-install it */
        if (h->nlmsg_type == RTM_DELNEIGH && (ndm->ndm_state & NUD_PERMANENT)) {
                netlink_handle_5549(ndm, zif, ifp, &ip);
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug(
+                               "\tNeighbor Entry Received is a 5549 entry, finished");
                return 0;
        }
 
@@ -2410,20 +2434,27 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
                        return 0;
        } else if (IS_ZEBRA_IF_BRIDGE(ifp))
                link_if = ifp;
-       else
+       else {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug(
+                               "\tNeighbor Entry received is not on a VLAN or a BRIDGE, ignoring");
                return 0;
+       }
 
        memset(&mac, 0, sizeof(struct ethaddr));
        if (h->nlmsg_type == RTM_NEWNEIGH) {
                if (tb[NDA_LLADDR]) {
                        if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
-                               zlog_debug(
-                                       "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
-                                       nl_msg_type_to_str(h->nlmsg_type),
-                                       nl_family_to_str(ndm->ndm_family),
-                                       ifp->name, ndm->ndm_ifindex,
-                                       (unsigned long)RTA_PAYLOAD(
-                                               tb[NDA_LLADDR]));
+                               if (IS_ZEBRA_DEBUG_KERNEL)
+                                       zlog_debug(
+                                               "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
+                                               nl_msg_type_to_str(
+                                                       h->nlmsg_type),
+                                               nl_family_to_str(
+                                                       ndm->ndm_family),
+                                               ifp->name, ndm->ndm_ifindex,
+                                               (unsigned long)RTA_PAYLOAD(
+                                                       tb[NDA_LLADDR]));
                                return 0;
                        }
 
@@ -2750,7 +2781,7 @@ int kernel_upd_neigh(struct interface *ifp, struct ipaddr *ip,
 int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
 {
        mpls_lse_t lse;
-       zebra_nhlfe_t *nhlfe;
+       const zebra_nhlfe_t *nhlfe;
        struct nexthop *nexthop = NULL;
        unsigned int nexthop_num;
        const char *routedesc;
@@ -2853,7 +2884,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
                char buf[NL_PKT_BUF_SIZE];
                struct rtattr *rta = (void *)buf;
                struct rtnexthop *rtnh;
-               union g_addr *src1 = NULL;
+               const union g_addr *src1 = NULL;
 
                rta->rta_type = RTA_MULTIPATH;
                rta->rta_len = RTA_LENGTH(0);
index 473ad98a3fbc2b7392ae85ccfff26fca5e45c871..29e0152bb2c9d73c4b33549e6c2d73f439ecaada 100644 (file)
 #include "zebra/zebra_mpls.h"
 #include "zebra/zebra_dplane.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define NL_DEFAULT_ROUTE_METRIC 20
 
 /*
@@ -79,6 +83,10 @@ extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
 extern int netlink_neigh_read_specific_ip(struct ipaddr *ip,
                                          struct interface *vlan_if);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* HAVE_NETLINK */
 
 #endif /* _ZEBRA_RT_NETLINK_H */
index f25259f300cef721a1edf47fb91a57d07d212a93..8d8bdd0a6df839c09c31d89ff4b561ec722e1681 100644 (file)
@@ -304,33 +304,41 @@ static int kernel_rtm(int cmd, const struct prefix *p,
 enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
 {
        enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS;
+       uint32_t type, old_type;
 
        if (dplane_ctx_get_src(ctx) != NULL) {
                zlog_err("route add: IPv6 sourcedest routes unsupported!");
                return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
 
+       type = dplane_ctx_get_type(ctx);
+       old_type = dplane_ctx_get_old_type(ctx);
+
        frr_elevate_privs(&zserv_privs) {
 
-               if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE)
-                       kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
-                                  dplane_ctx_get_ng(ctx),
-                                  dplane_ctx_get_metric(ctx));
-               else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL)
-                       kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
-                                  dplane_ctx_get_ng(ctx),
-                                  dplane_ctx_get_metric(ctx));
-               else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
+               if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) {
+                       if (!RSYSTEM_ROUTE(type))
+                               kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
+                                          dplane_ctx_get_ng(ctx),
+                                          dplane_ctx_get_metric(ctx));
+               } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) {
+                       if (!RSYSTEM_ROUTE(type))
+                               kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
+                                          dplane_ctx_get_ng(ctx),
+                                          dplane_ctx_get_metric(ctx));
+               } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
                        /* Must do delete and add separately -
                         * no update available
                         */
-                       kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
-                                  dplane_ctx_get_old_ng(ctx),
-                                  dplane_ctx_get_old_metric(ctx));
-
-                       kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
-                                  dplane_ctx_get_ng(ctx),
-                                  dplane_ctx_get_metric(ctx));
+                       if (!RSYSTEM_ROUTE(old_type))
+                               kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx),
+                                          dplane_ctx_get_old_ng(ctx),
+                                          dplane_ctx_get_old_metric(ctx));
+
+                       if (!RSYSTEM_ROUTE(type))
+                               kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx),
+                                          dplane_ctx_get_ng(ctx),
+                                          dplane_ctx_get_metric(ctx));
                } else {
                        zlog_err("Invalid routing socket update op %s (%u)",
                                 dplane_op2str(dplane_ctx_get_op(ctx)),
@@ -339,6 +347,20 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
                }
        } /* Elevated privs */
 
+       if (RSYSTEM_ROUTE(type)
+           && dplane_ctx_get_op(ctx) != DPLANE_OP_ROUTE_DELETE) {
+               struct nexthop *nexthop;
+
+               for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
+                       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+                               continue;
+
+                       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
+                               SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+                       }
+               }
+       }
+
        return res;
 }
 
index f7c27ebcb3a0c9c5de776e3ba49823ea1e396db0..53c497fc09c49b4823c96e12d515c0c07e0fae6d 100644 (file)
 #include "vty.h"
 #include "zebra/interface.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* NB: RTADV is defined in zebra/interface.h above */
 #if defined(HAVE_RTADV)
 
@@ -137,5 +141,8 @@ extern void rtadv_cmd_init(void);
 extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
 extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* _ZEBRA_RTADV_H */
index 4547a1bb3b1480fe6d0d3d434f0457cda53e510f..8c4741dc06115b2313afb48b7e1ee2c9be880f4c 100644 (file)
 
 #ifdef HAVE_NETLINK
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Handle netlink notification informing a rule add or delete.
  */
@@ -36,6 +40,10 @@ extern int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);
  */
 extern int netlink_rules_read(struct zebra_ns *zns);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* HAVE_NETLINK */
 
 #endif /* _ZEBRA_RULE_NETLINK_H */
index 5196162c4c549e2c6cfc9fd93a5a75f6863317f9..4f78f5097e635c7c775b24cdd1988e73cedca857 100644 (file)
 
 #include "zebra/zserv.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Table chunk struct
  * Client daemon which the chunk belongs to can be identified by either
@@ -63,4 +67,8 @@ int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start,
 int release_daemon_table_chunks(struct zserv *client);
 void table_manager_disable(ns_id_t ns_id);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _TABLE_MANAGER_H */
index 9f2bbcf426c68a1ba59e3663e0be5710d4a0b182..2eeb1f278809cb279fe9061d052f015b149cd3f8 100644 (file)
@@ -1036,6 +1036,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
        uint8_t flags = 0;
        uint16_t type = cmd2type[hdr->command];
        bool exist;
+       bool flag_changed = false;
+       uint8_t orig_flags;
 
        if (IS_ZEBRA_DEBUG_NHT)
                zlog_debug(
@@ -1084,6 +1086,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
                if (!rnh)
                        return;
 
+               orig_flags = rnh->flags;
                if (type == RNH_NEXTHOP_TYPE) {
                        if (flags
                            && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
@@ -1101,9 +1104,12 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
                                UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
                }
 
+               if (orig_flags != rnh->flags)
+                       flag_changed = true;
+
                zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
                /* Anything not AF_INET/INET6 has been filtered out above */
-               if (!exist)
+               if (!exist || flag_changed)
                        zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type,
                                           &p);
        }
@@ -1456,8 +1462,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
                                       &(api_nh->gate.ipv4),
                                       sizeof(struct in_addr));
                                zebra_vxlan_evpn_vrf_route_add(
-                                       vrf_id, &api_nh->rmac, &vtep_ip,
-                                       &api.prefix);
+                                       api_nh->vrf_id, &api_nh->rmac,
+                                       &vtep_ip, &api.prefix);
                        }
                        break;
                case NEXTHOP_TYPE_IPV6:
@@ -1479,8 +1485,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
                                memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6),
                                       sizeof(struct in6_addr));
                                zebra_vxlan_evpn_vrf_route_add(
-                                       vrf_id, &api_nh->rmac, &vtep_ip,
-                                       &api.prefix);
+                                       api_nh->vrf_id, &api_nh->rmac,
+                                       &vtep_ip, &api.prefix);
                        }
                        break;
                case NEXTHOP_TYPE_BLACKHOLE:
index b770b8e8810c1fab0028c4080ac60deb7c07ead4..d30fa2d0ef1586a725da5309b3241748e42a6467 100644 (file)
 #include "zebra/zebra_pbr.h"
 #include "zebra/zebra_errors.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * This is called to process inbound ZAPI messages.
  *
@@ -86,3 +90,7 @@ extern void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
                                   const unsigned int nexthop_num);
 
 extern void zsend_capabilities_all_clients(void);
+
+#ifdef __cplusplus
+}
+#endif
index 928169a86267914e930b58b0d51cfbf5fa178b17..3d1ff676a5ff322cf3a8b9ff7d90df24baa1e85c 100644 (file)
@@ -111,10 +111,13 @@ struct dplane_pw_info {
        int af;
        int status;
        uint32_t flags;
-       union g_addr nexthop;
+       union g_addr dest;
        mpls_label_t local_label;
        mpls_label_t remote_label;
 
+       /* Nexthops */
+       struct nexthop_group nhg;
+
        union pw_protocol_fields fields;
 };
 
@@ -386,6 +389,15 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
 
        case DPLANE_OP_PW_INSTALL:
        case DPLANE_OP_PW_UNINSTALL:
+               /* Free allocated nexthops */
+               if ((*pctx)->u.pw.nhg.nexthop) {
+                       /* This deals with recursive nexthops too */
+                       nexthops_free((*pctx)->u.pw.nhg.nexthop);
+
+                       (*pctx)->u.pw.nhg.nexthop = NULL;
+               }
+               break;
+
        case DPLANE_OP_NONE:
                break;
        }
@@ -520,7 +532,7 @@ const char *dplane_op2str(enum dplane_op_e op)
                ret = "PW_UNINSTALL";
                break;
 
-       };
+       }
 
        return ret;
 }
@@ -539,7 +551,7 @@ const char *dplane_res2str(enum zebra_dplane_result res)
        case ZEBRA_DPLANE_REQUEST_SUCCESS:
                ret = "SUCCESS";
                break;
-       };
+       }
 
        return ret;
 }
@@ -744,14 +756,15 @@ uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx)
        return ctx->u.lsp.flags;
 }
 
-zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx)
+const zebra_nhlfe_t *dplane_ctx_get_nhlfe(const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
 
        return ctx->u.lsp.nhlfe_list;
 }
 
-zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx)
+const zebra_nhlfe_t *
+dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
 
@@ -814,12 +827,12 @@ int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx)
        return ctx->u.pw.status;
 }
 
-const union g_addr *dplane_ctx_get_pw_nexthop(
+const union g_addr *dplane_ctx_get_pw_dest(
        const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
 
-       return &(ctx->u.pw.nexthop);
+       return &(ctx->u.pw.dest);
 }
 
 const union pw_protocol_fields *dplane_ctx_get_pw_proto(
@@ -830,6 +843,14 @@ const union pw_protocol_fields *dplane_ctx_get_pw_proto(
        return &(ctx->u.pw.fields);
 }
 
+const struct nexthop_group *
+dplane_ctx_get_pw_nhg(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return &(ctx->u.pw.nhg);
+}
+
 /*
  * End of dplane context accessors
  */
@@ -1039,7 +1060,11 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
                              enum dplane_op_e op,
                              struct zebra_pw *pw)
 {
-       int ret = AOK;
+       struct prefix p;
+       afi_t afi;
+       struct route_table *table;
+       struct route_node *rn;
+       struct route_entry *re;
 
        if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
                zlog_debug("init dplane ctx %s: pw '%s', loc %u, rem %u",
@@ -1058,6 +1083,7 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
 
        /* This name appears to be c-string, so we use string copy. */
        strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
+
        ctx->zd_vrf_id = pw->vrf_id;
        ctx->u.pw.ifindex = pw->ifindex;
        ctx->u.pw.type = pw->type;
@@ -1066,11 +1092,38 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
        ctx->u.pw.remote_label = pw->remote_label;
        ctx->u.pw.flags = pw->flags;
 
-       ctx->u.pw.nexthop = pw->nexthop;
+       ctx->u.pw.dest = pw->nexthop;
 
        ctx->u.pw.fields = pw->data;
 
-       return ret;
+       /* Capture nexthop info for the pw destination. We need to look
+        * up and use zebra datastructs, but we're running in the zebra
+        * pthread here so that should be ok.
+        */
+       memcpy(&p.u, &pw->nexthop, sizeof(pw->nexthop));
+       p.family = pw->af;
+       p.prefixlen = ((pw->af == AF_INET) ?
+                      IPV4_MAX_PREFIXLEN : IPV6_MAX_PREFIXLEN);
+
+       afi = (pw->af == AF_INET) ? AFI_IP : AFI_IP6;
+       table = zebra_vrf_table(afi, SAFI_UNICAST, pw->vrf_id);
+       if (table) {
+               rn = route_node_match(table, &p);
+               if (rn) {
+                       RNODE_FOREACH_RE(rn, re) {
+                               if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
+                                       break;
+                       }
+
+                       if (re)
+                               copy_nexthops(&(ctx->u.pw.nhg.nexthop),
+                                             re->ng.nexthop, NULL);
+
+                       route_unlock_node(rn);
+               }
+       }
+
+       return AOK;
 }
 
 /*
@@ -1476,10 +1529,6 @@ int dplane_provider_register(const char *name,
 
        /* Allocate and init new provider struct */
        p = XCALLOC(MTYPE_DP_PROV, sizeof(struct zebra_dplane_provider));
-       if (p == NULL) {
-               ret = ENOMEM;
-               goto done;
-       }
 
        pthread_mutex_init(&(p->dp_mutex), NULL);
        TAILQ_INIT(&(p->dp_ctx_in_q));
@@ -1779,6 +1828,14 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
                if (ctx == NULL)
                        break;
 
+               /* A previous provider plugin may have asked to skip the
+                * kernel update.
+                */
+               if (dplane_ctx_is_skip_kernel(ctx)) {
+                       res = ZEBRA_DPLANE_REQUEST_SUCCESS;
+                       goto skip_one;
+               }
+
                /* Dispatch to appropriate kernel-facing apis */
                switch (dplane_ctx_get_op(ctx)) {
 
@@ -1808,6 +1865,7 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
                        break;
                }
 
+skip_one:
                dplane_ctx_set_status(ctx, res);
 
                dplane_provider_enqueue_out_ctx(prov, ctx);
index 81226961e85d97c6e95157576f409b222c6994df..1246fcc8ec1d9d25920b4d0d5afd197b0f008463 100644 (file)
 #include "zebra/zserv.h"
 #include "zebra/zebra_mpls.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Key netlink info from zebra ns */
 struct zebra_dplane_info {
        ns_id_t ns_id;
@@ -203,8 +207,9 @@ const struct nexthop_group *dplane_ctx_get_old_ng(
 mpls_label_t dplane_ctx_get_in_label(const struct zebra_dplane_ctx *ctx);
 uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx);
 uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx);
-zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx);
-zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx);
+const zebra_nhlfe_t *dplane_ctx_get_nhlfe(const struct zebra_dplane_ctx *ctx);
+const zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(
+       const struct zebra_dplane_ctx *ctx);
 uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
 
 /* Accessors for pseudowire information */
@@ -215,10 +220,12 @@ int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
 int dplane_ctx_get_pw_af(const struct zebra_dplane_ctx *ctx);
 uint32_t dplane_ctx_get_pw_flags(const struct zebra_dplane_ctx *ctx);
 int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx);
-const union g_addr *dplane_ctx_get_pw_nexthop(
+const union g_addr *dplane_ctx_get_pw_dest(
        const struct zebra_dplane_ctx *ctx);
 const union pw_protocol_fields *dplane_ctx_get_pw_proto(
        const struct zebra_dplane_ctx *ctx);
+const struct nexthop_group *dplane_ctx_get_pw_nhg(
+       const struct zebra_dplane_ctx *ctx);
 
 /* Namespace info - esp. for netlink communication */
 const struct zebra_dplane_info *dplane_ctx_get_ns(
@@ -391,4 +398,8 @@ void zebra_dplane_pre_finish(void);
 void zebra_dplane_finish(void);
 void zebra_dplane_shutdown(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_DPLANE_H */
index 0af5f8a5514ac57a7662590c50d40a82d2dc1f9e..2b7831a408277720de3eb416098569bd61eb1d4b 100644 (file)
 
 #include "lib/ferr.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 enum zebra_log_refs {
        EC_ZEBRA_LM_RESPONSE = ZEBRA_FERR_START,
        EC_ZEBRA_LM_NO_SUCH_CLIENT,
@@ -126,4 +130,8 @@ enum zebra_log_refs {
 
 void zebra_error_init(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __EC_ZEBRAORS_H__ */
index 969ab6cfee3b01f65812b893348c8442e00b5482..943aad98642c754537e5c2db2530d993fc6769ba 100644 (file)
 
 #include "zebra/debug.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
 
 #define zfpm_debug(...)                                                        \
@@ -61,4 +65,9 @@ extern int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re,
                                      uint8_t *in_buf, size_t in_buf_len);
 
 extern struct route_entry *zfpm_route_for_update(rib_dest_t *dest);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_FPM_PRIVATE_H */
index 68c9d4a7a1a72bbf072da5a105aabd4a04eb2179..2e3e5b4a855b82a9903052b5760e5f14b3e268b9 100644 (file)
 #include "vlan.h"
 #include "vxlan.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* zebra L2 interface information - bridge slave (linkage to bridge) */
 struct zebra_l2info_brslave {
        ifindex_t bridge_ifindex; /* Bridge Master */
@@ -96,4 +100,9 @@ extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
 
 extern void zebra_l2if_update_bond_slave(struct interface *ifp,
                                         ifindex_t bond_ifindex);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_L2_H */
index de55478de2fc841d59b810063e0a83d8f31de1d4..667c73b2270fd348ef6bf8886dc31085c3e0c05c 100644 (file)
 
 #include "memory.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 DECLARE_MGROUP(ZEBRA)
 DECLARE_MTYPE(RTADV_PREFIX)
 DECLARE_MTYPE(ZEBRA_NS)
@@ -37,4 +41,8 @@ DECLARE_MTYPE(RNH)
 DECLARE_MTYPE(DP_CTX)
 DECLARE_MTYPE(DP_PROV)
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _QUAGGA_ZEBRA_MEMORY_H */
index c5c147c833e3d592be179ec4148d3ef70e651d63..90a5a41fa4f2b2a3346d2ea00c8538534b170553 100644 (file)
 
 #include "mlag.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void zebra_mlag_init(void);
 void zebra_mlag_terminate(void);
 
 enum mlag_role zebra_mlag_get_role(void);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index a06e15d90d4faf286b13d00cd090d13c04da09d3..5c375a6befc00018e8015c09052021644036c824 100644 (file)
@@ -249,8 +249,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
                                   lsp->ile.in_label, lsp->flags);
 
                lsp = hash_release(lsp_table, &lsp->ile);
-               if (lsp)
-                       XFREE(MTYPE_LSP, lsp);
+               XFREE(MTYPE_LSP, lsp);
        }
 
        return 0;
@@ -313,8 +312,7 @@ static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label)
                                   lsp->ile.in_label, lsp->flags);
 
                lsp = hash_release(lsp_table, &lsp->ile);
-               if (lsp)
-                       XFREE(MTYPE_LSP, lsp);
+               XFREE(MTYPE_LSP, lsp);
        }
 
        return 0;
@@ -1048,8 +1046,7 @@ static void lsp_processq_del(struct work_queue *wq, void *data)
                                   lsp->ile.in_label, lsp->flags);
 
                lsp = hash_release(lsp_table, &lsp->ile);
-               if (lsp)
-                       XFREE(MTYPE_LSP, lsp);
+               XFREE(MTYPE_LSP, lsp);
        }
 }
 
@@ -1335,8 +1332,7 @@ static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
                                   lsp->ile.in_label, lsp->flags);
 
                lsp = hash_release(lsp_table, &lsp->ile);
-               if (lsp)
-                       XFREE(MTYPE_LSP, lsp);
+               XFREE(MTYPE_LSP, lsp);
        }
 
        return 0;
@@ -1659,8 +1655,7 @@ static int snhlfe_del(zebra_snhlfe_t *snhlfe)
                slsp->snhlfe_list = snhlfe->next;
 
        snhlfe->prev = snhlfe->next = NULL;
-       if (snhlfe->ifname)
-               XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname);
+       XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname);
        XFREE(MTYPE_SNHLFE, snhlfe);
 
        return 0;
@@ -2539,8 +2534,7 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
                                           lsp->ile.in_label, lsp->flags);
 
                        lsp = hash_release(lsp_table, &lsp->ile);
-                       if (lsp)
-                               XFREE(MTYPE_LSP, lsp);
+                       XFREE(MTYPE_LSP, lsp);
                }
        }
        return 0;
@@ -2784,8 +2778,7 @@ int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label,
         * above. */
        if (!slsp->snhlfe_list) {
                slsp = hash_release(slsp_table, &tmp_ile);
-               if (slsp)
-                       XFREE(MTYPE_SLSP, slsp);
+               XFREE(MTYPE_SLSP, slsp);
        }
 
        return 0;
index 39f084ad2f7bbee121a52f265faca0d19efb208c..3a131e1aaf1224ca637ef7573e1f4370c69ebbfd 100644 (file)
@@ -34,6 +34,9 @@
 #include "zebra/zserv.h"
 #include "zebra/zebra_vrf.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* Definitions and macros. */
 
@@ -507,31 +510,48 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
        return "Unknown";
 }
 
-static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf)
+static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf,
+                                                struct prefix *p)
 {
+       struct route_table *table;
+       struct route_node *rn;
+       rib_dest_t *dest;
+
        if (!zvrf)
                return;
 
-       zvrf->mpls_flags |= MPLS_FLAG_SCHEDULE_LSPS;
+       table = zvrf->table[family2afi(p->family)][SAFI_UNICAST];
+       if (!table)
+               return;
+
+       rn = route_node_match(table, p);
+       if (!rn)
+               return;
+
+
+       dest = rib_dest_from_rnode(rn);
+       SET_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS);
 }
 
-static inline void mpls_unmark_lsps_for_processing(struct zebra_vrf *zvrf)
+static inline void mpls_unmark_lsps_for_processing(struct route_node *rn)
 {
-       if (!zvrf)
-               return;
+       rib_dest_t *dest = rib_dest_from_rnode(rn);
 
-       zvrf->mpls_flags &= ~MPLS_FLAG_SCHEDULE_LSPS;
+       UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS);
 }
 
-static inline int mpls_should_lsps_be_processed(struct zebra_vrf *zvrf)
+static inline int mpls_should_lsps_be_processed(struct route_node *rn)
 {
-       if (!zvrf)
-               return 0;
+       rib_dest_t *dest = rib_dest_from_rnode(rn);
 
-       return ((zvrf->mpls_flags & MPLS_FLAG_SCHEDULE_LSPS) ? 1 : 0);
+       return !!CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS);
 }
 
 /* Global variables. */
 extern int mpls_enabled;
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_ZEBRA_MPLS_H */
index 72c8f73522116c41965231cb784fd661c93b4baa..977a8eaf3c7711d7a3c9b464f1d70c909d33cbc7 100644 (file)
@@ -43,7 +43,7 @@ struct {
 } kr_state;
 
 static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
-                               zebra_nhlfe_t *nhlfe)
+                               const zebra_nhlfe_t *nhlfe)
 {
        struct iovec iov[5];
        struct rt_msghdr hdr;
@@ -135,7 +135,7 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
 #endif
 
 static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
-                               zebra_nhlfe_t *nhlfe)
+                               const zebra_nhlfe_t *nhlfe)
 {
        struct iovec iov[5];
        struct rt_msghdr hdr;
@@ -238,7 +238,7 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
 
 static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx)
 {
-       zebra_nhlfe_t *nhlfe;
+       const zebra_nhlfe_t *nhlfe;
        struct nexthop *nexthop = NULL;
        unsigned int nexthop_num = 0;
        int action;
@@ -342,7 +342,7 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
 
        /* pseudowire nexthop */
        memset(&ss, 0, sizeof(ss));
-       gaddr = dplane_ctx_get_pw_nexthop(ctx);
+       gaddr = dplane_ctx_get_pw_dest(ctx);
        switch (dplane_ctx_get_pw_af(ctx)) {
        case AF_INET:
                sa_in->sin_family = AF_INET;
@@ -415,7 +415,7 @@ enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
                break;
        default:
                break;
-       };
+       }
 
        return result;
 }
index 33851536005faa3dc64b013ae5dc48840c8b985d..3c12b82da3ed2380bd279304522430d043513127 100644 (file)
 
 #include "zebra/zserv.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct mcast_route_data {
        struct prefix_sg sg;
        unsigned int ifindex;
@@ -32,4 +36,8 @@ struct mcast_route_data {
 
 void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index d6530e6694877d7bdbf6c0fceadafeff0f58bf67..7a5f6851f481f94cc11eeaeca0c26a1a781b5215 100644 (file)
 #include "zebra.h"
 #include "ns.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern ns_id_t zebra_ns_id_get(const char *netnspath);
 extern ns_id_t zebra_ns_id_get_default(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __ZEBRA_NS_ID_H__ */
index 0ced749ae821b63aede0e3ee47309971743f85bd..18939283a70783dc47f1cdb6ac0356a52dcc4f30 100644 (file)
 #ifndef _NETNS_NOTIFY_H
 #define _NETNS_NOTIFY_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern void zebra_ns_notify_init(void);
 extern void zebra_ns_notify_parse(void);
 extern void zebra_ns_notify_close(void);
 
 extern struct zebra_privs_t zserv_privs;
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* NETNS_NOTIFY_H */
index 01af64c17bba2e7ca349adf921d3ccf41232e64c..dc79a83db0d878216b57ac9cde2231871acaccdb 100644 (file)
 #include "zebra/rib.h"
 #include "zebra/zebra_vrf.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef HAVE_NETLINK
 /* Socket interface to kernel */
 struct nlsock {
@@ -68,4 +72,8 @@ int zebra_ns_final_shutdown(struct ns *ns);
 
 int zebra_ns_config_write(struct vty *vty, struct ns *ns);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index 348bdeb9fca87653fc8084d4463de10150ed6e15..73db567eace35a52a1e6427f120504060025ae27 100644 (file)
@@ -388,7 +388,7 @@ bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
        r2 = (const struct zebra_pbr_iptable *)arg2;
 
        if (r1->vrf_id != r2->vrf_id)
-               return 0;
+               return false;
        if (r1->type != r2->type)
                return false;
        if (r1->unique != r2->unique)
index 5b6c23896c13f5ce5028df14ad1467725dbb6523..0d55491107604c39635939a8475b7affe9b43eaa 100644 (file)
 #include "rt.h"
 #include "pbr.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct zebra_pbr_rule {
        int sock;
 
@@ -252,4 +256,8 @@ DECLARE_HOOK(zebra_pbr_ipset_entry_update,
 DECLARE_HOOK(zebra_pbr_ipset_update,
             (int cmd, struct zebra_pbr_ipset *ipset), (cmd, ipset));
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_PBR_H */
index 1e942d6433f9f8642a9704994ad498f6ed6e30bd..bb352dc2ffd698fb3176500324cbf928b4c7979c 100644 (file)
@@ -328,7 +328,7 @@ DEFUN (zebra_ptm_enable_if,
        if (!old_ptm_enable && ptm_cb.ptm_enable) {
                if (!if_is_operative(ifp) && send_linkdown) {
                        if (IS_ZEBRA_DEBUG_EVENT)
-                               zlog_debug("%s: Bringing down interface %s\n",
+                               zlog_debug("%s: Bringing down interface %s",
                                           __func__, ifp->name);
                        if_down(ifp);
                }
@@ -354,7 +354,7 @@ DEFUN (no_zebra_ptm_enable_if,
                ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
                if (if_is_no_ptm_operative(ifp) && send_linkup) {
                        if (IS_ZEBRA_DEBUG_EVENT)
-                               zlog_debug("%s: Bringing up interface %s\n",
+                               zlog_debug("%s: Bringing up interface %s",
                                           __func__, ifp->name);
                        if_up(ifp);
                }
@@ -1215,8 +1215,6 @@ static struct ptm_process *pp_new(pid_t pid, struct zserv *zs)
 
        /* Allocate and register new process. */
        pp = XCALLOC(MTYPE_ZEBRA_PTM_BFD_PROCESS, sizeof(*pp));
-       if (pp == NULL)
-               return NULL;
 
        pp->pp_pid = pid;
        pp->pp_zs = zs;
index d0cdaf0bce8781f7409d297a0c041ad43d42a973..e578a02a94a4581330147b1244f20fdb5760b831 100644 (file)
@@ -31,6 +31,10 @@ extern const char ZEBRA_PTM_SOCK_NAME[];
 #include "zebra/zserv.h"
 #include "zebra/interface.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Zebra ptm context block */
 struct zebra_ptm_cb {
        int ptm_sock; /* ptm file descriptor. */
@@ -87,4 +91,9 @@ void zebra_ptm_if_init(struct zebra_if *zebra_ifp);
 void zebra_ptm_if_set_ptm_state(struct interface *ifp,
                                struct zebra_if *zebra_ifp);
 void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index c1b12bd0d18eac9310f4b359245a3114912bf202..4daf405825372f82f6a572c25742a56a1ce61e2b 100644 (file)
 
 #ifndef _ZEBRA_PTM_REDISTRIBUTE_H
 #define _ZEBRA_PTM_REDISTRIBUTE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern void zebra_interface_bfd_update(struct interface *, struct prefix *,
                                       struct prefix *, int, vrf_id_t);
 extern void zebra_bfd_peer_replay_req(void);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_PTM_REDISTRIBUTE_H */
index 9692fb4d40dd8fb6ff746dfe59bebabee17ee634..bbb37767251486b0f5b7df2f0a5350e45d9b4d75 100644 (file)
 
 #include "zebra/zebra_vrf.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define PW_INSTALL_RETRY_INTERVAL      30
 
 struct zebra_pw {
@@ -74,4 +78,8 @@ void zebra_pw_init(struct zebra_vrf *);
 void zebra_pw_exit(struct zebra_vrf *);
 void zebra_pw_vty_init(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* ZEBRA_PW_H_ */
index de1aa7d6d89490849fd33b2d4eebf2a5038b3288..557e6876e2ced199605eb30f0921423437bc1f40 100644 (file)
@@ -1175,10 +1175,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
                if (zebra_rib_labeled_unicast(re))
                        zebra_mpls_lsp_uninstall(info->zvrf, rn, re);
 
-               if (!RIB_SYSTEM_ROUTE(re))
-                       rib_uninstall_kernel(rn, re);
-               else
-                       UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
+               rib_uninstall_kernel(rn, re);
 
                dest->selected_fib = NULL;
 
@@ -1207,6 +1204,16 @@ static int rib_can_delete_dest(rib_dest_t *dest)
                return 0;
        }
 
+       /*
+        * Unresolved rnh's are stored on the default route's list
+        *
+        * dest->rnode can also be the source prefix node in an
+        * ipv6 sourcedest table.  Fortunately the prefix of a
+        * source prefix node can never be the default prefix.
+        */
+       if (is_default_prefix(&dest->rnode->p))
+               return 0;
+
        /*
         * Don't delete the dest if we have to update the FPM about this
         * prefix.
@@ -1218,6 +1225,88 @@ static int rib_can_delete_dest(rib_dest_t *dest)
        return 1;
 }
 
+void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
+{
+       rib_dest_t *dest = rib_dest_from_rnode(rn);
+       struct listnode *node, *nnode;
+       struct rnh *rnh;
+
+       /*
+        * We are storing the rnh's associated withb
+        * the tracked nexthop as a list of the rn's.
+        * Unresolved rnh's are placed at the top
+        * of the tree list.( 0.0.0.0/0 for v4 and 0::0/0 for v6 )
+        * As such for each rn we need to walk up the tree
+        * and see if any rnh's need to see if they
+        * would match a more specific route
+        */
+       while (rn) {
+               if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
+                       char buf[PREFIX_STRLEN];
+
+                       zlog_debug("%s: %s Being examined for Nexthop Tracking",
+                                  __PRETTY_FUNCTION__,
+                                  srcdest_rnode2str(rn, buf, sizeof(buf)));
+               }
+               if (!dest) {
+                       rn = rn->parent;
+                       if (rn)
+                               dest = rib_dest_from_rnode(rn);
+                       continue;
+               }
+               /*
+                * If we have any rnh's stored in the nht list
+                * then we know that this route node was used for
+                * nht resolution and as such we need to call the
+                * nexthop tracking evaluation code
+                */
+               for (ALL_LIST_ELEMENTS(dest->nht, node, nnode, rnh)) {
+                       struct zebra_vrf *zvrf =
+                               zebra_vrf_lookup_by_id(rnh->vrf_id);
+                       struct prefix *p = &rnh->node->p;
+
+                       if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
+                               char buf1[PREFIX_STRLEN];
+                               char buf2[PREFIX_STRLEN];
+
+                               zlog_debug("%u:%s has Nexthop(%s) depending on it, evaluating %u:%u",
+                                          zvrf->vrf->vrf_id,
+                                          srcdest_rnode2str(rn, buf1,
+                                                     sizeof(buf1)),
+                                          prefix2str(p, buf2, sizeof(buf2)),
+                                          seq, rnh->seqno);
+                       }
+
+                       /*
+                        * If we have evaluated this node on this pass
+                        * already, due to following the tree up
+                        * then we know that we can move onto the next
+                        * rnh to process.
+                        *
+                        * Additionally we call zebra_evaluate_rnh
+                        * when we gc the dest.  In this case we know
+                        * that there must be no other re's where
+                        * we were originally as such we know that
+                        * that sequence number is ok to respect.
+                        */
+                       if (rnh->seqno == seq) {
+                               if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+                                       zlog_debug(
+                                               "\tNode processed and moved already");
+                               continue;
+                       }
+
+                       rnh->seqno = seq;
+                       zebra_evaluate_rnh(zvrf, family2afi(p->family), 0,
+                                          rnh->type, p);
+               }
+
+               rn = rn->parent;
+               if (rn)
+                       dest = rib_dest_from_rnode(rn);
+       }
+}
+
 /*
  * rib_gc_dest
  *
@@ -1244,7 +1333,10 @@ int rib_gc_dest(struct route_node *rn)
                rnode_debug(rn, zvrf_id(zvrf), "removing dest from table");
        }
 
+       zebra_rib_evaluate_rn_nexthops(rn, zebra_router_get_next_sequence());
+
        dest->rnode = NULL;
+       list_delete(&dest->nht);
        XFREE(MTYPE_RIB_DEST, dest);
        rn->info = NULL;
 
@@ -1258,8 +1350,6 @@ int rib_gc_dest(struct route_node *rn)
 static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
                                struct route_entry *new)
 {
-       rib_dest_t *dest = rib_dest_from_rnode(rn);
-
        hook_call(rib_update, rn, "new route selected");
 
        /* Update real nexthop. This may actually determine if nexthop is active
@@ -1281,10 +1371,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
        if (zebra_rib_labeled_unicast(new))
                zebra_mpls_lsp_install(zvrf, rn, new);
 
-       if (!RIB_SYSTEM_ROUTE(new))
-               rib_install_kernel(rn, new, NULL);
-       else
-               dest->selected_fib = new;
+       rib_install_kernel(rn, new, NULL);
 
        UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
 }
@@ -1292,7 +1379,6 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
 static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
                                struct route_entry *old)
 {
-       rib_dest_t *dest = rib_dest_from_rnode(rn);
        hook_call(rib_update, rn, "removing existing route");
 
        /* Uninstall from kernel. */
@@ -1308,20 +1394,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
        if (zebra_rib_labeled_unicast(old))
                zebra_mpls_lsp_uninstall(zvrf, rn, old);
 
-       if (!RIB_SYSTEM_ROUTE(old))
-               rib_uninstall_kernel(rn, old);
-       else {
-               UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
-               /*
-                * We are setting this to NULL here
-                * because that is what we traditionally
-                * have been doing.  I am not positive
-                * that this is the right thing to do
-                * but let's leave the code alone
-                * for the RIB_SYSTEM_ROUTE case
-                */
-               dest->selected_fib = NULL;
-       }
+       rib_uninstall_kernel(rn, old);
 
        /* Update nexthop for route, reset changed flag. */
        /* Note: this code also handles the Linux case when an interface goes
@@ -1340,9 +1413,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
                                   struct route_entry *old,
                                   struct route_entry *new)
 {
-       struct nexthop *nexthop = NULL;
        int nh_active = 0;
-       rib_dest_t *dest = rib_dest_from_rnode(rn);
 
        /*
         * We have to install or update if a new route has been selected or
@@ -1384,48 +1455,15 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
                        if (zebra_rib_labeled_unicast(old))
                                zebra_mpls_lsp_uninstall(zvrf, rn, old);
 
-                       /* Non-system route should be installed. */
-                       if (!RIB_SYSTEM_ROUTE(new)) {
-                               /* If labeled-unicast route, install transit
-                                * LSP. */
-                               if (zebra_rib_labeled_unicast(new))
-                                       zebra_mpls_lsp_install(zvrf, rn, new);
+                       /*
+                        * Non-system route should be installed.
+                        * If labeled-unicast route, install transit
+                        * LSP.
+                        */
+                       if (zebra_rib_labeled_unicast(new))
+                               zebra_mpls_lsp_install(zvrf, rn, new);
 
-                               rib_install_kernel(rn, new, old);
-                       } else {
-                               UNSET_FLAG(new->status, ROUTE_ENTRY_INSTALLED);
-                               /*
-                                * We do not need to install the
-                                * selected route because it
-                                * is already isntalled by
-                                * the system( ie not us )
-                                * so just mark it as winning
-                                * we do need to ensure that
-                                * if we uninstall a route
-                                * from ourselves we don't
-                                * over write this pointer
-                                */
-                               dest->selected_fib = NULL;
-                       }
-                       /* If install succeeded or system route, cleanup flags
-                        * for prior route. */
-                       if (new != old) {
-                               if (RIB_SYSTEM_ROUTE(new)) {
-                                       if (!RIB_SYSTEM_ROUTE(old))
-                                               rib_uninstall_kernel(rn, old);
-                                       else
-                                               UNSET_FLAG(
-                                                       old->status,
-                                                       ROUTE_ENTRY_INSTALLED);
-                               } else {
-                                       UNSET_FLAG(old->status,
-                                                  ROUTE_ENTRY_INSTALLED);
-                                       for (nexthop = old->ng.nexthop; nexthop;
-                                            nexthop = nexthop->next)
-                                               UNSET_FLAG(nexthop->flags,
-                                                          NEXTHOP_FLAG_FIB);
-                               }
-                       }
+                       rib_install_kernel(rn, new, old);
                }
 
                /*
@@ -1455,25 +1493,18 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
                        if (zebra_rib_labeled_unicast(old))
                                zebra_mpls_lsp_uninstall(zvrf, rn, old);
 
-                       if (!RIB_SYSTEM_ROUTE(old))
-                               rib_uninstall_kernel(rn, old);
-                       else {
-                               UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
-                               dest->selected_fib = NULL;
-                       }
+                       rib_uninstall_kernel(rn, old);
                }
        } else {
                /*
                 * Same route selected; check if in the FIB and if not,
-                * re-install. This
-                * is housekeeping code to deal with race conditions in kernel
-                * with linux
-                * netlink reporting interface up before IPv4 or IPv6 protocol
-                * is ready
+                * re-install. This is housekeeping code to deal with
+                * race conditions in kernel with linux netlink reporting
+                * interface up before IPv4 or IPv6 protocol is ready
                 * to add routes.
                 */
-               if (!RIB_SYSTEM_ROUTE(new)
-                   && !CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED))
+               if (!CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED) ||
+                   RIB_SYSTEM_ROUTE(new))
                        rib_install_kernel(rn, new, NULL);
        }
 
@@ -1725,18 +1756,9 @@ static void rib_process(struct route_node *rn)
                        UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED);
                }
 
-               if (new_selected) {
+               if (new_selected)
                        SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED);
 
-                       /* Special case: new route is system route, so
-                        * dataplane update will not be done - ensure we
-                        * redistribute the route.
-                        */
-                       if (RIB_SYSTEM_ROUTE(new_selected))
-                               redistribute_update(p, src_p, new_selected,
-                                                   old_selected);
-               }
-
                if (old_selected) {
                        if (!new_selected)
                                redistribute_delete(p, src_p, old_selected);
@@ -1763,6 +1785,24 @@ static void rib_process(struct route_node *rn)
        rib_gc_dest(rn);
 }
 
+static void zebra_rib_evaluate_mpls(struct route_node *rn)
+{
+       rib_dest_t *dest = rib_dest_from_rnode(rn);
+       struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
+
+       if (!dest)
+               return;
+
+       if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS)) {
+               if (IS_ZEBRA_DEBUG_MPLS)
+                       zlog_debug(
+                               "%u: Scheduling all LSPs upon RIB completion",
+                               zvrf_id(zvrf));
+               zebra_mpls_lsp_schedule(zvrf);
+               mpls_unmark_lsps_for_processing(rn);
+       }
+}
+
 /*
  * Utility to match route with dplane context data
  */
@@ -1821,6 +1861,30 @@ done:
        return (result);
 }
 
+static void zebra_rib_fixup_system(struct route_node *rn)
+{
+       struct route_entry *re;
+
+       RNODE_FOREACH_RE(rn, re) {
+               struct nexthop *nhop;
+
+               if (!RIB_SYSTEM_ROUTE(re))
+                       continue;
+
+               if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+                       continue;
+
+               SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
+
+               for (ALL_NEXTHOPS(re->ng, nhop)) {
+                       if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
+                               continue;
+
+                       SET_FLAG(nhop->flags, NEXTHOP_FLAG_FIB);
+               }
+       }
+}
+
 /*
  * Route-update results processing after async dataplane update.
  */
@@ -1836,6 +1900,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
        enum dplane_op_e op;
        enum zebra_dplane_result status;
        const struct prefix *dest_pfx, *src_pfx;
+       uint32_t seq;
 
        /* Locate rn and re(s) from ctx */
 
@@ -1912,11 +1977,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
                        break;
        }
 
+       seq = dplane_ctx_get_seq(ctx);
+
        /*
         * Check sequence number(s) to detect stale results before continuing
         */
        if (re) {
-               if (re->dplane_sequence != dplane_ctx_get_seq(ctx)) {
+               if (re->dplane_sequence != seq) {
                        if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
                                zlog_debug("%u:%s Stale dplane result for re %p",
                                           dplane_ctx_get_vrf(ctx),
@@ -1932,7 +1999,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
                                           dplane_ctx_get_vrf(ctx),
                                           dest_str, old_re);
                } else
-                       UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+                       UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED);
        }
 
        switch (op) {
@@ -1987,6 +2054,17 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
                                                   NEXTHOP_FLAG_FIB);
                        }
 
+                       /*
+                        * System routes are weird in that they
+                        * allow multiple to be installed that match
+                        * to the same prefix, so after we get the
+                        * result we need to clean them up so that
+                        * we can actually use them.
+                        */
+                       if ((re && RIB_SYSTEM_ROUTE(re)) ||
+                           (old_re && RIB_SYSTEM_ROUTE(old_re)))
+                               zebra_rib_fixup_system(rn);
+
                        if (zvrf) {
                                zvrf->installs++;
                                /* Set flag for nexthop tracking processing */
@@ -2010,9 +2088,10 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
                        zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
 
                } else {
-                       if (re)
+                       if (re) {
                                SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
-                       if (old_re)
+                               UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
+                       } if (old_re)
                                SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
                        if (re)
                                zsend_route_notify_owner(re, dest_pfx,
@@ -2052,10 +2131,24 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
                                  prefix2str(dest_pfx,
                                             dest_str, sizeof(dest_str)));
                }
+
+               /*
+                * System routes are weird in that they
+                * allow multiple to be installed that match
+                * to the same prefix, so after we get the
+                * result we need to clean them up so that
+                * we can actually use them.
+                */
+               if ((re && RIB_SYSTEM_ROUTE(re)) ||
+                   (old_re && RIB_SYSTEM_ROUTE(old_re)))
+                       zebra_rib_fixup_system(rn);
                break;
        default:
                break;
        }
+
+       zebra_rib_evaluate_rn_nexthops(rn, seq);
+       zebra_rib_evaluate_mpls(rn);
 done:
 
        if (rn)
@@ -2110,47 +2203,12 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex)
        return 1;
 }
 
+
 /*
  * Perform next-hop tracking processing after RIB updates.
  */
 static void do_nht_processing(void)
 {
-       struct vrf *vrf;
-       struct zebra_vrf *zvrf;
-
-       /* Evaluate nexthops for those VRFs which underwent route processing.
-        * This
-        * should limit the evaluation to the necessary VRFs in most common
-        * situations.
-        */
-       RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
-               zvrf = vrf->info;
-               if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED))
-                       continue;
-
-               if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHT)
-                       zlog_debug("NHT processing check for zvrf %s",
-                                  zvrf_name(zvrf));
-
-               zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED;
-               zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL);
-               zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_IMPORT_CHECK_TYPE,
-                                  NULL);
-               zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL);
-               zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_IMPORT_CHECK_TYPE,
-                                  NULL);
-       }
-
-       /* Schedule LSPs for processing, if needed. */
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
-       if (mpls_should_lsps_be_processed(zvrf)) {
-               if (IS_ZEBRA_DEBUG_MPLS)
-                       zlog_debug(
-                               "%u: Scheduling all LSPs upon RIB completion",
-                               zvrf_id(zvrf));
-               zebra_mpls_lsp_schedule(zvrf);
-               mpls_unmark_lsps_for_processing(zvrf);
-       }
 }
 
 /* Dispatch the meta queue by picking, processing and unlocking the next RN from
@@ -2340,6 +2398,19 @@ static void rib_queue_init(void)
        return;
 }
 
+rib_dest_t *zebra_rib_create_dest(struct route_node *rn)
+{
+       rib_dest_t *dest;
+
+       dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t));
+       dest->nht = list_new();
+       route_lock_node(rn); /* rn route table reference */
+       rn->info = dest;
+       dest->rnode = rn;
+
+       return dest;
+}
+
 /* RIB updates are processed via a queue of pointers to route_nodes.
  *
  * The queue length is bounded by the maximal size of the routing table,
@@ -2392,10 +2463,7 @@ static void rib_link(struct route_node *rn, struct route_entry *re, int process)
                if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                        rnode_debug(rn, re->vrf_id, "rn %p adding dest", rn);
 
-               dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t));
-               route_lock_node(rn); /* rn route table reference */
-               rn->info = dest;
-               dest->rnode = rn;
+               dest = zebra_rib_create_dest(rn);
        }
 
        head = dest->routes;
@@ -2654,7 +2722,7 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
         * revalidation
         * of the rest of the RE.
         */
-       if (dest->selected_fib && !RIB_SYSTEM_ROUTE(dest->selected_fib)) {
+       if (dest->selected_fib) {
                changed = 1;
                if (IS_ZEBRA_DEBUG_RIB) {
                        char buf[PREFIX_STRLEN];
@@ -2676,7 +2744,6 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
        struct route_table *table;
        struct route_node *rn;
        struct route_entry *same = NULL;
-       struct nexthop *nexthop;
        int ret = 0;
 
        if (!re)
@@ -2740,13 +2807,6 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
                        break;
        }
 
-       /* If this route is kernel route, set FIB flag to the route. */
-       if (RIB_SYSTEM_ROUTE(re)) {
-               SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
-               for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
-                       SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
-       }
-
        /* Link new re to node.*/
        if (IS_ZEBRA_DEBUG_RIB) {
                rnode_debug(rn, re->vrf_id,
@@ -3222,10 +3282,8 @@ void rib_close_table(struct route_table *table)
                        if (info->safi == SAFI_UNICAST)
                                hook_call(rib_update, rn, NULL);
 
-                       if (!RIB_SYSTEM_ROUTE(dest->selected_fib)) {
-                               rib_uninstall_kernel(rn, dest->selected_fib);
-                               dest->selected_fib = NULL;
-                       }
+                       rib_uninstall_kernel(rn, dest->selected_fib);
+                       dest->selected_fib = NULL;
                }
        }
 }
@@ -3235,7 +3293,6 @@ void rib_close_table(struct route_table *table)
  */
 static int handle_pw_result(struct zebra_dplane_ctx *ctx)
 {
-       int ret = 0;
        struct zebra_pw *pw;
        struct zebra_vrf *vrf;
 
@@ -3254,7 +3311,7 @@ static int handle_pw_result(struct zebra_dplane_ctx *ctx)
 
 done:
 
-       return ret;
+       return 0;
 }
 
 
index 52637c6062d01ee4679cb17ec3f198f1bdf34f66..a1519e45cd6d7415471430a5d7ca5fdb7365d812 100644 (file)
@@ -94,6 +94,61 @@ char *rnh_str(struct rnh *rnh, char *buf, int size)
        return buf;
 }
 
+static void zebra_rnh_remove_from_routing_table(struct rnh *rnh)
+{
+       struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id);
+       struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST];
+       struct route_node *rn;
+       rib_dest_t *dest;
+
+       if (!table)
+               return;
+
+       rn = route_node_match(table, &rnh->resolved_route);
+       if (!rn)
+               return;
+
+       if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
+               char buf[PREFIX_STRLEN];
+               char buf1[PREFIX_STRLEN];
+
+               zlog_debug("%s: %u:%s removed from tracking on %s",
+                          __PRETTY_FUNCTION__, rnh->vrf_id,
+                          prefix2str(&rnh->node->p, buf, sizeof(buf)),
+                          srcdest_rnode2str(rn, buf1, sizeof(buf)));
+       }
+
+       dest = rib_dest_from_rnode(rn);
+       listnode_delete(dest->nht, rnh);
+       route_unlock_node(rn);
+}
+
+static void zebra_rnh_store_in_routing_table(struct rnh *rnh)
+{
+       struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id);
+       struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST];
+       struct route_node *rn;
+       rib_dest_t *dest;
+
+       rn = route_node_match(table, &rnh->resolved_route);
+       if (!rn)
+               return;
+
+       if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
+               char buf[PREFIX_STRLEN];
+               char buf1[PREFIX_STRLEN];
+
+               zlog_debug("%s: %u:%s added for tracking on %s",
+                          __PRETTY_FUNCTION__, rnh->vrf_id,
+                          prefix2str(&rnh->node->p, buf, sizeof(buf)),
+                          srcdest_rnode2str(rn, buf1, sizeof(buf)));
+       }
+
+       dest = rib_dest_from_rnode(rn);
+       listnode_add(dest->nht, rnh);
+       route_unlock_node(rn);
+}
+
 struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
                          bool *exists)
 {
@@ -101,12 +156,13 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
        struct route_node *rn;
        struct rnh *rnh = NULL;
        char buf[PREFIX2STR_BUFFER];
+       afi_t afi = family2afi(p->family);
 
        if (IS_ZEBRA_DEBUG_NHT) {
                prefix2str(p, buf, sizeof(buf));
                zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type);
        }
-       table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type);
+       table = get_rnh_table(vrfid, afi, type);
        if (!table) {
                prefix2str(p, buf, sizeof(buf));
                flog_warn(EC_ZEBRA_RNH_NO_TABLE,
@@ -124,13 +180,26 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
 
        if (!rn->info) {
                rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh));
+
+               /*
+                * The resolved route is already 0.0.0.0/0 or
+                * 0::0/0 due to the calloc right above, but
+                * we should set the family so that future
+                * comparisons can just be done
+                */
+               rnh->resolved_route.family = p->family;
                rnh->client_list = list_new();
                rnh->vrf_id = vrfid;
+               rnh->type = type;
+               rnh->seqno = 0;
+               rnh->afi = afi;
                rnh->zebra_pseudowire_list = list_new();
                route_lock_node(rn);
                rn->info = rnh;
                rnh->node = rn;
                *exists = false;
+
+               zebra_rnh_store_in_routing_table(rnh);
        } else
                *exists = true;
 
@@ -161,9 +230,30 @@ struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
 
 void zebra_free_rnh(struct rnh *rnh)
 {
+       struct zebra_vrf *zvrf;
+       struct route_table *table;
+
+       zebra_rnh_remove_from_routing_table(rnh);
        rnh->flags |= ZEBRA_NHT_DELETED;
        list_delete(&rnh->client_list);
        list_delete(&rnh->zebra_pseudowire_list);
+
+       zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id);
+       table = zvrf->table[family2afi(rnh->resolved_route.family)][SAFI_UNICAST];
+
+       if (table) {
+               struct route_node *rern;
+
+               rern = route_node_match(table, &rnh->resolved_route);
+               if (rern) {
+                       rib_dest_t *dest;
+
+                       route_unlock_node(rern);
+
+                       dest = rib_dest_from_rnode(rern);
+                       listnode_delete(dest->nht, rnh);
+               }
+       }
        free_state(rnh->vrf_id, rnh->state, rnh->node);
        XFREE(MTYPE_RNH, rnh);
 }
@@ -344,6 +434,16 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi,
            && !prefix_same(&nrn->p, &rn->p))
                return NULL;
 
+       if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
+               char buf[PREFIX_STRLEN];
+               char buf1[PREFIX_STRLEN];
+
+               zlog_debug("%s: %u:%s Resolved Import Entry to %s",
+                          __PRETTY_FUNCTION__, rnh->vrf_id,
+                          prefix2str(&rnh->node->p, buf, sizeof(buf)),
+                          srcdest_rnode2str(rn, buf1, sizeof(buf)));
+       }
+
        /* Identify appropriate route entry. */
        RNODE_FOREACH_RE (rn, re) {
                if (!CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)
@@ -354,6 +454,10 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi,
 
        if (re)
                *prn = rn;
+
+       if (!re && IS_ZEBRA_DEBUG_NHT_DETAILED)
+               zlog_debug("\tRejected due to removed or is a bgp route");
+
        return re;
 }
 
@@ -361,9 +465,10 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi,
  * See if a tracked route entry for import (by BGP) has undergone any
  * change, and if so, notify the client.
  */
-static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, afi_t afi,
+static void zebra_rnh_eval_import_check_entry(struct zebra_vrf *zvrf, afi_t afi,
                                              int force, struct route_node *nrn,
                                              struct rnh *rnh,
+                                             struct route_node *prn,
                                              struct route_entry *re)
 {
        int state_changed = 0;
@@ -371,25 +476,40 @@ static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, afi_t afi,
        char bufn[INET6_ADDRSTRLEN];
        struct listnode *node;
 
+       zebra_rnh_remove_from_routing_table(rnh);
+       if (prn) {
+               prefix_copy(&rnh->resolved_route, &prn->p);
+       } else {
+               int family = rnh->resolved_route.family;
+
+               memset(&rnh->resolved_route.family, 0, sizeof(struct prefix));
+               rnh->resolved_route.family = family;
+       }
+       zebra_rnh_store_in_routing_table(rnh);
+
        if (re && (rnh->state == NULL)) {
                if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
                        state_changed = 1;
        } else if (!re && (rnh->state != NULL))
                state_changed = 1;
 
-       if (compare_state(re, rnh->state))
+       if (compare_state(re, rnh->state)) {
                copy_state(rnh, re, nrn);
+               state_changed = 1;
+       }
 
        if (state_changed || force) {
                if (IS_ZEBRA_DEBUG_NHT) {
                        prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
-                       zlog_debug("%u:%s: Route import check %s %s\n", vrfid,
+                       zlog_debug("%u:%s: Route import check %s %s",
+                                  zvrf->vrf->vrf_id,
                                   bufn, rnh->state ? "passed" : "failed",
                                   state_changed ? "(state changed)" : "");
                }
                /* state changed, notify clients */
                for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
-                       send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid);
+                       send_client(rnh, client,
+                                   RNH_IMPORT_CHECK_TYPE, zvrf->vrf->vrf_id);
                }
        }
 }
@@ -412,7 +532,7 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi,
        if (IS_ZEBRA_DEBUG_NHT) {
                prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
                if (prn && re) {
-                       prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN);
+                       srcdest_rnode2str(prn, bufp, INET6_ADDRSTRLEN);
                        zlog_debug("%u:%s: NH resolved over route %s",
                                   zvrf->vrf->vrf_id, bufn, bufp);
                } else
@@ -545,19 +665,43 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
         * most-specific match. Do similar logic as in zebra_rib.c
         */
        while (rn) {
+               if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
+                       char buf[PREFIX_STRLEN];
+                       char buf1[PREFIX_STRLEN];
+
+                       zlog_debug("%s: %u:%s Possible Match to %s",
+                                  __PRETTY_FUNCTION__, rnh->vrf_id,
+                                  prefix2str(&rnh->node->p, buf, sizeof(buf)),
+                                  srcdest_rnode2str(rn, buf1, sizeof(buf)));
+               }
+
                /* Do not resolve over default route unless allowed &&
                 * match route to be exact if so specified
                 */
                if (is_default_prefix(&rn->p)
-                   && !rnh_resolve_via_default(rn->p.family))
+                   && !rnh_resolve_via_default(rn->p.family)) {
+                       if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+                               zlog_debug(
+                                       "\tNot allowed to resolve through default prefix");
                        return NULL;
+               }
 
                /* Identify appropriate route entry. */
                RNODE_FOREACH_RE (rn, re) {
-                       if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+                       if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
+                               if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+                                       zlog_debug(
+                                               "\tRoute Entry %s removed",
+                                               zebra_route_string(re->type));
                                continue;
-                       if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
+                       }
+                       if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
+                               if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+                                       zlog_debug(
+                                               "\tRoute Entry %s !selected",
+                                               zebra_route_string(re->type));
                                continue;
+                       }
 
                        /* Just being SELECTED isn't quite enough - must
                         * have an installed nexthop to be useful.
@@ -567,8 +711,13 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
                                        break;
                        }
 
-                       if (nexthop == NULL)
+                       if (nexthop == NULL) {
+                               if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+                                       zlog_debug(
+                                               "\tRoute Entry %s no nexthops",
+                                               zebra_route_string(re->type));
                                continue;
+                       }
 
                        if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) {
                                if ((re->type == ZEBRA_ROUTE_CONNECT)
@@ -594,10 +743,14 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
                        return re;
                }
 
-               if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
+               if (!CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
                        rn = rn->parent;
-               else
+               else {
+                       if (IS_ZEBRA_DEBUG_NHT_DETAILED)
+                               zlog_debug(
+                                       "\tNexthop must be connected, cannot recurse up");
                        return NULL;
+               }
        }
 
        return NULL;
@@ -629,11 +782,20 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
         * the resolving route has some change (e.g., metric), there is a state
         * change.
         */
-       if (!prefix_same(&rnh->resolved_route, &prn->p)) {
+       zebra_rnh_remove_from_routing_table(rnh);
+       if (!prefix_same(&rnh->resolved_route, prn ? NULL : &prn->p)) {
                if (prn)
                        prefix_copy(&rnh->resolved_route, &prn->p);
-               else
+               else {
+                       /*
+                        * Just quickly store the family of the resolved
+                        * route so that we can reset it in a second here
+                        */
+                       int family = rnh->resolved_route.family;
+
                        memset(&rnh->resolved_route, 0, sizeof(struct prefix));
+                       rnh->resolved_route.family = family;
+               }
 
                copy_state(rnh, re, nrn);
                state_changed = 1;
@@ -641,6 +803,7 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
                copy_state(rnh, re, nrn);
                state_changed = 1;
        }
+       zebra_rnh_store_in_routing_table(rnh);
 
        if (state_changed || force) {
                /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e.,
@@ -689,8 +852,8 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
 
        /* Process based on type of entry. */
        if (type == RNH_IMPORT_CHECK_TYPE)
-               zebra_rnh_eval_import_check_entry(zvrf->vrf->vrf_id, afi, force,
-                                                 nrn, rnh, re);
+               zebra_rnh_eval_import_check_entry(zvrf, afi, force, nrn, rnh,
+                                                 prn, re);
        else
                zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn,
                                             re);
@@ -775,7 +938,7 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
 
        table = get_rnh_table(vrfid, afi, type);
        if (!table) {
-               zlog_debug("print_rnhs: rnh table not found\n");
+               zlog_debug("print_rnhs: rnh table not found");
                return;
        }
 
@@ -790,7 +953,6 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
 static void free_state(vrf_id_t vrf_id, struct route_entry *re,
                       struct route_node *rn)
 {
-
        if (!re)
                return;
 
@@ -1025,7 +1187,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
 
        ntable = get_rnh_table(vrf_id, afi, type);
        if (!ntable) {
-               zlog_debug("cleanup_rnh_client: rnh table not found\n");
+               zlog_debug("cleanup_rnh_client: rnh table not found");
                return -1;
        }
 
index 00ee60dc1a8c7efff632598ef28209abd4523744..7d823c7acc7a4dd652cd26755c7a9815043a04fd 100644 (file)
 #include "prefix.h"
 #include "vty.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t;
+
 /* Nexthop structure. */
 struct rnh {
        uint8_t flags;
@@ -36,6 +42,12 @@ struct rnh {
        /* VRF identifier. */
        vrf_id_t vrf_id;
 
+       afi_t afi;
+
+       rnh_type_t type;
+
+       uint32_t seqno;
+
        struct route_entry *state;
        struct prefix resolved_route;
        struct list *client_list;
@@ -51,8 +63,6 @@ struct rnh {
        int filtered[ZEBRA_ROUTE_MAX];
 };
 
-typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t;
-
 extern int zebra_rnh_ip_default_route;
 extern int zebra_rnh_ipv6_default_route;
 
@@ -83,4 +93,9 @@ extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
 extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
                                  rnh_type_t);
 extern char *rnh_str(struct rnh *rnh, char *buf, int size);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_ZEBRA_RNH_H */
index 7d72583dd8b3420c769fb9cbc6de185a495fda56..5d1cbbe781d5de5b2f5ebbb5ae45000e946ab719 100644 (file)
@@ -127,10 +127,8 @@ static int zebra_route_match_delete(struct vty *vty, const char *command,
                break;
        }
 
-       if (dep_name)
-               XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
-       if (rmap_name)
-               XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+       XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+       XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
 
        return retval;
 }
index abd2ad78f750fc49ba9106ec5612d004c8968428..6a630e1ac089d9b2785e8f67a37e0784b7780bcc 100644 (file)
 
 #include "lib/routemap.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern void zebra_route_map_init(void);
 extern void zebra_routemap_config_write_protocol(struct vty *vty,
                                                 struct zebra_vrf *vrf);
@@ -48,4 +52,8 @@ zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p,
                          struct zebra_vrf *zvrf, struct route_entry *,
                          struct nexthop *nexthop);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index c3b861c2424b0f16a93c9f90f15bb12bb31ce4ae..9e09cbca3fb546efa986f93e9c4b56be956dd9a0 100644 (file)
@@ -164,14 +164,33 @@ static void zebra_router_free_table(struct zebra_router_table *zrt)
 {
        void *table_info;
 
-       rib_close_table(zrt->table);
-
        table_info = route_table_get_info(zrt->table);
        route_table_finish(zrt->table);
+       RB_REMOVE(zebra_router_table_head, &zrouter.tables, zrt);
+
        XFREE(MTYPE_RIB_TABLE_INFO, table_info);
        XFREE(MTYPE_ZEBRA_NS, zrt);
 }
 
+void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid,
+                               afi_t afi, safi_t safi)
+{
+       struct zebra_router_table finder;
+       struct zebra_router_table *zrt;
+
+       memset(&finder, 0, sizeof(finder));
+       finder.afi = afi;
+       finder.safi = safi;
+       finder.tableid = tableid;
+       finder.ns_id = zvrf->zns->ns_id;
+       zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
+
+       if (!zrt)
+               return;
+
+       zebra_router_free_table(zrt);
+}
+
 uint32_t zebra_router_get_next_sequence(void)
 {
        return 1
index fb28495917ab9990cebc06be458598cb0c3a7cfb..72b5e9b9b1e0088c392268f7fe8eb301a2fed031 100644 (file)
 
 #include "zebra/zebra_ns.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * This header file contains the idea of a router and as such
  * owns data that is associated with a router from zebra's
@@ -104,6 +108,11 @@ struct zebra_router {
 
        /* Mlag information for the router */
        struct zebra_mlag_info mlag_info;
+
+       /*
+        * The EVPN instance, if any
+        */
+       struct zebra_vrf *evpn_vrf;
 };
 
 extern struct zebra_router zrouter;
@@ -117,6 +126,8 @@ extern struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf,
 extern struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
                                                  uint32_t tableid, afi_t afi,
                                                  safi_t safi);
+extern void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid,
+                                      afi_t afi, safi_t safi);
 
 extern int zebra_router_config_write(struct vty *vty);
 
@@ -127,4 +138,19 @@ extern void zebra_router_sweep_route(void);
 extern void zebra_router_show_table_summary(struct vty *vty);
 
 extern uint32_t zebra_router_get_next_sequence(void);
+
+static inline vrf_id_t zebra_vrf_get_evpn_id(void)
+{
+       return zrouter.evpn_vrf ? zvrf_id(zrouter.evpn_vrf) : VRF_DEFAULT;
+}
+static inline struct zebra_vrf *zebra_vrf_get_evpn(void)
+{
+       return zrouter.evpn_vrf ? zrouter.evpn_vrf
+                               : zebra_vrf_lookup_by_id(VRF_DEFAULT);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index d18305495bc33bc1b59ce27aa7b102b8cf6e64cc..2d721ec8a1a53ca6e8a396e438b0184ace37ceb8 100644 (file)
@@ -167,6 +167,11 @@ static int zebra_vrf_disable(struct vrf *vrf)
 
        /* Remove all routes. */
        for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+               route_table_finish(zvrf->rnh_table[afi]);
+               zvrf->rnh_table[afi] = NULL;
+               route_table_finish(zvrf->import_check_table[afi]);
+               zvrf->import_check_table[afi] = NULL;
+
                for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
                        rib_close_table(zvrf->table[afi][safi]);
        }
@@ -208,13 +213,11 @@ static int zebra_vrf_disable(struct vrf *vrf)
                 * table, see rib_close_table above
                 * we no-longer need this pointer.
                 */
-               for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+               for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
+                       zebra_router_release_table(zvrf, zvrf->table_id, afi,
+                                                  safi);
                        zvrf->table[afi][safi] = NULL;
-
-               route_table_finish(zvrf->rnh_table[afi]);
-               zvrf->rnh_table[afi] = NULL;
-               route_table_finish(zvrf->import_check_table[afi]);
-               zvrf->import_check_table[afi] = NULL;
+               }
        }
 
        return 0;
@@ -256,19 +259,19 @@ static int zebra_vrf_delete(struct vrf *vrf)
 
        /* release allocated memory */
        for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
-               void *table_info;
-
                for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
                        table = zvrf->table[afi][safi];
                        if (table) {
-                               table_info = route_table_get_info(table);
-                               route_table_finish(table);
-                               XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+                               zebra_router_release_table(zvrf, zvrf->table_id,
+                                                          afi, safi);
+                               zvrf->table[afi][safi] = NULL;
                        }
                }
 
-               route_table_finish(zvrf->rnh_table[afi]);
-               route_table_finish(zvrf->import_check_table[afi]);
+               if (zvrf->rnh_table[afi])
+                       route_table_finish(zvrf->rnh_table[afi]);
+               if (zvrf->import_check_table[afi])
+                       route_table_finish(zvrf->import_check_table[afi]);
        }
 
        /* Cleanup EVPN states for vrf */
@@ -351,8 +354,12 @@ void zebra_rtable_node_cleanup(struct route_table *table,
                rib_unlink(node, re);
        }
 
-       if (node->info)
+       if (node->info) {
+               rib_dest_t *dest = node->info;
+
+               list_delete(&dest->nht);
                XFREE(MTYPE_RIB_DEST, node->info);
+       }
 }
 
 static void zebra_rnhtable_node_cleanup(struct route_table *table,
@@ -368,10 +375,19 @@ static void zebra_rnhtable_node_cleanup(struct route_table *table,
 static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
                                   safi_t safi)
 {
+       struct route_node *rn;
+       struct prefix p;
+
        assert(!zvrf->table[afi][safi]);
 
        zvrf->table[afi][safi] =
                zebra_router_get_table(zvrf, zvrf->table_id, afi, safi);
+
+       memset(&p, 0, sizeof(p));
+       p.family = afi2family(afi);
+
+       rn = srcdest_rnode_get(zvrf->table[afi][safi], &p, NULL);
+       zebra_rib_create_dest(rn);
 }
 
 /* Allocate new zebra VRF. */
index e35101d83313d6ba6a92c2df525cb505fd812bfc..524c175b79cd1c21e3d2b60a4325de450aa1c083 100644 (file)
 #include <zebra/zebra_pw.h>
 #include <lib/vxlan.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* MPLS (Segment Routing) global block */
 typedef struct mpls_srgb_t_ {
        uint32_t start_label;
@@ -107,18 +111,18 @@ struct zebra_vrf {
 #define MPLS_FLAG_SCHEDULE_LSPS    (1 << 0)
 
        /*
-        * VNI hash table (for EVPN). Only in default instance.
+        * VNI hash table (for EVPN). Only in the EVPN instance.
         */
        struct hash *vni_table;
 
        /*
-        * Whether EVPN is enabled or not. Only in default instance.
+        * Whether EVPN is enabled or not. Only in the EVPN instance.
         */
        int advertise_all_vni;
 
        /*
         * Whether we are advertising g/w macip in EVPN or not.
-        * Only in default instance.
+        * Only in the EVPN instance.
         */
        int advertise_gw_macip;
 
@@ -203,4 +207,9 @@ extern void zebra_vrf_init(void);
 
 extern void zebra_rtable_node_cleanup(struct route_table *table,
                                      struct route_node *node);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* ZEBRA_VRF_H */
index 537820f7ea71dd8ec2f3633438d682c240242b06..ad6184200530249369696646b5a6bdba16638d02 100644 (file)
@@ -383,6 +383,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
        json_object *json_labels = NULL;
        time_t uptime;
        struct tm *tm;
+       rib_dest_t *dest = rib_dest_from_rnode(rn);
 
        uptime = time(NULL);
        uptime -= re->uptime;
@@ -407,6 +408,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
                        json_object_boolean_true_add(json_route, "selected");
 
+               if (dest->selected_fib == re)
+                       json_object_boolean_true_add(json_route,
+                                                    "destSelected");
+
                json_object_int_add(json_route, "distance",
                                    re->distance);
                json_object_int_add(json_route, "metric", re->metric);
@@ -420,12 +425,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
                        json_object_boolean_true_add(json_route, "queued");
 
-               if (re->type != ZEBRA_ROUTE_CONNECT) {
-                       json_object_int_add(json_route, "distance",
-                                           re->distance);
-                       json_object_int_add(json_route, "metric", re->metric);
-               }
-
                if (re->tag)
                        json_object_int_add(json_route, "tag", re->tag);
 
@@ -1370,7 +1369,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
                        else
                                rib_cnt[re->type]++;
 
-                       if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
+                       if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
                                fib_cnt[ZEBRA_ROUTE_TOTAL]++;
 
                                if (is_ibgp)
@@ -1609,7 +1608,7 @@ DEFUN (show_vrf,
        return CMD_SUCCESS;
 }
 
-DEFUN_HIDDEN (default_vrf_vni_mapping,
+DEFUN (default_vrf_vni_mapping,
        default_vrf_vni_mapping_cmd,
        "vni " CMD_VNI_RANGE "[prefix-routes-only]",
        "VNI corresponding to the DEFAULT VRF\n"
@@ -1639,7 +1638,7 @@ DEFUN_HIDDEN (default_vrf_vni_mapping,
        return CMD_SUCCESS;
 }
 
-DEFUN_HIDDEN (no_default_vrf_vni_mapping,
+DEFUN (no_default_vrf_vni_mapping,
        no_default_vrf_vni_mapping_cmd,
        "no vni " CMD_VNI_RANGE,
        NO_STR
@@ -1797,7 +1796,7 @@ DEFUN (show_evpn_vni,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_vnis(vty, zvrf, uj);
        return CMD_SUCCESS;
 }
@@ -1813,7 +1812,7 @@ DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_vnis_detail(vty, zvrf, uj);
        return CMD_SUCCESS;
 }
@@ -1832,7 +1831,7 @@ DEFUN (show_evpn_vni_vni,
        bool uj = use_json(argc, argv);
 
        vni = strtoul(argv[3]->arg, NULL, 10);
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_vni(vty, zvrf, vni, uj);
        return CMD_SUCCESS;
 }
@@ -1976,7 +1975,7 @@ DEFUN (show_evpn_mac_vni,
        bool uj = use_json(argc, argv);
 
        vni = strtoul(argv[4]->arg, NULL, 10);
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
        return CMD_SUCCESS;
 }
@@ -1994,7 +1993,7 @@ DEFUN (show_evpn_mac_vni_all,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
        return CMD_SUCCESS;
 }
@@ -2012,7 +2011,7 @@ DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj);
        return CMD_SUCCESS;
 }
@@ -2038,7 +2037,7 @@ DEFUN (show_evpn_mac_vni_all_vtep,
                        vty_out(vty, "%% Malformed VTEP IP address\n");
                return CMD_WARNING;
        }
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
 
        return CMD_SUCCESS;
@@ -2068,7 +2067,7 @@ DEFUN (show_evpn_mac_vni_mac,
                vty_out(vty, "%% Malformed MAC address");
                return CMD_WARNING;
        }
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj);
        return CMD_SUCCESS;
 }
@@ -2097,7 +2096,7 @@ DEFUN (show_evpn_mac_vni_vtep,
                return CMD_WARNING;
        }
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
        return CMD_SUCCESS;
 }
@@ -2116,7 +2115,7 @@ DEFPY (show_evpn_mac_vni_all_dad,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
        return CMD_SUCCESS;
 }
@@ -2138,7 +2137,7 @@ DEFPY (show_evpn_mac_vni_dad,
        bool uj = use_json(argc, argv);
 
        vni = strtoul(argv[4]->arg, NULL, 10);
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
 
        zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
 
@@ -2161,7 +2160,7 @@ DEFPY (show_evpn_neigh_vni_dad,
        bool uj = use_json(argc, argv);
 
        vni = strtoul(argv[4]->arg, NULL, 10);
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
        return CMD_SUCCESS;
 }
@@ -2180,7 +2179,7 @@ DEFPY (show_evpn_neigh_vni_all_dad,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
        return CMD_SUCCESS;
 }
@@ -2201,7 +2200,7 @@ DEFUN (show_evpn_neigh_vni,
        bool uj = use_json(argc, argv);
 
        vni = strtoul(argv[4]->arg, NULL, 10);
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
        return CMD_SUCCESS;
 }
@@ -2219,7 +2218,7 @@ DEFUN (show_evpn_neigh_vni_all,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
        return CMD_SUCCESS;
 }
@@ -2236,7 +2235,7 @@ DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd,
        struct zebra_vrf *zvrf;
        bool uj = use_json(argc, argv);
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj);
        return CMD_SUCCESS;
 }
@@ -2264,7 +2263,7 @@ DEFUN (show_evpn_neigh_vni_neigh,
                        vty_out(vty, "%% Malformed Neighbor address\n");
                return CMD_WARNING;
        }
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
        return CMD_SUCCESS;
 }
@@ -2293,7 +2292,7 @@ DEFUN (show_evpn_neigh_vni_vtep,
                return CMD_WARNING;
        }
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
        return CMD_SUCCESS;
 }
@@ -2358,7 +2357,7 @@ DEFPY (clear_evpn_dup_addr,
        struct ethaddr mac_addr;
        int ret = CMD_SUCCESS;
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        if (vni_val) {
                vni = strtoul(vni_val, NULL, 10);
 
index 4cd70381c7728a75a62a5bde7662c6cb3b7236fb..3a8426e77257ac922d14610cb3d97e3ab5e8c0fd 100644 (file)
@@ -324,7 +324,7 @@ static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
 {
        struct zebra_vrf *zvrf;
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        if (zvrf && zvrf->advertise_gw_macip)
                return 1;
 
@@ -338,7 +338,7 @@ static int advertise_svi_macip_enabled(zebra_vni_t *zvni)
 {
        struct zebra_vrf *zvrf;
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        if (zvrf && zvrf->advertise_svi_macip)
                return 1;
 
@@ -382,6 +382,9 @@ static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
                SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
                /* Capture Duplicate detection time */
                nbr->dad_dup_detect_time = monotime(NULL);
+               /* Mark neigh inactive */
+               ZEBRA_NEIGH_SET_INACTIVE(nbr);
+
                return 1;
        } else if (is_old_mac_dup && !is_new_mac_dup) {
                UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
@@ -704,11 +707,10 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
        struct zebra_vrf *zvrf = NULL;
        struct timeval detect_start_time = {0, 0};
 
-       zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        if (!zvrf)
                return;
 
-       zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
        ipaddr2str(&n->ip, buf2, sizeof(buf2));
        prefix_mac2str(&n->emac, buf1, sizeof(buf1));
        type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ?
@@ -1152,7 +1154,9 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
        struct zebra_vrf *zvrf;
        struct timeval detect_start_time = {0, 0};
 
-       zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
+       if (!zvrf)
+               return;
 
        vty = (struct vty *)ctxt;
        prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
@@ -2076,7 +2080,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
 
        s = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
-       zclient_create_header(s, cmd, VRF_DEFAULT);
+       zclient_create_header(s, cmd, zebra_vrf_get_evpn_id());
        stream_putl(s, vni);
        stream_put(s, macaddr->octet, ETH_ALEN);
        if (ip) {
@@ -2190,6 +2194,8 @@ static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
 
        memcpy(&n->emac, mac, ETH_ALEN);
        n->state = ZEBRA_NEIGH_INACTIVE;
+       n->zvni = zvni;
+       n->dad_ip_auto_recovery_timer = NULL;
 
        /* Associate the neigh to mac */
        zmac = zvni_mac_lookup(zvni, mac);
@@ -2211,10 +2217,12 @@ static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
        if (zmac)
                listnode_delete(zmac->neigh_list, n);
 
+       /* Cancel auto recovery */
+       THREAD_OFF(n->dad_ip_auto_recovery_timer);
+
        /* Free the VNI hash entry and allocated memory. */
        tmp_n = hash_release(zvni->neigh_table, n);
-       if (tmp_n)
-               XFREE(MTYPE_NEIGH, tmp_n);
+       XFREE(MTYPE_NEIGH, tmp_n);
 
        return 0;
 }
@@ -2987,8 +2995,12 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
        }
 
        zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
-       if (!zvrf)
+       if (!zvrf) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("\tUnable to find vrf for: %d",
+                                  zvni->vxlan_if->vrf_id);
                return -1;
+       }
 
        /* Check if the neighbor exists. */
        n = zvni_neigh_lookup(zvni, ip);
@@ -3018,6 +3030,9 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                        cur_is_router = !!CHECK_FLAG(n->flags,
                                                     ZEBRA_NEIGH_ROUTER_FLAG);
                        if (!mac_different && is_router == cur_is_router) {
+                               if (IS_ZEBRA_DEBUG_VXLAN)
+                                       zlog_debug(
+                                               "\tIgnoring entry mac is the same and is_router == cur_is_router");
                                n->ifindex = ifp->ifindex;
                                return 0;
                        }
@@ -3046,6 +3061,11 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                                        return zvni_neigh_send_add_to_client(
                                                        zvni->vni, ip, macaddr,
                                                        n->flags, n->loc_seq);
+                               else {
+                                       if (IS_ZEBRA_DEBUG_VXLAN)
+                                               zlog_debug(
+                                                       "\tNeighbor active and frozen");
+                               }
                                return 0;
                        }
 
@@ -3180,12 +3200,17 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                return 0;
        }
 
-       ZEBRA_NEIGH_SET_ACTIVE(n);
        n->loc_seq = zmac->loc_seq;
 
-       if (!neigh_on_hold)
+       if (!neigh_on_hold) {
+               ZEBRA_NEIGH_SET_ACTIVE(n);
+
                return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
                                             n->flags, n->loc_seq);
+       } else {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("\tNeighbor on hold not sending");
+       }
        return 0;
 }
 
@@ -3292,6 +3317,9 @@ static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
        mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
        assert(mac);
 
+       mac->zvni = zvni;
+       mac->dad_mac_auto_recovery_timer = NULL;
+
        mac->neigh_list = list_new();
        mac->neigh_list->cmp = neigh_list_cmp;
 
@@ -3305,12 +3333,14 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
 {
        zebra_mac_t *tmp_mac;
 
+       /* Cancel auto recovery */
+       THREAD_OFF(mac->dad_mac_auto_recovery_timer);
+
        list_delete(&mac->neigh_list);
 
        /* Free the VNI hash entry and allocated memory. */
        tmp_mac = hash_release(zvni->mac_table, mac);
-       if (tmp_mac)
-               XFREE(MTYPE_MAC, tmp_mac);
+       XFREE(MTYPE_MAC, tmp_mac);
 
        return 0;
 }
@@ -3803,7 +3833,7 @@ static zebra_vni_t *zvni_lookup(vni_t vni)
        zebra_vni_t tmp_vni;
        zebra_vni_t *zvni = NULL;
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        assert(zvrf);
        memset(&tmp_vni, 0, sizeof(zebra_vni_t));
        tmp_vni.vni = vni;
@@ -3821,7 +3851,7 @@ static zebra_vni_t *zvni_add(vni_t vni)
        zebra_vni_t tmp_zvni;
        zebra_vni_t *zvni = NULL;
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        assert(zvrf);
        memset(&tmp_zvni, 0, sizeof(zebra_vni_t));
        tmp_zvni.vni = vni;
@@ -3847,7 +3877,7 @@ static int zvni_del(zebra_vni_t *zvni)
        struct zebra_vrf *zvrf;
        zebra_vni_t *tmp_zvni;
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        assert(zvrf);
 
        zvni->vxlan_if = NULL;
@@ -3862,8 +3892,7 @@ static int zvni_del(zebra_vni_t *zvni)
 
        /* Free the VNI hash entry and allocated memory. */
        tmp_zvni = hash_release(zvrf->vni_table, zvni);
-       if (tmp_zvni)
-               XFREE(MTYPE_ZVNI, tmp_zvni);
+       XFREE(MTYPE_ZVNI, tmp_zvni);
 
        return 0;
 }
@@ -3883,7 +3912,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni)
 
        s = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
-       zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
+       zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id());
        stream_putl(s, zvni->vni);
        stream_put_in_addr(s, &zvni->local_vtep_ip);
        stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */
@@ -3917,7 +3946,7 @@ static int zvni_send_del_to_client(vni_t vni)
        s = stream_new(ZEBRA_MAX_PACKET_SIZ);
        stream_reset(s);
 
-       zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
+       zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id());
        stream_putl(s, vni);
 
        /* Write packet size. */
@@ -4299,8 +4328,7 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
        }
 
        tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
-       if (tmp_rmac)
-               XFREE(MTYPE_MAC, tmp_rmac);
+       XFREE(MTYPE_MAC, tmp_rmac);
 
        return 0;
 }
@@ -4476,8 +4504,7 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
        }
 
        tmp_n = hash_release(zl3vni->nh_table, n);
-       if (tmp_n)
-               XFREE(MTYPE_NEIGH, tmp_n);
+       XFREE(MTYPE_NEIGH, tmp_n);
 
        return 0;
 }
@@ -4709,8 +4736,7 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni)
 
        /* Free the VNI hash entry and allocated memory. */
        tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni);
-       if (tmp_zl3vni)
-               XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
+       XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
 
        return 0;
 }
@@ -6930,7 +6956,7 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
        if (!is_evpn_enabled())
                return;
 
-       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zvrf = zebra_vrf_get_evpn();
        if (!zvrf)
                return;
 
@@ -7585,7 +7611,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
        if (!zvni) {
                if (IS_ZEBRA_DEBUG_VXLAN)
                        zlog_debug(
-                               "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
+                               "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
                                sticky ? "sticky " : "",
                                prefix_mac2str(macaddr, buf, sizeof(buf)),
                                ifp->name, ifp->ifindex, vid);
@@ -7593,15 +7619,20 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
        }
 
        if (!zvni->vxlan_if) {
-               zlog_debug(
-                       "VNI %u hash %p doesn't have intf upon local MAC ADD",
-                       zvni->vni, zvni);
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug(
+                               "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
+                               zvni->vni, zvni);
                return -1;
        }
 
        zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
-       if (!zvrf)
+       if (!zvrf) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("\tNo Vrf found for vrf_id: %d",
+                                  zvni->vxlan_if->vrf_id);
                return -1;
+       }
 
        /* Check if we need to create or update or it is a NO-OP. */
        mac = zvni_mac_lookup(zvni, macaddr);
@@ -7651,7 +7682,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
                            && mac->fwd_info.local.vid == vid) {
                                if (IS_ZEBRA_DEBUG_VXLAN)
                                        zlog_debug(
-                                               "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
+                                               "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
                                                "entry exists and has not changed ",
                                                sticky ? "sticky " : "",
                                                prefix_mac2str(macaddr, buf,
@@ -7767,9 +7798,9 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
                return;
        }
 
-       if (zvrf_id(zvrf) != VRF_DEFAULT) {
-               zlog_debug("Recv MACIP DEL for non-default VRF %u",
-                          zvrf_id(zvrf));
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
+                         zvrf_id(zvrf));
                return;
        }
 
@@ -7851,9 +7882,9 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
                return;
        }
 
-       if (zvrf_id(zvrf) != VRF_DEFAULT) {
-               zlog_debug("Recv MACIP ADD for non-default VRF %u",
-                          zvrf_id(zvrf));
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
+                         zvrf_id(zvrf));
                return;
        }
 
@@ -8587,10 +8618,10 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
                                    int add)
 {
        zebra_l3vni_t *zl3vni = NULL;
-       struct zebra_vrf *zvrf_default = NULL;
+       struct zebra_vrf *zvrf_evpn = NULL;
 
-       zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT);
-       if (!zvrf_default)
+       zvrf_evpn = zebra_vrf_get_evpn();
+       if (!zvrf_evpn)
                return -1;
 
        if (IS_ZEBRA_DEBUG_VXLAN)
@@ -8644,7 +8675,7 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
                zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
 
                /* formulate l2vni list */
-               hash_iterate(zvrf_default->vni_table, zvni_add_to_l3vni_list,
+               hash_iterate(zvrf_evpn->vni_table, zvni_add_to_l3vni_list,
                             zl3vni);
 
                if (is_l3vni_oper_up(zl3vni))
@@ -8739,8 +8770,8 @@ void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)
        struct stream *s;
        enum vxlan_flood_control flood_ctrl;
 
-       if (zvrf_id(zvrf) != VRF_DEFAULT) {
-               zlog_err("EVPN flood control for non-default VRF %u",
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_err("EVPN flood control for non-EVPN VRF %u",
                         zvrf_id(zvrf));
                return;
        }
@@ -8779,9 +8810,9 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
        zebra_vni_t *zvni = NULL;
        struct interface *ifp = NULL;
 
-       if (zvrf_id(zvrf) != VRF_DEFAULT) {
-               zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
-                          zvrf_id(zvrf));
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
+                         zvrf_id(zvrf));
                return;
        }
 
@@ -8878,9 +8909,9 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
        struct zebra_l2info_vxlan zl2_info;
        struct interface *vlan_if = NULL;
 
-       if (zvrf_id(zvrf) != VRF_DEFAULT) {
-               zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
-                          zvrf_id(zvrf));
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
+                         zvrf_id(zvrf));
                return;
        }
 
@@ -8941,8 +8972,8 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
        zebra_vni_t *zvni = NULL;
        struct interface *ifp = NULL;
 
-       if (zvrf_id(zvrf) != VRF_DEFAULT) {
-               zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
                           zvrf_id(zvrf));
                return;
        }
@@ -9048,18 +9079,18 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
        int advertise = 0;
        enum vxlan_flood_control flood_ctrl;
 
-       if (zvrf_id(zvrf) != VRF_DEFAULT) {
-               zlog_debug("EVPN VNI Adv for non-default VRF %u",
-                          zvrf_id(zvrf));
+       /* Mismatch between EVPN VRF and current VRF (should be prevented by
+        * bgpd's cli) */
+       if (is_evpn_enabled() && !EVPN_ENABLED(zvrf))
                return;
-       }
 
        s = msg;
        STREAM_GETC(s, advertise);
        STREAM_GETC(s, flood_ctrl);
 
        if (IS_ZEBRA_DEBUG_VXLAN)
-               zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
+               zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
+                          zvrf_name(zvrf), zvrf_id(zvrf),
                           advertise ? "enabled" : "disabled",
                           is_evpn_enabled() ? "enabled" : "disabled",
                           flood_ctrl);
@@ -9068,7 +9099,9 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
                return;
 
        zvrf->advertise_all_vni = advertise;
-       if (is_evpn_enabled()) {
+       if (EVPN_ENABLED(zvrf)) {
+               zrouter.evpn_vrf = zvrf;
+
                /* Note BUM handling */
                zvrf->vxlan_flood_ctrl = flood_ctrl;
 
@@ -9092,6 +9125,9 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
 
                /* cleanup all l3vnis */
                hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL);
+
+               /* Mark as "no EVPN VRF" */
+               zrouter.evpn_vrf = NULL;
        }
 
 stream_failure:
@@ -9132,6 +9168,7 @@ void zebra_vxlan_init(void)
 {
        zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
                                          "Zebra VRF L3 VNI table");
+       zrouter.evpn_vrf = NULL;
 }
 
 /* free l3vni table */
@@ -9163,23 +9200,23 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t)
        nbr = THREAD_ARG(t);
 
        /* since this is asynchronous we need sanity checks*/
-       nbr = zvni_neigh_lookup(zvni, &nbr->ip);
-       if (!nbr)
+       zvrf = vrf_info_lookup(nbr->zvni->vrf_id);
+       if (!zvrf)
                return 0;
 
        zvni = zvni_lookup(nbr->zvni->vni);
        if (!zvni)
                return 0;
 
-       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
-       if (!zvrf)
+       nbr = zvni_neigh_lookup(zvni, &nbr->ip);
+       if (!nbr)
                return 0;
 
        if (IS_ZEBRA_DEBUG_VXLAN)
                zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
                          __PRETTY_FUNCTION__,
-                         prefix_mac2str(&nbr->emac, buf1, sizeof(buf1)),
-                         ipaddr2str(&nbr->ip, buf2, sizeof(buf2)),
+                         prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)),
+                         ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
                          nbr->flags,
                          nbr->dad_count, zvni->vni);
 
@@ -9189,6 +9226,7 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t)
        nbr->detect_start_time.tv_usec = 0;
        nbr->dad_dup_detect_time = 0;
        nbr->dad_ip_auto_recovery_timer = NULL;
+       ZEBRA_NEIGH_SET_ACTIVE(nbr);
 
        /* Send to BGP */
        if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
@@ -9213,16 +9251,16 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
        mac = THREAD_ARG(t);
 
        /* since this is asynchronous we need sanity checks*/
-       mac = zvni_mac_lookup(zvni, &mac->macaddr);
-       if (!mac)
+       zvrf = vrf_info_lookup(mac->zvni->vrf_id);
+       if (!zvrf)
                return 0;
 
        zvni = zvni_lookup(mac->zvni->vni);
        if (!zvni)
                return 0;
 
-       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
-       if (!zvrf)
+       mac = zvni_mac_lookup(zvni, &mac->macaddr);
+       if (!mac)
                return 0;
 
        if (IS_ZEBRA_DEBUG_VXLAN)
index 2cf21ff90b649c0a2997e54513f0a97e05347294..2ff92970d777a825b36148ea058b7340a938fcf8 100644 (file)
@@ -25,6 +25,7 @@
 #define _ZEBRA_VXLAN_H
 
 #include <zebra.h>
+#include <zebra/zebra_router.h>
 
 #include "linklist.h"
 #include "if.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/zserv.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Is EVPN enabled? */
 #define EVPN_ENABLED(zvrf)  (zvrf)->advertise_all_vni
 static inline int is_evpn_enabled(void)
 {
        struct zebra_vrf *zvrf = NULL;
-       zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
-       return zvrf ? zvrf->advertise_all_vni : 0;
+       zvrf = zebra_vrf_get_evpn();
+       return zvrf ? EVPN_ENABLED(zvrf) : 0;
 }
 
 static inline int
 is_vxlan_flooding_head_end(void)
 {
-       struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
+       struct zebra_vrf *zvrf = zebra_vrf_get_evpn();
 
        if (!zvrf)
                return 0;
@@ -206,4 +211,8 @@ extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
                                            struct zebra_vrf *zvrf,
                                            vni_t vni);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_VXLAN_H */
index c36d156359f305d965108169864d5346e62204b1..5081c08d1931a484a661743c462450202b77b394 100644 (file)
 
 #include <zebra.h>
 
-#include <zebra.h>
-
 #include "if.h"
 #include "linklist.h"
 #include "zebra_vxlan.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define ERR_STR_SZ 256
 
 /* definitions */
@@ -421,4 +423,8 @@ struct nh_walk_ctx {
        struct json_object *json;
 };
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_VXLAN_PRIVATE_H */
index 6532491cefe5821c3a774108cdb4f349bfcf1b05..f5bb3aabb767428bccadcc61c4d33745784d2c39 100644 (file)
@@ -773,6 +773,18 @@ static int zserv_accept(struct thread *thread)
        return 0;
 }
 
+void zserv_close(void)
+{
+       /*
+        * On shutdown, let's close the socket down
+        * so that long running processes of killing the
+        * routing table doesn't leave us in a bad
+        * state where a client tries to reconnect
+        */
+       close(zsock);
+       zsock = -1;
+}
+
 void zserv_start(char *path)
 {
        int ret;
index ac016e65f3e19563b394fd6723e0bd46cafe0c59..86863d961c2bf961f87dd727f172b65027a6ce9c 100644 (file)
 #include "zebra/zebra_vrf.h"  /* for zebra_vrf */
 /* clang-format on */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Default port information. */
 #define ZEBRA_VTY_PORT                2601
 
@@ -179,6 +183,13 @@ extern unsigned int multipath_num;
  */
 extern void zserv_init(void);
 
+/*
+ * Stop the Zebra API server.
+ *
+ * closes the socket
+ */
+extern void zserv_close(void);
+
 /*
  * Start Zebra API server.
  *
@@ -234,4 +245,8 @@ extern void zserv_read_file(char *input);
 /* TODO */
 int zebra_finalize(struct thread *event);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _ZEBRA_ZEBRA_H */