summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/docker-daily-master.yml7
-rw-r--r--.github/workflows/docker-stable.yml53
-rw-r--r--alpine/APKBUILD.in2
-rw-r--r--babeld/.gitignore1
-rw-r--r--babeld/babel_interface.c209
-rw-r--r--babeld/babel_main.c29
-rw-r--r--babeld/babeld.c38
-rw-r--r--babeld/subdir.am4
-rw-r--r--bfdd/control.c9
-rw-r--r--bgpd/bgp_attr.c290
-rw-r--r--bgpd/bgp_attr.h11
-rw-r--r--bgpd/bgp_bfd.c4
-rw-r--r--bgpd/bgp_debug.c45
-rw-r--r--bgpd/bgp_debug.h3
-rw-r--r--bgpd/bgp_evpn.c15
-rw-r--r--bgpd/bgp_evpn_vty.c15
-rw-r--r--bgpd/bgp_evpn_vty.h3
-rw-r--r--bgpd/bgp_fsm.c3
-rw-r--r--bgpd/bgp_fsm.h2
-rw-r--r--bgpd/bgp_keepalives.c17
-rw-r--r--bgpd/bgp_keepalives.h12
-rw-r--r--bgpd/bgp_memory.c4
-rw-r--r--bgpd/bgp_memory.h2
-rw-r--r--bgpd/bgp_mpath.c14
-rw-r--r--bgpd/bgp_mplsvpn.c98
-rw-r--r--bgpd/bgp_nht.c49
-rw-r--r--bgpd/bgp_open.c17
-rw-r--r--bgpd/bgp_orr.c1176
-rw-r--r--bgpd/bgp_orr.h102
-rw-r--r--bgpd/bgp_packet.c13
-rw-r--r--bgpd/bgp_route.c257
-rw-r--r--bgpd/bgp_routemap.c7
-rw-r--r--bgpd/bgp_snmp_bgp4v2.c6
-rw-r--r--bgpd/bgp_updgrp.c9
-rw-r--r--bgpd/bgp_vty.c357
-rw-r--r--bgpd/bgp_zebra.c128
-rw-r--r--bgpd/bgpd.c39
-rw-r--r--bgpd/bgpd.h70
-rw-r--r--bgpd/subdir.am2
-rw-r--r--doc/developer/subdir.am1
-rw-r--r--doc/user/bfd.rst48
-rw-r--r--doc/user/bgp.rst369
-rw-r--r--doc/user/evpn.rst26
-rw-r--r--doc/user/ospfd.rst10
-rw-r--r--doc/user/subdir.am2
-rw-r--r--isisd/isis_nb.c60
-rw-r--r--isisd/isis_nb.h30
-rw-r--r--isisd/isis_nb_state.c222
-rw-r--r--lib/bfd.c451
-rw-r--r--lib/bfd.h17
-rw-r--r--lib/command.h8
-rw-r--r--lib/elf_py.c2
-rw-r--r--lib/if.c3
-rw-r--r--lib/orr_msg.h94
-rw-r--r--lib/prefix.c2
-rw-r--r--lib/subdir.am1
-rw-r--r--lib/vrf.c3
-rw-r--r--lib/xref.h13
-rw-r--r--lib/zclient.h6
-rw-r--r--lib/zlog_5424.c7
-rw-r--r--ospfd/ospf_dump.c46
-rw-r--r--ospfd/ospf_dump.h5
-rw-r--r--ospfd/ospf_lsa.c97
-rw-r--r--ospfd/ospf_lsa.h26
-rw-r--r--ospfd/ospf_lsdb.c9
-rw-r--r--ospfd/ospf_memory.c1
-rw-r--r--ospfd/ospf_memory.h1
-rw-r--r--ospfd/ospf_orr.c594
-rw-r--r--ospfd/ospf_orr.h58
-rw-r--r--ospfd/ospf_route.c4
-rw-r--r--ospfd/ospf_route.h3
-rw-r--r--ospfd/ospf_spf.c201
-rw-r--r--ospfd/ospf_spf.h3
-rw-r--r--ospfd/ospf_vty.c167
-rw-r--r--ospfd/ospf_zebra.c7
-rw-r--r--ospfd/ospfd.c1
-rw-r--r--ospfd/ospfd.h10
-rw-r--r--ospfd/subdir.am2
-rw-r--r--pimd/pim_ifchannel.c2
-rw-r--r--staticd/static_bfd.c390
-rw-r--r--staticd/static_debug.c15
-rw-r--r--staticd/static_debug.h4
-rw-r--r--staticd/static_nb.c27
-rw-r--r--staticd/static_nb.h7
-rw-r--r--staticd/static_nb_config.c107
-rw-r--r--staticd/static_routes.c6
-rw-r--r--staticd/static_routes.h28
-rw-r--r--staticd/static_vty.c208
-rw-r--r--staticd/static_zebra.c4
-rw-r--r--staticd/subdir.am2
-rw-r--r--tests/topotests/bfd_topo3/r3/bfd-static-down.json12
-rw-r--r--tests/topotests/bfd_topo3/r3/bfd-static.json13
-rw-r--r--tests/topotests/bfd_topo3/r3/staticd.conf1
-rw-r--r--tests/topotests/bfd_topo3/r4/bfd-peers.json48
-rw-r--r--tests/topotests/bfd_topo3/r4/bgpd.conf1
-rw-r--r--tests/topotests/bfd_topo3/r4/staticd.conf2
-rw-r--r--tests/topotests/bfd_topo3/r4/zebra.conf4
-rw-r--r--tests/topotests/bfd_topo3/r5/bfd-peers.json23
-rw-r--r--tests/topotests/bfd_topo3/r5/bfdd.conf11
-rw-r--r--tests/topotests/bfd_topo3/r5/staticd.conf2
-rw-r--r--tests/topotests/bfd_topo3/r5/zebra.conf10
-rw-r--r--tests/topotests/bfd_topo3/r6/bfd-peers.json46
-rw-r--r--tests/topotests/bfd_topo3/r6/bfd-static-down.json19
-rw-r--r--tests/topotests/bfd_topo3/r6/bfd-static.json19
-rw-r--r--tests/topotests/bfd_topo3/r6/bfdd.conf11
-rw-r--r--tests/topotests/bfd_topo3/r6/staticd.conf5
-rw-r--r--tests/topotests/bfd_topo3/r6/zebra.conf10
-rw-r--r--tests/topotests/bfd_topo3/test_bfd_topo3.dot22
-rw-r--r--tests/topotests/bfd_topo3/test_bfd_topo3.jpgbin34705 -> 42789 bytes
-rw-r--r--tests/topotests/bfd_topo3/test_bfd_topo3.py90
-rw-r--r--tests/topotests/bgp_accept_own/pe1/bgpd.conf1
-rw-r--r--tests/topotests/bgp_accept_own/pe1/zebra.conf3
-rw-r--r--tests/topotests/bgp_accept_own/test_bgp_accept_own.py47
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/zebra.conf2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/zebra.conf2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf1
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/zebra.conf1
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf1
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/zebra.conf1
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py14
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf48
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/staticd.conf6
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/zebra.conf11
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py21
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py50
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py77
-rw-r--r--tests/topotests/bgp_path_attribute_discard/__init__.py0
-rw-r--r--tests/topotests/bgp_path_attribute_discard/exabgp.env53
-rw-r--r--tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg24
-rw-r--r--tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_path_attribute_discard/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py159
-rw-r--r--tests/topotests/bgp_sender_as_path_loop_detection/r1/bgpd.conf23
-rw-r--r--tests/topotests/bgp_sender_as_path_loop_detection/r1/zebra.conf1
-rw-r--r--tests/topotests/bgp_sender_as_path_loop_detection/r2/bgpd.conf15
-rw-r--r--tests/topotests/bgp_sender_as_path_loop_detection/r3/bgpd.conf6
-rw-r--r--tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py48
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/bgpd.conf0
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/bgpd.conf0
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/bgpd.conf15
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/staticd.conf3
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/bgpd.conf10
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/staticd.conf3
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/zebra.conf2
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/bgpd.conf52
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/staticd.conf6
-rw-r--r--tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/zebra.conf29
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py46
-rw-r--r--tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json2
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf1
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json2
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py407
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py932
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py932
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4.py1909
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf6
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py234
-rw-r--r--tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py27
-rw-r--r--tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py72
-rw-r--r--tests/topotests/lib/bgprib.py193
-rw-r--r--tests/topotests/lib/common_config.py20
-rw-r--r--tests/topotests/lib/lutil.py45
-rw-r--r--tests/topotests/lib/micronet.py32
-rw-r--r--tests/topotests/lib/pim.py34
-rwxr-xr-xtests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py18
-rwxr-xr-xtests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py39
-rw-r--r--tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py85
-rw-r--r--tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py18
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py29
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py60
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py277
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py50
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py120
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py35
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py119
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt2
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt2
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt4
-rw-r--r--tests/topotests/pim_basic/test_pim.py12
-rwxr-xr-xtests/topotests/pim_igmp_vrf/test_pim_vrf.py10
-rw-r--r--tests/topotests/route_scale/scale_test_common.py2
-rw-r--r--tests/topotests/zebra_netlink/test_zebra_netlink.py2
-rwxr-xr-xtools/frr-reload.py2
-rw-r--r--yang/frr-bfdd.yang30
-rw-r--r--yang/frr-isisd.yang73
-rw-r--r--yang/frr-staticd.yang18
-rw-r--r--zebra/connected.c72
-rw-r--r--zebra/dplane_fpm_nl.c5
-rw-r--r--zebra/interface.c3
-rw-r--r--zebra/rt.h2
-rw-r--r--zebra/rt_netlink.c6
-rw-r--r--zebra/rt_netlink.h4
-rw-r--r--zebra/zebra_dplane.c4
-rw-r--r--zebra/zebra_evpn_mac.c18
-rw-r--r--zebra/zebra_fpm_netlink.c11
-rw-r--r--zebra/zebra_netns_notify.c35
-rw-r--r--zebra/zebra_ptm.h14
-rw-r--r--zebra/zebra_rib.c21
-rw-r--r--zebra/zebra_vty.c95
-rw-r--r--zebra/zebra_vxlan.c35
-rw-r--r--zebra/zebra_vxlan.h2
-rw-r--r--zebra/zserv.c68
-rw-r--r--zebra/zserv.h15
209 files changed, 6822 insertions, 7150 deletions
diff --git a/.github/workflows/docker-daily-master.yml b/.github/workflows/docker-daily-master.yml
index 5b521a870d..59787b4067 100644
--- a/.github/workflows/docker-daily-master.yml
+++ b/.github/workflows/docker-daily-master.yml
@@ -38,8 +38,9 @@ jobs:
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
+ registry: quay.io
+ username: ${{ secrets.QUAY_USERNAME }}
+ password: ${{ secrets.QUAY_ROBOT_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v3
@@ -47,6 +48,6 @@ jobs:
context: .
file: ./docker/alpine/Dockerfile
push: true
- tags: ${{ secrets.DOCKERHUB_USERNAME }}/frr:master
+ tags: quay.io/frrouting/frr:master
build-args: PKGVER=${{ steps.vars.outputs.date }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
diff --git a/.github/workflows/docker-stable.yml b/.github/workflows/docker-stable.yml
deleted file mode 100644
index 1e069a722e..0000000000
--- a/.github/workflows/docker-stable.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-name: Build stable branch images for Docker
-
-on:
- push:
- branches:
- - 'stable/**'
-
-concurrency:
- group: ${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- docker_daily_master:
- if: github.repository == 'frrouting/frr'
- runs-on: ubuntu-latest
- permissions:
- contents: read
- steps:
- - name: Custom variables
- id: vars
- run: |
- # To package a specific git commit, the date of the commit gets
- # appended to the latest release, e.g. 1.0.0_git20180204.
- # This is the requirement by APKBUILD (abuild).
- # More details: https://wiki.alpinelinux.org/wiki/APKBUILD_Reference.
- echo ::set-output name=date::$(date +'%Y%m%d')
- # Get the real version specified in configure.ac file.
- echo ::set-output name=frr_version::$(grep AC_INIT configure.ac | cut -d '[' -f3 | cut -d ']' -f 1)
-
- - name: Checkout
- uses: actions/checkout@v3
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v2
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2
-
- - name: Login to Docker Hub
- uses: docker/login-action@v2
- with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
-
- - name: Build and push
- uses: docker/build-push-action@v3
- with:
- context: .
- file: ./docker/alpine/Dockerfile
- push: true
- tags: ${{ secrets.DOCKERHUB_USERNAME }}/frr:v${{ steps.vars.outputs.frr_version }}
- build-args: PKGVER=${{ steps.vars.outputs.date }}
- platforms: linux/amd64,linux/arm64,linux/arm/v7
diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in
index 3aad9549b5..fef7a61ccc 100644
--- a/alpine/APKBUILD.in
+++ b/alpine/APKBUILD.in
@@ -10,7 +10,7 @@ depends="json-c c-ares iproute2 python3 bash"
makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
acct autoconf automake bash 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
+ expat fakeroot flex fortify-headers gdbm git gmp json-c-dev kmod
lddtree libacl libatomic libattr libblkid libburn libbz2 libc-dev
libcap-dev libcurl libedit libffi libgcc libgomp libisoburn libisofs
libltdl libressl libssh2 libstdc++ libtool libuuid
diff --git a/babeld/.gitignore b/babeld/.gitignore
index 71ef6786c7..abb4d9321a 100644
--- a/babeld/.gitignore
+++ b/babeld/.gitignore
@@ -5,3 +5,4 @@
!Makefile
!subdir.am
!.gitignore
+*_clippy.c
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index 00fb58e576..cc50898017 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -42,6 +42,10 @@ THE SOFTWARE.
#include "xroute.h"
#include "babel_errors.h"
+#ifndef VTYSH_EXTRACT_PL
+#include "babeld/babel_interface_clippy.c"
+#endif
+
DEFINE_MTYPE_STATIC(BABELD, BABEL_IF, "Babel Interface");
#define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
@@ -307,9 +311,10 @@ babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
}
/* [Interface Command] Tell the interface is wire. */
-DEFUN (babel_set_wired,
+DEFPY (babel_set_wired,
babel_set_wired_cmd,
- "babel wired",
+ "[no] babel wired",
+ NO_STR
"Babel interface commands\n"
"Enable wired optimizations\n")
{
@@ -319,14 +324,15 @@ DEFUN (babel_set_wired,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_set_wired_internal(babel_ifp, 1);
+ babel_set_wired_internal(babel_ifp, no ? 0 : 1);
return CMD_SUCCESS;
}
/* [Interface Command] Tell the interface is wireless (default). */
-DEFUN (babel_set_wireless,
+DEFPY (babel_set_wireless,
babel_set_wireless_cmd,
- "babel wireless",
+ "[no] babel wireless",
+ NO_STR
"Babel interface commands\n"
"Disable wired optimizations (assume wireless)\n")
{
@@ -336,34 +342,17 @@ DEFUN (babel_set_wireless,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_set_wired_internal(babel_ifp, 0);
+ babel_set_wired_internal(babel_ifp, no ? 1 : 0);
return CMD_SUCCESS;
}
/* [Interface Command] Enable split horizon. */
-DEFUN (babel_split_horizon,
+DEFPY (babel_split_horizon,
babel_split_horizon_cmd,
- "babel split-horizon",
- "Babel interface commands\n"
- "Enable split horizon processing\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
-
- babel_ifp = babel_get_if_nfo(ifp);
-
- assert (babel_ifp != NULL);
- babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
- return CMD_SUCCESS;
-}
-
-/* [Interface Command] Disable split horizon (default). */
-DEFUN (no_babel_split_horizon,
- no_babel_split_horizon_cmd,
- "no babel split-horizon",
+ "[no] babel split-horizon",
NO_STR
"Babel interface commands\n"
- "Disable split horizon processing\n")
+ "Enable split horizon processing\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
@@ -371,213 +360,180 @@ DEFUN (no_babel_split_horizon,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
+ if (!no)
+ SET_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON);
+ else
+ UNSET_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON);
return CMD_SUCCESS;
}
/* [Interface Command]. */
-DEFUN (babel_set_hello_interval,
+DEFPY (babel_set_hello_interval,
babel_set_hello_interval_cmd,
- "babel hello-interval (20-655340)",
+ "[no] babel hello-interval (20-655340)",
+ NO_STR
"Babel interface commands\n"
"Time between scheduled hellos\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int interval;
-
- interval = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->hello_interval = interval;
+ babel_ifp->hello_interval = no ?
+ BABEL_DEFAULT_HELLO_INTERVAL : hello_interval;
return CMD_SUCCESS;
}
/* [Interface Command]. */
-DEFUN (babel_set_update_interval,
+DEFPY (babel_set_update_interval,
babel_set_update_interval_cmd,
- "babel update-interval (20-655340)",
+ "[no] babel update-interval (20-655340)",
+ NO_STR
"Babel interface commands\n"
"Time between scheduled updates\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int interval;
-
- interval = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->update_interval = interval;
+ babel_ifp->update_interval = no ?
+ BABEL_DEFAULT_UPDATE_INTERVAL : update_interval;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rxcost,
+DEFPY (babel_set_rxcost,
babel_set_rxcost_cmd,
- "babel rxcost (1-65534)",
+ "[no] babel rxcost (1-65534)",
+ NO_STR
"Babel interface commands\n"
"Rxcost multiplier\n"
"Units\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int rxcost;
-
- rxcost = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
+ if (no)
+ rxcost = CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ?
+ BABEL_DEFAULT_RXCOST_WIRED : BABEL_DEFAULT_RXCOST_WIRELESS;
+
babel_ifp->cost = rxcost;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rtt_decay,
+DEFPY (babel_set_rtt_decay,
babel_set_rtt_decay_cmd,
- "babel rtt-decay (1-256)",
+ "[no] babel rtt-decay (1-256)",
+ NO_STR
"Babel interface commands\n"
"Decay factor for exponential moving average of RTT samples\n"
"Units of 1/256\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int decay;
-
- decay = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->rtt_decay = decay;
+ babel_ifp->rtt_decay = no ? BABEL_DEFAULT_RTT_DECAY : rtt_decay;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rtt_min,
+DEFPY (babel_set_rtt_min,
babel_set_rtt_min_cmd,
- "babel rtt-min (1-65535)",
+ "[no] babel rtt-min (1-65535)",
+ NO_STR
"Babel interface commands\n"
"Minimum RTT starting for increasing cost\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int rtt;
-
- rtt = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
/* The value is entered in milliseconds but stored as microseconds. */
- babel_ifp->rtt_min = rtt * 1000;
+ babel_ifp->rtt_min = no ? BABEL_DEFAULT_RTT_MIN : rtt_min * 1000;
return CMD_SUCCESS;
}
-DEFUN (babel_set_rtt_max,
+DEFPY (babel_set_rtt_max,
babel_set_rtt_max_cmd,
- "babel rtt-max (1-65535)",
+ "[no] babel rtt-max (1-65535)",
+ NO_STR
"Babel interface commands\n"
"Maximum RTT\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int rtt;
-
- rtt = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
/* The value is entered in milliseconds but stored as microseconds. */
- babel_ifp->rtt_max = rtt * 1000;
+ babel_ifp->rtt_max = no ? BABEL_DEFAULT_RTT_MAX : rtt_max * 1000;
return CMD_SUCCESS;
}
-DEFUN (babel_set_max_rtt_penalty,
+DEFPY (babel_set_max_rtt_penalty,
babel_set_max_rtt_penalty_cmd,
- "babel max-rtt-penalty (0-65535)",
+ "[no] babel max-rtt-penalty (0-65535)",
+ NO_STR
"Babel interface commands\n"
"Maximum additional cost due to RTT\n"
"Milliseconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
- int penalty;
-
- penalty = strtoul(argv[2]->arg, NULL, 10);
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->max_rtt_penalty = penalty;
+ babel_ifp->max_rtt_penalty = no ?
+ BABEL_DEFAULT_MAX_RTT_PENALTY : max_rtt_penalty;
return CMD_SUCCESS;
}
-DEFUN (babel_set_enable_timestamps,
+DEFPY (babel_set_enable_timestamps,
babel_set_enable_timestamps_cmd,
- "babel enable-timestamps",
- "Babel interface commands\n"
- "Enable timestamps\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
-
- babel_ifp = babel_get_if_nfo(ifp);
- assert (babel_ifp != NULL);
-
- babel_ifp->flags |= BABEL_IF_TIMESTAMPS;
- return CMD_SUCCESS;
-}
-
-DEFUN (no_babel_set_enable_timestamps,
- no_babel_set_enable_timestamps_cmd,
- "no babel enable-timestamps",
+ "[no] babel enable-timestamps",
NO_STR
"Babel interface commands\n"
- "Disable timestamps\n")
+ "Enable timestamps\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
-
- babel_ifp->flags &= ~BABEL_IF_TIMESTAMPS;
+ if (!no)
+ SET_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS);
+ else
+ UNSET_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS);
return CMD_SUCCESS;
}
-DEFUN (babel_set_channel,
+DEFPY (babel_set_channel,
babel_set_channel_cmd,
- "babel channel (1-254)",
- "Babel interface commands\n"
- "Channel number for diversity routing\n"
- "Number\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
- int channel;
-
- channel = strtoul(argv[2]->arg, NULL, 10);
-
- babel_ifp = babel_get_if_nfo(ifp);
- assert (babel_ifp != NULL);
-
- babel_ifp->channel = channel;
- return CMD_SUCCESS;
-}
-
-DEFUN (babel_set_channel_interfering,
- babel_set_channel_interfering_cmd,
- "babel channel interfering",
+ "[no] babel channel <(1-254)$ch|interfering$interfering|"
+ "noninterfering$noninterfering>",
+ NO_STR
"Babel interface commands\n"
"Channel number for diversity routing\n"
- "Mark channel as interfering\n")
+ "Number\n"
+ "Mark channel as interfering\n"
+ "Mark channel as noninterfering\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
babel_interface_nfo *babel_ifp;
@@ -585,24 +541,15 @@ DEFUN (babel_set_channel_interfering,
babel_ifp = babel_get_if_nfo(ifp);
assert (babel_ifp != NULL);
- babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
- return CMD_SUCCESS;
-}
-
-DEFUN (babel_set_channel_noninterfering,
- babel_set_channel_noninterfering_cmd,
- "babel channel noninterfering",
- "Babel interface commands\n"
- "Channel number for diversity routing\n"
- "Mark channel as noninterfering\n")
-{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- babel_interface_nfo *babel_ifp;
-
- babel_ifp = babel_get_if_nfo(ifp);
- assert (babel_ifp != NULL);
+ if (no)
+ ch = CHECK_FLAG(babel_ifp->flags, BABEL_IF_WIRED) ?
+ BABEL_IF_CHANNEL_NONINTERFERING : BABEL_IF_CHANNEL_INTERFERING;
+ else if (interfering)
+ ch = BABEL_IF_CHANNEL_INTERFERING;
+ else if (noninterfering)
+ ch = BABEL_IF_CHANNEL_NONINTERFERING;
- babel_ifp->channel = BABEL_IF_CHANNEL_NONINTERFERING;
+ babel_ifp->channel = ch;
return CMD_SUCCESS;
}
@@ -1239,7 +1186,6 @@ babel_if_init(void)
install_element(BABEL_NODE, &babel_network_cmd);
install_element(BABEL_NODE, &no_babel_network_cmd);
install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
- install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
install_element(INTERFACE_NODE, &babel_set_wired_cmd);
install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
@@ -1251,9 +1197,6 @@ babel_if_init(void)
install_element(INTERFACE_NODE, &babel_set_rtt_max_cmd);
install_element(INTERFACE_NODE, &babel_set_max_rtt_penalty_cmd);
install_element(INTERFACE_NODE, &babel_set_enable_timestamps_cmd);
- install_element(INTERFACE_NODE, &no_babel_set_enable_timestamps_cmd);
- install_element(INTERFACE_NODE, &babel_set_channel_interfering_cmd);
- install_element(INTERFACE_NODE, &babel_set_channel_noninterfering_cmd);
/* "show babel ..." commands */
install_element(VIEW_NODE, &show_babel_interface_cmd);
diff --git a/babeld/babel_main.c b/babeld/babel_main.c
index b29374fee3..9aa5ce3a01 100644
--- a/babeld/babel_main.c
+++ b/babeld/babel_main.c
@@ -50,7 +50,6 @@ THE SOFTWARE.
static void babel_fail(void);
static void babel_init_random(void);
-static void babel_replace_by_null(int fd);
static void babel_exit_properly(void);
static void babel_save_state_file(void);
@@ -199,8 +198,6 @@ main(int argc, char **argv)
resend_delay = BABEL_DEFAULT_RESEND_DELAY;
change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
- babel_replace_by_null(STDIN_FILENO);
-
/* init some quagga's dependencies, and babeld's commands */
if_zapi_callbacks(babel_ifp_create, babel_ifp_up,
babel_ifp_down, babel_ifp_destroy);
@@ -248,32 +245,6 @@ babel_init_random(void)
}
/*
- close fd, and replace it by "/dev/null"
- exit if error
- */
-static void
-babel_replace_by_null(int fd)
-{
- int fd_null;
- int rc;
-
- fd_null = open("/dev/null", O_RDONLY);
- if(fd_null < 0) {
- flog_err_sys(EC_LIB_SYSTEM_CALL, "open(null): %s", safe_strerror(errno));
- exit(1);
- }
-
- rc = dup2(fd_null, fd);
- if(rc < 0) {
- flog_err_sys(EC_LIB_SYSTEM_CALL, "dup2(null, 0): %s",
- safe_strerror(errno));
- exit(1);
- }
-
- close(fd_null);
-}
-
-/*
Load the state file: check last babeld's running state, usefull in case of
"/etc/init.d/babeld restart"
*/
diff --git a/babeld/babeld.c b/babeld/babeld.c
index dfdc924cbd..34e1a4318b 100644
--- a/babeld/babeld.c
+++ b/babeld/babeld.c
@@ -47,6 +47,10 @@ THE SOFTWARE.
#include "babel_zebra.h"
#include "babel_errors.h"
+#ifndef VTYSH_EXTRACT_PL
+#include "babeld/babeld_clippy.c"
+#endif
+
DEFINE_MGROUP(BABELD, "babeld");
DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure");
@@ -662,50 +666,42 @@ DEFUN (no_babel_diversity,
}
/* [Babel Command] */
-DEFUN (babel_diversity_factor,
+DEFPY (babel_diversity_factor,
babel_diversity_factor_cmd,
- "babel diversity-factor (1-256)",
+ "[no] babel diversity-factor (1-256)$factor",
+ NO_STR
"Babel commands\n"
"Set the diversity factor.\n"
"Factor in units of 1/256.\n")
{
- int factor;
-
- factor = strtoul(argv[2]->arg, NULL, 10);
-
- diversity_factor = factor;
+ diversity_factor = no ? BABEL_DEFAULT_DIVERSITY_FACTOR : factor;
return CMD_SUCCESS;
}
/* [Babel Command] */
-DEFUN (babel_set_resend_delay,
+DEFPY (babel_set_resend_delay,
babel_set_resend_delay_cmd,
- "babel resend-delay (20-655340)",
+ "[no] babel resend-delay (20-655340)$delay",
+ NO_STR
"Babel commands\n"
"Time before resending a message\n"
"Milliseconds\n")
{
- int interval;
-
- interval = strtoul(argv[2]->arg, NULL, 10);
-
- resend_delay = interval;
+ resend_delay = no ? BABEL_DEFAULT_RESEND_DELAY : delay;
return CMD_SUCCESS;
}
/* [Babel Command] */
-DEFUN (babel_set_smoothing_half_life,
+DEFPY (babel_set_smoothing_half_life,
babel_set_smoothing_half_life_cmd,
- "babel smoothing-half-life (0-65534)",
+ "[no] babel smoothing-half-life (0-65534)$seconds",
+ NO_STR
"Babel commands\n"
"Smoothing half-life\n"
"Seconds (0 to disable)\n")
{
- int seconds;
-
- seconds = strtoul(argv[2]->arg, NULL, 10);
-
- change_smoothing_half_life(seconds);
+ change_smoothing_half_life(no ? BABEL_DEFAULT_SMOOTHING_HALF_LIFE
+ : seconds);
return CMD_SUCCESS;
}
diff --git a/babeld/subdir.am b/babeld/subdir.am
index 4b9037283c..d2d425218b 100644
--- a/babeld/subdir.am
+++ b/babeld/subdir.am
@@ -43,4 +43,8 @@ noinst_HEADERS += \
babeld/xroute.h \
# end
+clippy_scan += \
+ babeld/babel_interface.c \
+ babeld/babeld.c
+
babeld_babeld_LDADD = lib/libfrr.la $(LIBCAP)
diff --git a/bfdd/control.c b/bfdd/control.c
index 473843fe25..01cfed8f90 100644
--- a/bfdd/control.c
+++ b/bfdd/control.c
@@ -435,6 +435,15 @@ static void control_read(struct thread *t)
return;
}
+#define FRR_BFD_MAXLEN 10 * 1024
+
+ if (plen > FRR_BFD_MAXLEN) {
+ zlog_debug("%s: client closed, invalid message length: %d",
+ __func__, bcm.bcm_length);
+ control_free(bcs);
+ return;
+ }
+
if (bcm.bcm_ver != BMV_VERSION_1) {
zlog_debug("%s: client closed due bad version: %d", __func__,
bcm.bcm_ver);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 3d93e8a1ac..e60c1bb8dc 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -33,6 +33,7 @@
#include "filter.h"
#include "command.h"
#include "srv6.h"
+#include "frrstr.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@@ -73,7 +74,6 @@ static const struct message attr_str[] = {
{BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES"},
{BGP_ATTR_AS4_PATH, "AS4_PATH"},
{BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"},
- {BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT"},
{BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"},
{BGP_ATTR_ENCAP, "ENCAP"},
{BGP_ATTR_OTC, "OTC"},
@@ -825,56 +825,55 @@ bool attrhash_cmp(const void *p1, const void *p2)
&& attr1->med == attr2->med
&& attr1->local_pref == attr2->local_pref
&& attr1->rmap_change_flags == attr2->rmap_change_flags) {
- if (attr1->aggregator_as == attr2->aggregator_as &&
- attr1->aggregator_addr.s_addr ==
- attr2->aggregator_addr.s_addr &&
- attr1->weight == attr2->weight &&
- attr1->tag == attr2->tag &&
- attr1->label_index == attr2->label_index &&
- attr1->mp_nexthop_len == attr2->mp_nexthop_len &&
- bgp_attr_get_ecommunity(attr1) ==
- bgp_attr_get_ecommunity(attr2) &&
- bgp_attr_get_ipv6_ecommunity(attr1) ==
- bgp_attr_get_ipv6_ecommunity(attr2) &&
- bgp_attr_get_lcommunity(attr1) ==
- bgp_attr_get_lcommunity(attr2) &&
- bgp_attr_get_cluster(attr1) ==
- bgp_attr_get_cluster(attr2) &&
- bgp_attr_get_transit(attr1) ==
- bgp_attr_get_transit(attr2) &&
- bgp_attr_get_aigp_metric(attr1) ==
- bgp_attr_get_aigp_metric(attr2) &&
- attr1->rmap_table_id == attr2->rmap_table_id &&
- (attr1->encap_tunneltype == attr2->encap_tunneltype) &&
- encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
+ if (attr1->aggregator_as == attr2->aggregator_as
+ && attr1->aggregator_addr.s_addr
+ == attr2->aggregator_addr.s_addr
+ && attr1->weight == attr2->weight
+ && attr1->tag == attr2->tag
+ && attr1->label_index == attr2->label_index
+ && attr1->mp_nexthop_len == attr2->mp_nexthop_len
+ && bgp_attr_get_ecommunity(attr1)
+ == bgp_attr_get_ecommunity(attr2)
+ && bgp_attr_get_ipv6_ecommunity(attr1)
+ == bgp_attr_get_ipv6_ecommunity(attr2)
+ && bgp_attr_get_lcommunity(attr1)
+ == bgp_attr_get_lcommunity(attr2)
+ && bgp_attr_get_cluster(attr1)
+ == bgp_attr_get_cluster(attr2)
+ && bgp_attr_get_transit(attr1)
+ == bgp_attr_get_transit(attr2)
+ && bgp_attr_get_aigp_metric(attr1)
+ == bgp_attr_get_aigp_metric(attr2)
+ && attr1->rmap_table_id == attr2->rmap_table_id
+ && (attr1->encap_tunneltype == attr2->encap_tunneltype)
+ && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
#ifdef ENABLE_BGP_VNC
&& encap_same(bgp_attr_get_vnc_subtlvs(attr1),
bgp_attr_get_vnc_subtlvs(attr2))
#endif
&& IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
- &attr2->mp_nexthop_global) &&
- IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
- &attr2->mp_nexthop_local) &&
- IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
- &attr2->mp_nexthop_global_in) &&
- IPV4_ADDR_SAME(&attr1->originator_id,
- &attr2->originator_id) &&
- overlay_index_same(attr1, attr2) &&
- !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) &&
- attr1->es_flags == attr2->es_flags &&
- attr1->mm_sync_seqnum == attr2->mm_sync_seqnum &&
- attr1->df_pref == attr2->df_pref &&
- attr1->df_alg == attr2->df_alg &&
- attr1->nh_ifindex == attr2->nh_ifindex &&
- attr1->nh_flag == attr2->nh_flag &&
- attr1->nh_lla_ifindex == attr2->nh_lla_ifindex &&
- attr1->distance == attr2->distance &&
- srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn) &&
- srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
- attr1->srte_color == attr2->srte_color &&
- attr1->nh_type == attr2->nh_type &&
- attr1->bh_type == attr2->bh_type &&
- attr1->otc == attr2->otc)
+ &attr2->mp_nexthop_global)
+ && IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
+ &attr2->mp_nexthop_local)
+ && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
+ &attr2->mp_nexthop_global_in)
+ && IPV4_ADDR_SAME(&attr1->originator_id,
+ &attr2->originator_id)
+ && overlay_index_same(attr1, attr2)
+ && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t))
+ && attr1->es_flags == attr2->es_flags
+ && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum
+ && attr1->df_pref == attr2->df_pref
+ && attr1->df_alg == attr2->df_alg
+ && attr1->nh_ifindex == attr2->nh_ifindex
+ && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex
+ && attr1->distance == attr2->distance
+ && srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn)
+ && srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn)
+ && attr1->srte_color == attr2->srte_color
+ && attr1->nh_type == attr2->nh_type
+ && attr1->bh_type == attr2->bh_type
+ && attr1->otc == attr2->otc)
return true;
}
@@ -1852,6 +1851,7 @@ stream_failure:
/* Atomic aggregate. */
static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
{
+ struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
@@ -1864,10 +1864,22 @@ static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto atomic_ignore;
+
/* Set atomic aggregate flag. */
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
return BGP_ATTR_PARSE_PROCEED;
+
+atomic_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Aggregator attribute */
@@ -1893,6 +1905,9 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto aggregator_ignore;
+
if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV))
aggregator_as = stream_getl(peer->curr);
else
@@ -1919,6 +1934,15 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
}
return BGP_ATTR_PARSE_PROCEED;
+
+aggregator_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* New Aggregator attribute */
@@ -1939,6 +1963,9 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
0);
}
+ if (peer->discard_attrs[args->type])
+ goto as4_aggregator_ignore;
+
aggregator_as = stream_getl(peer->curr);
*as4_aggregator_as = aggregator_as;
@@ -1962,6 +1989,15 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
}
return BGP_ATTR_PARSE_PROCEED;
+
+as4_aggregator_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
@@ -2081,6 +2117,9 @@ bgp_attr_community(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto community_ignore;
+
bgp_attr_set_community(
attr,
community_parse((uint32_t *)stream_pnt(peer->curr), length));
@@ -2096,6 +2135,15 @@ bgp_attr_community(struct bgp_attr_parser_args *args)
args->total);
return BGP_ATTR_PARSE_PROCEED;
+
+community_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Originator ID attribute. */
@@ -2119,11 +2167,23 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto originator_id_ignore;
+
attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
return BGP_ATTR_PARSE_PROCEED;
+
+originator_id_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Cluster list attribute. */
@@ -2146,6 +2206,9 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto cluster_list_ignore;
+
bgp_attr_set_cluster(
attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
length));
@@ -2156,6 +2219,15 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST);
return BGP_ATTR_PARSE_PROCEED;
+
+cluster_list_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Multiprotocol reachability information parse. */
@@ -2255,12 +2327,6 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
return BGP_ATTR_PARSE_WITHDRAW;
}
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
- if (if_is_operative(peer->nexthop.ifp))
- SET_FLAG(attr->nh_flag,
- BGP_ATTR_NH_IF_OPERSTATE);
- else
- UNSET_FLAG(attr->nh_flag,
- BGP_ATTR_NH_IF_OPERSTATE);
}
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
@@ -2278,12 +2344,6 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
return BGP_ATTR_PARSE_WITHDRAW;
}
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
- if (if_is_operative(peer->nexthop.ifp))
- SET_FLAG(attr->nh_flag,
- BGP_ATTR_NH_IF_OPERSTATE);
- else
- UNSET_FLAG(attr->nh_flag,
- BGP_ATTR_NH_IF_OPERSTATE);
}
if (attr->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
@@ -2427,6 +2487,9 @@ bgp_attr_large_community(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto large_community_ignore;
+
bgp_attr_set_lcommunity(
attr, lcommunity_parse(stream_pnt(peer->curr), length));
/* XXX: fix ecommunity_parse to use stream API */
@@ -2437,6 +2500,15 @@ bgp_attr_large_community(struct bgp_attr_parser_args *args)
args->total);
return BGP_ATTR_PARSE_PROCEED;
+
+large_community_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Extended Community attribute. */
@@ -2528,6 +2600,9 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto ipv6_ext_community_ignore;
+
ipv6_ecomm = ecommunity_parse_ipv6(
stream_pnt(peer->curr), length,
CHECK_FLAG(peer->flags,
@@ -2542,6 +2617,15 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
args->total);
return BGP_ATTR_PARSE_PROCEED;
+
+ipv6_ext_community_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* Parse Tunnel Encap attribute in an UPDATE */
@@ -3216,6 +3300,9 @@ static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
goto aigp_ignore;
}
+ if (peer->discard_attrs[args->type])
+ goto aigp_ignore;
+
if (!bgp_attr_aigp_valid(s, length))
goto aigp_ignore;
@@ -3226,6 +3313,10 @@ static enum bgp_attr_parse_ret bgp_attr_aigp(struct bgp_attr_parser_args *args)
aigp_ignore:
stream_forward_getp(peer->curr, length);
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
return BGP_ATTR_PARSE_PROCEED;
}
@@ -3244,6 +3335,9 @@ static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
args->total);
}
+ if (peer->discard_attrs[args->type])
+ goto otc_ignore;
+
attr->otc = stream_getl(peer->curr);
if (!attr->otc) {
flog_err(EC_BGP_ATTR_MAL_AS_PATH, "OTC attribute value is 0");
@@ -3254,6 +3348,15 @@ static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
return BGP_ATTR_PARSE_PROCEED;
+
+otc_ignore:
+ stream_forward_getp(peer->curr, length);
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
}
/* BGP unknown attribute treatment. */
@@ -3277,6 +3380,14 @@ bgp_attr_unknown(struct bgp_attr_parser_args *args)
/* Forward read pointer of input stream. */
stream_forward_getp(peer->curr, length);
+ if (peer->discard_attrs[type]) {
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("%pBP: Ignoring attribute %s", peer,
+ lookup_msg(attr_str, args->type, NULL));
+
+ return BGP_ATTR_PARSE_PROCEED;
+ }
+
/* If any of the mandatory well-known attributes are not recognized,
then the Error Subcode is set to Unrecognized Well-known
Attribute. The Data field contains the unrecognized attribute
@@ -3917,8 +4028,8 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
}
} break;
case SAFI_MPLS_VPN: {
- if (attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
stream_putc(s, 48);
stream_putl(s, 0); /* RD = 0, per RFC */
stream_putl(s, 0);
@@ -4984,3 +5095,62 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
len = stream_get_endp(s) - cp - 2;
stream_putw_at(s, cp, len);
}
+
+void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
+ const char *discard_attrs)
+{
+ int i, num_attributes;
+ char **attributes;
+ afi_t afi;
+ safi_t safi;
+
+ if (discard_attrs) {
+ frrstr_split(discard_attrs, " ", &attributes, &num_attributes);
+
+ for (i = 0; i < BGP_ATTR_MAX; i++)
+ peer->discard_attrs[i] = false;
+
+ for (i = 0; i < num_attributes; i++) {
+ uint8_t attr_num = strtoul(attributes[i], NULL, 10);
+
+ XFREE(MTYPE_TMP, attributes[i]);
+
+ /* Some of the attributes, just can't be ignored. */
+ if (attr_num == BGP_ATTR_ORIGIN ||
+ attr_num == BGP_ATTR_AS_PATH ||
+ attr_num == BGP_ATTR_NEXT_HOP ||
+ attr_num == BGP_ATTR_MULTI_EXIT_DISC ||
+ attr_num == BGP_ATTR_MP_REACH_NLRI ||
+ attr_num == BGP_ATTR_MP_UNREACH_NLRI ||
+ attr_num == BGP_ATTR_EXT_COMMUNITIES) {
+ vty_out(vty,
+ "%% Can't discard path-attribute %s, ignoring.\n",
+ lookup_msg(attr_str, attr_num, NULL));
+ continue;
+ }
+
+ /* Ignore local-pref, originator-id, cluster-list only
+ * for eBGP.
+ */
+ if (peer->sort != BGP_PEER_EBGP &&
+ (attr_num == BGP_ATTR_LOCAL_PREF ||
+ attr_num == BGP_ATTR_ORIGINATOR_ID ||
+ attr_num == BGP_ATTR_CLUSTER_LIST)) {
+ vty_out(vty,
+ "%% Can discard path-attribute %s only for eBGP, ignoring.\n",
+ lookup_msg(attr_str, attr_num, NULL));
+ continue;
+ }
+
+ peer->discard_attrs[attr_num] = true;
+ }
+ XFREE(MTYPE_TMP, attributes);
+
+ /* Configuring path attributes to be discarded will trigger
+ * an inbound Route Refresh to ensure that the routing table
+ * is up to date.
+ */
+ FOREACH_AFI_SAFI (afi, safi)
+ peer_clear_soft(peer, afi, safi, BGP_CLEAR_SOFT_IN);
+ }
+}
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index f8beb5fba9..cb0bf4a43c 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -170,12 +170,6 @@ struct attr {
uint32_t med;
uint32_t local_pref;
ifindex_t nh_ifindex;
- uint8_t nh_flag;
-
-#define BGP_ATTR_NH_VALID 0x01
-#define BGP_ATTR_NH_IF_OPERSTATE 0x02
-#define BGP_ATTR_NH_MP_PREFER_GLOBAL 0x04 /* MP Nexthop preference */
-#define BGP_ATTR_NH_REFRESH 0x08
/* Path origin attribute */
uint8_t origin;
@@ -226,6 +220,9 @@ struct attr {
/* MP Nexthop length */
uint8_t mp_nexthop_len;
+ /* MP Nexthop preference */
+ uint8_t mp_nexthop_prefer_global;
+
/* Static MAC for EVPN */
uint8_t sticky;
@@ -417,6 +414,8 @@ extern unsigned int attrhash_key_make(const void *p);
extern void attr_show_all(struct vty *vty);
extern unsigned long int attr_count(void);
extern unsigned long int attr_unknown_count(void);
+extern void bgp_path_attribute_discard_vty(struct vty *vty, struct peer *peer,
+ const char *discard_attrs);
/* Cluster list prototypes. */
extern bool cluster_loop_check(struct cluster_list *cluster,
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index d66b916b95..11b074af2e 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -521,10 +521,8 @@ DEFUN (neighbor_bfd_check_controlplane_failure,
else
idx_peer = 1;
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
- if (!peer) {
- vty_out(vty, "%% Specify remote-as or peer-group commands first\n");
+ if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- }
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
bgp_group_configure_bfd(peer);
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 9e540b63cb..f01c3e4f35 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -73,7 +73,6 @@ unsigned long conf_bgp_debug_graceful_restart;
unsigned long conf_bgp_debug_evpn_mh;
unsigned long conf_bgp_debug_bfd;
unsigned long conf_bgp_debug_cond_adv;
-unsigned long conf_bgp_debug_optimal_route_reflection;
unsigned long term_bgp_debug_as4;
unsigned long term_bgp_debug_neighbor_events;
@@ -95,7 +94,6 @@ unsigned long term_bgp_debug_graceful_restart;
unsigned long term_bgp_debug_evpn_mh;
unsigned long term_bgp_debug_bfd;
unsigned long term_bgp_debug_cond_adv;
-unsigned long term_bgp_debug_optimal_route_reflection;
struct list *bgp_debug_neighbor_events_peers = NULL;
struct list *bgp_debug_keepalive_peers = NULL;
@@ -144,7 +142,6 @@ static const struct message bgp_notify_open_msg[] = {
{BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS"},
{BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier"},
{BGP_NOTIFY_OPEN_UNSUP_PARAM, "/Unsupported Optional Parameter"},
- {BGP_NOTIFY_OPEN_AUTH_FAILURE, "/Authentication Failure"},
{BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, "/Unacceptable Hold Time"},
{BGP_NOTIFY_OPEN_UNSUP_CAPBL, "/Unsupported Capability"},
{BGP_NOTIFY_OPEN_ROLE_MISMATCH, "/Role Mismatch"},
@@ -158,7 +155,6 @@ static const struct message bgp_notify_update_msg[] = {
{BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, "/Attribute Flags Error"},
{BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, "/Attribute Length Error"},
{BGP_NOTIFY_UPDATE_INVAL_ORIGIN, "/Invalid ORIGIN Attribute"},
- {BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP, "/AS Routing Loop"},
{BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, "/Invalid NEXT_HOP Attribute"},
{BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, "/Optional Attribute Error"},
{BGP_NOTIFY_UPDATE_INVAL_NETWORK, "/Invalid Network Field"},
@@ -1989,33 +1985,6 @@ DEFPY (debug_bgp_evpn_mh,
return CMD_SUCCESS;
}
-DEFPY (debug_bgp_optimal_route_reflection,
- debug_bgp_optimal_route_reflection_cmd,
- "[no$no] debug bgp optimal-route-reflection",
- NO_STR
- DEBUG_STR
- BGP_STR
- BGP_ORR_DEBUG)
-{
- if (vty->node == CONFIG_NODE) {
- if (no)
- DEBUG_OFF(optimal_route_reflection, ORR);
- else
- DEBUG_ON(optimal_route_reflection, ORR);
- } else {
- if (no) {
- TERM_DEBUG_OFF(optimal_route_reflection, ORR);
- vty_out(vty,
- "BGP Optimal Route Reflection debugging is off\n");
- } else {
- TERM_DEBUG_ON(optimal_route_reflection, ORR);
- vty_out(vty,
- "BGP Optimal Route Reflection debugging is on\n");
- }
- }
- return CMD_SUCCESS;
-}
-
DEFUN (debug_bgp_labelpool,
debug_bgp_labelpool_cmd,
"debug bgp labelpool",
@@ -2154,7 +2123,6 @@ DEFUN (no_debug_bgp,
TERM_DEBUG_OFF(evpn_mh, EVPN_MH_RT);
TERM_DEBUG_OFF(bfd, BFD_LIB);
TERM_DEBUG_OFF(cond_adv, COND_ADV);
- TERM_DEBUG_OFF(optimal_route_reflection, ORR);
vty_out(vty, "All possible debugging has been turned off\n");
@@ -2251,10 +2219,6 @@ DEFUN_NOSH (show_debugging_bgp,
vty_out(vty,
" BGP conditional advertisement debugging is on\n");
- if (BGP_DEBUG(optimal_route_reflection, ORR))
- vty_out(vty,
- " BGP Optimal Route Reflection debugging is on\n");
-
cmd_show_lib_debugs(vty);
return CMD_SUCCESS;
@@ -2391,11 +2355,6 @@ static int bgp_config_write_debug(struct vty *vty)
write++;
}
- if (CONF_BGP_DEBUG(optimal_route_reflection, ORR)) {
- vty_out(vty, "debug bgp optimal-route-reflection\n");
- write++;
- }
-
return write;
}
@@ -2528,10 +2487,6 @@ void bgp_debug_init(void)
/* debug bgp conditional advertisement */
install_element(ENABLE_NODE, &debug_bgp_cond_adv_cmd);
install_element(CONFIG_NODE, &debug_bgp_cond_adv_cmd);
-
- /* debug bgp optimal route reflection */
- install_element(ENABLE_NODE, &debug_bgp_optimal_route_reflection_cmd);
- install_element(CONFIG_NODE, &debug_bgp_optimal_route_reflection_cmd);
}
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index f7090260ac..be5ed0afdc 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -81,7 +81,6 @@ extern unsigned long conf_bgp_debug_graceful_restart;
extern unsigned long conf_bgp_debug_evpn_mh;
extern unsigned long conf_bgp_debug_bfd;
extern unsigned long conf_bgp_debug_cond_adv;
-extern unsigned long conf_bgp_debug_optimal_route_reflection;
extern unsigned long term_bgp_debug_as4;
extern unsigned long term_bgp_debug_neighbor_events;
@@ -101,7 +100,6 @@ extern unsigned long term_bgp_debug_graceful_restart;
extern unsigned long term_bgp_debug_evpn_mh;
extern unsigned long term_bgp_debug_bfd;
extern unsigned long term_bgp_debug_cond_adv;
-extern unsigned long term_bgp_debug_optimal_route_reflection;
extern struct list *bgp_debug_neighbor_events_peers;
extern struct list *bgp_debug_keepalive_peers;
@@ -140,7 +138,6 @@ struct bgp_debug_filter {
#define BGP_DEBUG_PBR_ERROR 0x02
#define BGP_DEBUG_EVPN_MH_ES 0x01
#define BGP_DEBUG_EVPN_MH_RT 0x02
-#define BGP_DEBUG_ORR 0x01
#define BGP_DEBUG_PACKET_SEND 0x01
#define BGP_DEBUG_PACKET_SEND_DETAIL 0x02
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 7a8a91b00b..c9e935668e 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -2119,10 +2119,11 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
char buf3[ESI_STR_LEN];
zlog_debug(
- "VRF %s vni %u type-2 route evp %pFX RMAC %pEA nexthop %pI4 esi %s",
+ "VRF %s vni %u type-%u route evp %pFX RMAC %pEA nexthop %pI4 esi %s",
vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id)
- : " ",
- vpn->vni, p, &attr.rmac, &attr.mp_nexthop_global_in,
+ : "None",
+ vpn->vni, p->prefix.route_type, p, &attr.rmac,
+ &attr.mp_nexthop_global_in,
esi_to_str(esi, buf3, sizeof(buf3)));
}
@@ -6436,14 +6437,8 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
/* Locate VNI hash */
vpn = bgp_evpn_lookup_vni(bgp, vni);
- if (!vpn) {
- if (bgp_debug_zebra(NULL))
- flog_warn(
- EC_BGP_EVPN_VPN_VNI,
- "%u: VNI hash entry for VNI %u not found at DEL",
- bgp->vrf_id, vni);
+ if (!vpn)
return 0;
- }
/* Remove all local EVPN routes and schedule for processing (to
* withdraw from peers).
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index c3f648b720..ca6f079401 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -3192,6 +3192,21 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
}
}
+int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
+ bool use_json, int detail)
+{
+ json_object *json = NULL;
+
+ if (use_json)
+ json = json_object_new_object();
+
+ evpn_show_all_routes(vty, bgp, type, json, detail);
+
+ if (use_json)
+ vty_json(vty, json);
+ return CMD_SUCCESS;
+}
+
/*
* Display specified VNI (vty handler)
*/
diff --git a/bgpd/bgp_evpn_vty.h b/bgpd/bgp_evpn_vty.h
index 6b17a83b74..8901644d73 100644
--- a/bgpd/bgp_evpn_vty.h
+++ b/bgpd/bgp_evpn_vty.h
@@ -42,4 +42,7 @@ extern int argv_find_and_parse_oly_idx(struct cmd_token **argv, int argc,
extern int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv,
int argc);
+extern int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
+ bool use_json, int detail);
+
#endif /* _QUAGGA_BGP_EVPN_VTY_H */
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 923586f633..c57e148ef8 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1339,9 +1339,6 @@ void bgp_fsm_change_status(struct peer *peer, enum bgp_fsm_status status)
&& bgp_update_delay_applicable(peer->bgp))
bgp_update_delay_process_status_change(peer);
- /* BGP ORR : Update Active Root */
- bgp_peer_update_orr_active_roots(peer);
-
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s fd %d went from %s to %s", peer->host, peer->fd,
lookup_msg(bgp_status_msg, peer->ostatus, NULL),
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index 6418e15b9a..a6e90612af 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -176,6 +176,4 @@ const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd);
const char *print_global_gr_mode(enum global_mode gl_mode);
const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd);
int bgp_peer_reg_with_nht(struct peer *peer);
-
-extern void bgp_peer_update_orr_active_roots(struct peer *peer);
#endif /* _QUAGGA_BGP_FSM_H */
diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c
index 0e83157ecd..fb1237c022 100644
--- a/bgpd/bgp_keepalives.c
+++ b/bgpd/bgp_keepalives.c
@@ -273,8 +273,9 @@ void bgp_keepalives_on(struct peer *peer)
peer_lock(peer);
}
SET_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON);
+ /* Force the keepalive thread to wake up */
+ pthread_cond_signal(peerhash_cond);
}
- bgp_keepalives_wake();
}
void bgp_keepalives_off(struct peer *peer)
@@ -304,19 +305,15 @@ void bgp_keepalives_off(struct peer *peer)
}
}
-void bgp_keepalives_wake(void)
-{
- frr_with_mutex (peerhash_mtx) {
- pthread_cond_signal(peerhash_cond);
- }
-}
-
int bgp_keepalives_stop(struct frr_pthread *fpt, void **result)
{
assert(fpt->running);
- atomic_store_explicit(&fpt->running, false, memory_order_relaxed);
- bgp_keepalives_wake();
+ frr_with_mutex (peerhash_mtx) {
+ atomic_store_explicit(&fpt->running, false,
+ memory_order_relaxed);
+ pthread_cond_signal(peerhash_cond);
+ }
pthread_join(fpt->thread, result);
return 0;
diff --git a/bgpd/bgp_keepalives.h b/bgpd/bgp_keepalives.h
index d1cb7d2462..e8d0d3d401 100644
--- a/bgpd/bgp_keepalives.h
+++ b/bgpd/bgp_keepalives.h
@@ -74,18 +74,6 @@ extern void bgp_keepalives_init(void);
extern void *bgp_keepalives_start(void *arg);
/**
- * Poking function for keepalives pthread.
- *
- * Under normal circumstances the pthread will automatically wake itself
- * whenever it is necessary to do work. This function may be used to force the
- * thread to wake up and see if there is any work to do, or if it is time to
- * die.
- *
- * It is not necessary to call this after bgp_keepalives_on().
- */
-extern void bgp_keepalives_wake(void);
-
-/**
* Stops the thread and blocks until it terminates.
*/
int bgp_keepalives_stop(struct frr_pthread *fpt, void **result);
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index ced3e1890e..850657d35e 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -134,12 +134,8 @@ DEFINE_MTYPE(BGPD, BGP_EVPN_VRF_IMPORT_RT, "BGP EVPN VRF Import RT");
DEFINE_MTYPE(BGPD, BGP_SRV6_L3VPN, "BGP prefix-sid srv6 l3vpn servcie");
DEFINE_MTYPE(BGPD, BGP_SRV6_VPN, "BGP prefix-sid srv6 vpn service");
-
DEFINE_MTYPE(BGPD, BGP_SRV6_SID, "BGP srv6 segment-id");
DEFINE_MTYPE(BGPD, BGP_SRV6_FUNCTION, "BGP srv6 function");
DEFINE_MTYPE(BGPD, EVPN_REMOTE_IP, "BGP EVPN Remote IP hash entry");
DEFINE_MTYPE(BGPD, BGP_NOTIFICATION, "BGP Notification Message");
-DEFINE_MTYPE(BGPD, BGP_ORR_GROUP, "BGP Optimal Route Reflection Group");
-DEFINE_MTYPE(BGPD, BGP_ORR_GROUP_NAME,
- "BGP Optimal Route Reflection Group Name");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 990c6e1faa..510cfa21c9 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -137,7 +137,5 @@ DECLARE_MTYPE(BGP_SRV6_FUNCTION);
DECLARE_MTYPE(EVPN_REMOTE_IP);
DECLARE_MTYPE(BGP_NOTIFICATION);
-DECLARE_MTYPE(BGP_ORR_GROUP);
-DECLARE_MTYPE(BGP_ORR_GROUP_NAME);
#endif /* _QUAGGA_BGP_MEMORY_H */
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index 84c847d796..32a5e14b11 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -142,21 +142,15 @@ int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
&bpi2->attr->mp_nexthop_global);
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- addr1 = (CHECK_FLAG(
- bpi1->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ addr1 = (bpi1->attr->mp_nexthop_prefer_global)
? bpi1->attr->mp_nexthop_global
: bpi1->attr->mp_nexthop_local;
- addr2 = (CHECK_FLAG(
- bpi2->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ addr2 = (bpi2->attr->mp_nexthop_prefer_global)
? bpi2->attr->mp_nexthop_global
: bpi2->attr->mp_nexthop_local;
- if (!CHECK_FLAG(bpi1->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL) &&
- !CHECK_FLAG(bpi2->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ if (!bpi1->attr->mp_nexthop_prefer_global
+ && !bpi2->attr->mp_nexthop_prefer_global)
compare = !bgp_interface_same(
bpi1->peer->ifp,
bpi2->peer->ifp);
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 9b86c9b4b1..288115f211 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1060,11 +1060,9 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
{
struct bgp_path_info *bpi_ultimate;
struct bgp *bgp_nexthop;
- struct bgp_table *table;
bool nh_valid;
bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
- table = bgp_dest_table(bpi_ultimate->net);
if (bpi->extra && bpi->extra->bgp_orig)
bgp_nexthop = bpi->extra->bgp_orig;
@@ -1072,25 +1070,15 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
bgp_nexthop = bgp_orig;
/*
- * No nexthop tracking for redistributed routes,
- * for static (i.e. coming from the bgp network statement or for
- * EVPN-imported routes that get leaked.
+ * No nexthop tracking for redistributed routes, for
+ * EVPN-imported routes that get leaked, or for routes
+ * leaked between VRFs with accept-own community.
*/
if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE ||
- is_pi_family_evpn(bpi_ultimate))
- nh_valid = 1;
- else if (bpi_ultimate->type == ZEBRA_ROUTE_BGP &&
- bpi_ultimate->sub_type == BGP_ROUTE_STATIC && table &&
- (table->safi == SAFI_UNICAST ||
- table->safi == SAFI_LABELED_UNICAST)) {
- /* Routes from network statement */
- if (CHECK_FLAG(bgp_nexthop->flags, BGP_FLAG_IMPORT_CHECK))
- nh_valid = bgp_find_or_add_nexthop(
- to_bgp, bgp_nexthop, afi, safi, bpi_ultimate,
- NULL, 0, p);
- else
- nh_valid = 1;
- } else
+ is_pi_family_evpn(bpi_ultimate) ||
+ CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_ACCEPT_OWN))
+ nh_valid = true;
+ else
/*
* TBD do we need to do anything about the
* 'connected' parameter?
@@ -1109,9 +1097,8 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
}
if (debug)
- zlog_debug("%s: %pFX nexthop is %svalid (in vrf %s)", __func__,
- p, (nh_valid ? "" : "not "),
- bgp_nexthop->name_pretty);
+ zlog_debug("%s: %pFX nexthop is %svalid (in %s)", __func__, p,
+ (nh_valid ? "" : "not "), bgp_nexthop->name_pretty);
return nh_valid;
}
@@ -1280,7 +1267,6 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (debug)
zlog_debug("%s: ->%s: %pBD Found route, changed attr",
__func__, to_bgp->name_pretty, bn);
- UNSET_FLAG(bpi->attr->nh_flag, BGP_ATTR_NH_REFRESH);
return bpi;
}
@@ -1879,13 +1865,18 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
uint32_t num_labels = 0;
int nexthop_self_flag = 1;
struct bgp_path_info *bpi_ultimate = NULL;
- struct bgp_path_info *bpi;
int origin_local = 0;
struct bgp *src_vrf;
struct interface *ifp;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
+ if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
+ if (debug)
+ zlog_debug("%s: skipping: %s", __func__, debugmsg);
+ return false;
+ }
+
/*
* For VRF-2-VRF route-leaking,
* the source will be the originating VRF.
@@ -1902,14 +1893,6 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
else
src_vrf = from_bgp;
- bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
-
- if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
- if (debug)
- zlog_debug("%s: skipping: %s", __func__, debugmsg);
- return false;
- }
-
/* Check for intersection of route targets */
if (!ecommunity_include(
to_bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
@@ -1924,8 +1907,9 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
/* A route MUST NOT ever be accepted back into its source VRF, even if
* it carries one or more RTs that match that VRF.
*/
- if (prd && memcmp(&prd->val, &to_bgp->vpn_policy[afi].tovpn_rd.val,
- ECOMMUNITY_SIZE) == 0) {
+ if (CHECK_FLAG(path_vpn->flags, BGP_PATH_ACCEPT_OWN) && prd &&
+ memcmp(&prd->val, &to_bgp->vpn_policy[afi].tovpn_rd.val,
+ ECOMMUNITY_SIZE) == 0) {
if (debug)
zlog_debug(
"%s: skipping import, match RD (%pRD) of src VRF (%s) and the prefix (%pFX)",
@@ -1935,8 +1919,8 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
}
if (debug)
- zlog_debug("%s: updating RD %pRD, %pFX to vrf %s", __func__,
- prd, p, to_bgp->name_pretty);
+ zlog_debug("%s: updating RD %pRD, %pFX to %s", __func__, prd, p,
+ to_bgp->name_pretty);
/* shallow copy */
static_attr = *path_vpn->attr;
@@ -1963,18 +1947,6 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
community_strip_accept_own(&static_attr);
- for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
- if (bpi->extra && bpi->extra->parent == path_vpn)
- break;
- }
-
- if (bpi &&
- leak_update_nexthop_valid(to_bgp, bn, &static_attr, afi, safi,
- path_vpn, bpi, src_vrf, p, debug))
- SET_FLAG(static_attr.nh_flag, BGP_ATTR_NH_VALID);
- else
- UNSET_FLAG(static_attr.nh_flag, BGP_ATTR_NH_VALID);
-
/*
* Nexthop: stash and clear
*
@@ -1987,6 +1959,20 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
memset(&nexthop_orig, 0, sizeof(nexthop_orig));
nexthop_orig.family = nhfamily;
+ /* If the path has accept-own community and the source VRF
+ * is valid, reset next-hop to self, to allow importing own
+ * routes between different VRFs on the same node.
+ * Set the nh ifindex to VRF's interface, not the real interface.
+ * Let the kernel to decide with double lookup the real next-hop
+ * interface when installing the route.
+ */
+ if (src_bgp) {
+ subgroup_announce_reset_nhop(nhfamily, &static_attr);
+ ifp = if_get_vrf_loopback(src_vrf->vrf_id);
+ if (ifp)
+ static_attr.nh_ifindex = ifp->ifindex;
+ }
+
switch (nhfamily) {
case AF_INET:
/* save */
@@ -2017,22 +2003,6 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
break;
}
- if (static_attr.nexthop.s_addr == INADDR_ANY &&
- IN6_IS_ADDR_UNSPECIFIED(&static_attr.mp_nexthop_global)) {
- ifp = if_get_vrf_loopback(src_vrf->vrf_id);
- if (ifp)
- static_attr.nh_ifindex = ifp->ifindex;
- } else if (static_attr.nh_ifindex)
- ifp = if_lookup_by_index(static_attr.nh_ifindex,
- src_vrf->vrf_id);
- else
- ifp = NULL;
-
- if (ifp && if_is_operative(ifp))
- SET_FLAG(static_attr.nh_flag, BGP_ATTR_NH_IF_OPERSTATE);
- else
- UNSET_FLAG(static_attr.nh_flag, BGP_ATTR_NH_IF_OPERSTATE);
-
/*
* route map handling
*/
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index b6b0c584d7..cf8ff524e9 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -46,7 +46,6 @@
#include "bgpd/bgp_flowspec_util.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_rd.h"
-#include "bgpd/bgp_mplsvpn.h"
extern struct zclient *zclient;
@@ -389,7 +388,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
if (pi && is_route_parent_evpn(pi))
bnc->is_evpn_gwip_nexthop = true;
- if (is_bgp_static_route && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)) {
+ if (is_bgp_static_route) {
SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
/* If we're toggling the type, re-register */
@@ -424,8 +423,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
- } else if (peer && !connected &&
- CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
+ } else if (peer && !connected
+ && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
@@ -835,13 +834,10 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
{
struct bgp_nexthop_cache_head *tree = NULL;
struct bgp_nexthop_cache *bnc_nhc, *bnc_import;
- struct bgp_path_info *pi;
- struct bgp_dest *dest;
struct bgp *bgp;
struct prefix match;
struct zapi_route nhr;
afi_t afi;
- safi_t safi;
bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp) {
@@ -862,37 +858,25 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
tree = &bgp->nexthop_cache_table[afi];
bnc_nhc = bnc_find(tree, &match, nhr.srte_color, 0);
- if (bnc_nhc)
+ if (!bnc_nhc) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug(
+ "parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache",
+ &nhr.prefix, nhr.srte_color, bgp->name_pretty);
+ } else
bgp_process_nexthop_update(bnc_nhc, &nhr, false);
- else if (BGP_DEBUG(nht, NHT))
- zlog_debug(
- "parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache",
- &nhr.prefix, nhr.srte_color, bgp->name_pretty);
tree = &bgp->import_check_table[afi];
bnc_import = bnc_find(tree, &match, nhr.srte_color, 0);
- if (bnc_import) {
+ if (!bnc_import) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug(
+ "parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check",
+ &nhr.prefix, nhr.srte_color, bgp->name_pretty);
+ } else
bgp_process_nexthop_update(bnc_import, &nhr, true);
- safi = nhr.safi;
- if (bgp->rib[afi][safi]) {
- dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
- &match, NULL);
-
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next)
- if (pi->peer == bgp->peer_self &&
- pi->type == ZEBRA_ROUTE_BGP &&
- pi->sub_type == BGP_ROUTE_STATIC)
- vpn_leak_from_vrf_update(
- bgp_get_default(), bgp, pi);
- }
- } else if (BGP_DEBUG(nht, NHT))
- zlog_debug(
- "parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check",
- &nhr.prefix, nhr.srte_color, bgp->name_pretty);
-
/*
* HACK: if any BGP route is dependant on an SR-policy that doesn't
* exist, zebra will never send NH updates relative to that policy. In
@@ -1005,8 +989,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
*/
else if (pi->attr->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
- if (CHECK_FLAG(pi->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ if (pi->attr->mp_nexthop_prefer_global)
p->u.prefix6 =
pi->attr->mp_nexthop_global;
else
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 79c54dd32d..659e93bdfa 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -1129,13 +1129,6 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
return 0;
}
-static int bgp_auth_parse(struct peer *peer, size_t length)
-{
- bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_AUTH_FAILURE);
- return -1;
-}
-
static bool strict_capability_same(struct peer *peer)
{
int i, j;
@@ -1339,17 +1332,11 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
zlog_debug(
"%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
peer->host, opt_type,
- opt_type == BGP_OPEN_OPT_AUTH
- ? "Authentication"
- : opt_type == BGP_OPEN_OPT_CAP
- ? "Capability"
- : "Unknown",
+ opt_type == BGP_OPEN_OPT_CAP ? "Capability"
+ : "Unknown",
opt_length);
switch (opt_type) {
- case BGP_OPEN_OPT_AUTH:
- ret = bgp_auth_parse(peer, opt_length);
- break;
case BGP_OPEN_OPT_CAP:
ret = bgp_capability_parse(peer, opt_length,
mp_capability, &error);
diff --git a/bgpd/bgp_orr.c b/bgpd/bgp_orr.c
deleted file mode 100644
index 7fed6b775e..0000000000
--- a/bgpd/bgp_orr.c
+++ /dev/null
@@ -1,1176 +0,0 @@
-/*
- * BGP Optimal Route Reflection
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-#include "bgpd/bgpd.h"
-#include "bgpd/bgp_debug.h"
-#include "bgpd/bgp_orr.h"
-#include "bgpd/bgp_vty.h"
-#include "zclient.h"
-
-DEFINE_MTYPE_STATIC(BGPD, ORR_IGP_INFO, "ORR IGP Metric info");
-
-static inline bool is_orr_primary_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->primary && strmatch(orr_group->primary->host, host);
-}
-
-static inline bool is_orr_secondary_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->secondary &&
- strmatch(orr_group->secondary->host, host);
-}
-
-static inline bool is_orr_tertiary_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->tertiary && strmatch(orr_group->tertiary->host, host);
-}
-
-static inline bool is_orr_active_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->active && strmatch(orr_group->active->host, host);
-}
-
-static inline bool is_orr_root_node(struct bgp_orr_group *orr_group, char *host)
-{
- return is_orr_primary_root(orr_group, host) ||
- is_orr_secondary_root(orr_group, host) ||
- is_orr_tertiary_root(orr_group, host);
-}
-
-static inline bool is_peer_orr_group_member(struct peer *peer, afi_t afi,
- safi_t safi, const char *name)
-{
- return peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP) &&
- strmatch(peer->orr_group_name[afi][safi], name);
-}
-
-static inline bool is_peer_reachable(struct peer *peer, afi_t afi, safi_t safi)
-{
- return peer && peer->afc_nego[afi][safi] && peer_established(peer);
-}
-
-static inline bool is_peer_active_eligible(struct peer *peer, afi_t afi,
- safi_t safi, const char *name)
-{
- return is_peer_reachable(peer, afi, safi) &&
- is_peer_orr_group_member(peer, afi, safi, name);
-}
-
-static void bgp_orr_igp_metric_register(struct bgp_orr_group *orr_group,
- bool reg);
-
-static void
-bgp_peer_update_orr_group_active_root(struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_orr_group *orr_group);
-
-static struct bgp_orr_group *bgp_orr_group_new(struct bgp *bgp, afi_t afi,
- safi_t safi, const char *name)
-{
- int ret;
- struct list *orr_group_list = NULL;
- struct bgp_orr_group *orr_group = NULL;
-
- assert(bgp && name);
-
- if (!bgp->orr_group[afi][safi])
- bgp->orr_group[afi][safi] = list_new();
-
- orr_group_list = bgp->orr_group[afi][safi];
- orr_group = XCALLOC(MTYPE_BGP_ORR_GROUP, sizeof(struct bgp_orr_group));
-
- listnode_add(orr_group_list, orr_group);
-
- orr_group->name = XSTRDUP(MTYPE_BGP_ORR_GROUP_NAME, name);
- orr_group->afi = afi;
- orr_group->safi = safi;
- orr_group->primary = orr_group->secondary = orr_group->tertiary = NULL;
- orr_group->bgp = bgp;
-
- /* Initialize ORR Group route table */
- orr_group->route_table = bgp_table_init(bgp, afi, safi);
- assert(orr_group->route_table);
-
- /*
- * Register for opaque messages from IGPs when first ORR group is
- * configured.
- */
- if (!bgp->orr_group_count) {
- ret = zclient_register_opaque(zclient, ORR_IGP_METRIC_UPDATE);
- if (ret != ZCLIENT_SEND_SUCCESS)
- bgp_orr_debug(
- "%s: zclient_register_opaque failed with ret = %d",
- __func__, ret);
- }
-
- bgp->orr_group_count++;
-
- return orr_group;
-}
-
-static void bgp_orr_group_free(struct bgp_orr_group *orr_group)
-{
- afi_t afi;
- safi_t safi;
- struct bgp *bgp;
-
- assert(orr_group && orr_group->bgp && orr_group->name);
-
- bgp_orr_debug("%s: Deleting ORR group %s", __func__, orr_group->name);
-
- afi = orr_group->afi;
- safi = orr_group->safi;
- bgp = orr_group->bgp;
-
- /*
- * Unregister with IGP for metric calculation from specified location
- * and delete igp_metric_info calculated for this group
- */
- bgp_orr_igp_metric_register(orr_group, false);
-
- /* Free RR client list associated with this ORR group */
- if (orr_group->rr_client_list)
- list_delete(&orr_group->rr_client_list);
-
- /* Free route table */
- bgp_table_unlock(orr_group->route_table);
- orr_group->route_table = NULL;
-
- /* Unset ORR Group parameters */
- XFREE(MTYPE_BGP_ORR_GROUP_NAME, orr_group->name);
-
- listnode_delete(bgp->orr_group[afi][safi], orr_group);
- XFREE(MTYPE_BGP_ORR_GROUP, orr_group);
-
- bgp->orr_group_count--;
-
- if (!bgp->orr_group[afi][safi]->count)
- list_delete(&bgp->orr_group[afi][safi]);
-}
-
-struct bgp_orr_group *bgp_orr_group_lookup_by_name(struct bgp *bgp, afi_t afi,
- safi_t safi,
- const char *name)
-{
- struct list *orr_group_list = NULL;
- struct bgp_orr_group *group = NULL;
- struct listnode *node;
-
- assert(bgp);
-
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, group))
- if (strmatch(group->name, name))
- return group;
-
- bgp_orr_debug("%s: For %s, ORR Group '%s' not found.", __func__,
- get_afi_safi_str(afi, safi, false), name);
-
- return NULL;
-}
-
-static char *bgp_orr_group_rrclient_lookup(struct bgp_orr_group *orr_group,
- const char *rr_client_host)
-{
- char *rrclient = NULL;
- struct list *orr_group_rrclient_list = NULL;
- struct listnode *node;
-
- orr_group_rrclient_list = orr_group->rr_client_list;
- if (!orr_group_rrclient_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_rrclient_list, node, rrclient))
- if (strmatch(rrclient, rr_client_host))
- return rrclient;
-
- bgp_orr_debug(
- "%s: For %s, %s not found in ORR Group '%s' RR Client list",
- __func__,
- get_afi_safi_str(orr_group->afi, orr_group->safi, false),
- rr_client_host, orr_group->name);
-
- return NULL;
-}
-
-static void bgp_orr_group_rrclient_update(struct peer *peer, afi_t afi,
- safi_t safi,
- const char *orr_group_name, bool add)
-{
- char *rr_client = NULL;
- struct bgp_orr_group *orr_group = NULL;
- struct list *rr_client_list = NULL;
-
- assert(peer && peer->bgp && orr_group_name);
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(peer->bgp, afi, safi,
- orr_group_name);
- if (!orr_group) {
- bgp_orr_debug("%s: For %s, ORR Group '%s' not found.", __func__,
- get_afi_safi_str(afi, safi, false),
- orr_group_name);
- return;
- }
-
- /* Get BGP ORR client entry for the given RR client */
- rr_client = bgp_orr_group_rrclient_lookup(orr_group, peer->host);
-
- /* Nothing to do */
- if ((rr_client && add) || (!rr_client && !add))
- return;
-
- if (add) {
- /* Create BGP ORR RR client entry to the ORR Group */
- if (!orr_group->rr_client_list)
- orr_group->rr_client_list = list_new();
- rr_client_list = orr_group->rr_client_list;
- rr_client = XSTRDUP(MTYPE_BGP_PEER_HOST, peer->host);
-
- listnode_add(rr_client_list, rr_client);
-
- bgp_orr_debug(
- "%s: For %s, %pBP is added to ORR Group '%s' RR Client list.",
- __func__, get_afi_safi_str(afi, safi, false), peer,
- orr_group_name);
- } else {
- /* Delete BGP ORR RR client entry from the ORR Group */
- listnode_delete(orr_group->rr_client_list, rr_client);
- XFREE(MTYPE_BGP_PEER_HOST, rr_client);
- if (!orr_group->rr_client_list->count)
- list_delete(&orr_group->rr_client_list);
-
- bgp_orr_debug(
- "%s: For %s, %pBP is removed from ORR Group '%s' RR Client list.",
- __func__, get_afi_safi_str(afi, safi, false), peer,
- orr_group_name);
- }
-}
-
-/* Create/Update BGP Optimal Route Reflection Group */
-int bgp_afi_safi_orr_group_set(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name, struct peer *primary,
- struct peer *secondary, struct peer *tertiary)
-{
- bool primary_eligible = false;
- bool secondary_eligible = false;
- bool tertiary_eligible = false;
- struct bgp_orr_group *orr_group = NULL;
-
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' Primary %pBP Secondary %pBP Tertiary %pBP",
- __func__, get_afi_safi_str(afi, safi, false), name, primary,
- secondary, tertiary);
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(bgp, afi, safi, name);
- if (!orr_group) {
- /* Create BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_new(bgp, afi, safi, name);
- }
-
- /* Compare and update Primary Root Address */
- if (primary) {
- if (!orr_group->primary ||
- !strmatch(orr_group->primary->host, primary->host))
- orr_group->primary = primary;
- else
- bgp_orr_debug("%s: No change in Primary Root",
- __func__);
-
- /*
- * Update Active Root if there is a change and primary is
- * reachable.
- */
- primary_eligible =
- is_peer_active_eligible(primary, afi, safi, name);
- if (!orr_group->active) {
- orr_group->active = primary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else if (orr_group->primary &&
- !strmatch(orr_group->active->host,
- orr_group->primary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = primary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else
- bgp_orr_debug("%s: %s", __func__,
- orr_group->primary
- ? "No change in Active Root"
- : "Primary Root is NULL");
- } else {
- if (orr_group->primary) {
- if (orr_group->active &&
- strmatch(orr_group->active->host,
- orr_group->primary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
- orr_group->primary = NULL;
- }
- }
-
- /* Compare and update Secondary Root Address */
- if (secondary) {
- if (!orr_group->secondary ||
- !strmatch(orr_group->secondary->host, secondary->host))
- orr_group->secondary = secondary;
- else
- bgp_orr_debug("%s: No change in Secondary Root",
- __func__);
-
- /* Update Active Root if Primary is not reachable */
- secondary_eligible =
- is_peer_active_eligible(secondary, afi, safi, name);
- if (!orr_group->active) {
- orr_group->active = secondary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else if (!primary_eligible && orr_group->secondary &&
- !strmatch(orr_group->active->host,
- orr_group->secondary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = secondary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else
- bgp_orr_debug(
- "%s: %s", __func__,
- primary_eligible
- ? "Primary is Active Root"
- : orr_group->secondary
- ? "No change in Active Root"
- : "Secondary Root is NULL");
- } else {
- if (orr_group->secondary) {
- if (orr_group->active &&
- strmatch(orr_group->active->host,
- orr_group->secondary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
- orr_group->secondary = NULL;
- }
- }
-
- /* Compare and update Tertiary Root Address */
- if (tertiary) {
- if (!orr_group->tertiary ||
- !strmatch(orr_group->tertiary->host, tertiary->host))
- orr_group->tertiary = tertiary;
- else
- bgp_orr_debug("%s: No change in Tertiay Root",
- __func__);
-
- /*
- * Update Active Root if Primary & Secondary are not reachable
- */
- tertiary_eligible =
- is_peer_active_eligible(tertiary, afi, safi, name);
- if (!orr_group->active) {
- orr_group->active = tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else if (!primary_eligible && !secondary_eligible &&
- orr_group->tertiary &&
- !strmatch(orr_group->active->host,
- orr_group->tertiary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else
- bgp_orr_debug(
- "%s: %s", __func__,
- primary_eligible
- ? "Primary is Active Root"
- : secondary_eligible
- ? "Secondary is Active Root"
- : !orr_group->tertiary
- ? "Tertiary Root is NULL"
- : "No change in Active Root");
- } else {
- if (orr_group->tertiary) {
- if (orr_group->active &&
- strmatch(orr_group->active->host,
- orr_group->tertiary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
- orr_group->tertiary = NULL;
- }
- }
-
- if (orr_group->active && !primary_eligible && !secondary_eligible &&
- !tertiary_eligible) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
-
- bgp_orr_debug("%s: For %s, ORR Group '%s' Active Root is %pBP",
- __func__, get_afi_safi_str(afi, safi, false), name,
- orr_group->active);
-
- return CMD_SUCCESS;
-}
-
-/* Delete BGP Optimal Route Reflection Group */
-int bgp_afi_safi_orr_group_unset(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name)
-{
- struct bgp_orr_group *orr_group;
-
- orr_group = bgp_orr_group_lookup_by_name(bgp, afi, safi, name);
- if (!orr_group)
- return CMD_WARNING;
-
- /* Check if there are any neighbors configured with this ORR Group */
- if (orr_group->rr_client_list) {
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' not removed as '%s' is configured on neighbor(s)",
- __func__,
- get_afi_safi_str(orr_group->afi, orr_group->safi,
- false),
- name, name);
- return CMD_WARNING;
- }
-
- bgp_orr_group_free(orr_group);
- return CMD_SUCCESS;
-}
-
-/* Set optimal route reflection group to the peer */
-static int peer_orr_group_set(struct peer *peer, afi_t afi, safi_t safi,
- const char *orr_group_name)
-{
- struct bgp_orr_group *orr_group = NULL;
-
- if (!peer)
- return CMD_WARNING;
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(peer->bgp, afi, safi,
- orr_group_name);
- if (!orr_group) {
- /* Create BGP ORR entry for the given address-family */
- orr_group =
- bgp_orr_group_new(peer->bgp, afi, safi, orr_group_name);
- }
-
- /* Skip processing if there is no change in ORR Group */
- if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP)) {
- if (strmatch(peer->orr_group_name[afi][safi], orr_group_name)) {
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' is already configured on %pBP",
- __func__, get_afi_safi_str(afi, safi, false),
- orr_group_name, peer);
- return CMD_SUCCESS;
- }
- /* Remove the peer from ORR Group's peer list */
- bgp_orr_group_rrclient_update(peer, afi, safi,
- peer->orr_group_name[afi][safi],
- false);
- XFREE(MTYPE_BGP_ORR_GROUP_NAME,
- peer->orr_group_name[afi][safi]);
- }
-
- peer->orr_group_name[afi][safi] =
- XSTRDUP(MTYPE_BGP_ORR_GROUP_NAME, orr_group_name);
- SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORR_GROUP);
-
- /* Add the peer to ORR Group's client list */
- bgp_orr_group_rrclient_update(peer, afi, safi, orr_group_name, true);
-
- /* Update ORR group active root and register with IGP */
- bgp_peer_update_orr_group_active_root(peer, afi, safi, orr_group);
-
- return CMD_SUCCESS;
-}
-
-/* Unset optimal route reflection group from the peer*/
-int peer_orr_group_unset(struct peer *peer, afi_t afi, safi_t safi,
- const char *orr_group_name)
-{
- struct bgp_orr_group *orr_group = NULL;
-
- assert(peer && peer->bgp && orr_group_name);
-
- if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP) ||
- !strmatch(peer->orr_group_name[afi][safi], orr_group_name)) {
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' is not configured on %pBP",
- __func__, get_afi_safi_str(afi, safi, false),
- orr_group_name, peer);
- return CMD_ERR_NO_MATCH;
- }
-
- /* Check if this RR Client is one of the root nodes */
- orr_group = bgp_orr_group_lookup_by_name(peer->bgp, afi, safi,
- orr_group_name);
-
- /* Should not be Null when orr-group is enabled on peer */
- assert(orr_group);
-
- /* Check if the peer is one of the root nodes of the ORR group */
- if (is_orr_root_node(orr_group, peer->host))
- return CMD_WARNING;
-
- /* Remove the peer from ORR Group's client list */
- bgp_orr_group_rrclient_update(peer, afi, safi, orr_group_name, false);
-
- /* Update ORR group active root and unregister with IGP */
- bgp_peer_update_orr_group_active_root(peer, afi, safi, orr_group);
-
- UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORR_GROUP);
- XFREE(MTYPE_BGP_ORR_GROUP_NAME, peer->orr_group_name[afi][safi]);
-
- return CMD_SUCCESS;
-}
-
-int bgp_afi_safi_orr_group_set_vty(struct vty *vty, afi_t afi, safi_t safi,
- const char *name, const char *primary_str,
- const char *secondary_str,
- const char *tertiary_str, bool unset)
-{
- int ret = CMD_WARNING_CONFIG_FAILED;
- struct bgp *bgp;
- struct peer *primary = NULL, *secondary = NULL, *tertiary = NULL;
-
- bgp = bgp_get_default();
- if (!bgp) {
- vty_out(vty, "%% No BGP process is configured\n");
- return ret;
- }
-
- if (unset) {
- ret = bgp_afi_safi_orr_group_unset(bgp, afi, safi, name);
- if (ret != CMD_SUCCESS)
- vty_out(vty,
- "%% ORR Group %s not removed as '%s' is not found OR configured on neighbor(s)\n",
- name, name);
- return ret;
- }
-
- primary = peer_and_group_lookup_vty(vty, primary_str);
- if (!primary || !peer_af_flag_check(primary, afi, safi,
- PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty,
- "%% Primary Root is not a Route Reflector Client\n");
- return ret;
- }
-
- if (secondary_str) {
- secondary = peer_and_group_lookup_vty(vty, secondary_str);
- if (!secondary ||
- !peer_af_flag_check(secondary, afi, safi,
- PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty,
- "%% Secondary Root is not a Route Reflector Client\n");
- return ret;
- }
- }
-
- if (tertiary_str) {
- tertiary = peer_and_group_lookup_vty(vty, tertiary_str);
- if (!tertiary ||
- !peer_af_flag_check(tertiary, afi, safi,
- PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty,
- "%% Tertiary Root is not a Route Reflector Client\n");
- return ret;
- }
- }
- return bgp_afi_safi_orr_group_set(bgp, afi, safi, name, primary,
- secondary, tertiary);
-}
-
-/* Set optimal route reflection group name to the peer. */
-int peer_orr_group_set_vty(struct vty *vty, const char *ip_str, afi_t afi,
- safi_t safi, const char *orr_group_name, bool unset)
-{
- int ret = CMD_WARNING_CONFIG_FAILED;
- struct peer *peer;
-
- peer = peer_and_group_lookup_vty(vty, ip_str);
- if (!peer)
- return ret;
-
- if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty, "%% Neighbor %s is not a Route Reflector Client\n",
- peer->host);
- return ret;
- }
-
- if (!unset) {
- ret = peer_orr_group_set(peer, afi, safi, orr_group_name);
- if (ret != CMD_SUCCESS)
- vty_out(vty, "%% ORR Group '%s' is not configured\n",
- orr_group_name);
- } else {
- ret = peer_orr_group_unset(peer, afi, safi, orr_group_name);
- if (ret == CMD_ERR_NO_MATCH)
- vty_out(vty,
- "%% ORR Group '%s' is not configured on %s\n",
- orr_group_name, peer->host);
- else if (ret == CMD_WARNING)
- vty_out(vty,
- "%% %s is one of the root nodes of ORR Group '%s'.\n",
- peer->host, orr_group_name);
- }
- return bgp_vty_return(vty, ret);
-}
-
-void bgp_config_write_orr(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi)
-{
- struct list *orr_group_list;
- struct listnode *node;
- struct bgp_orr_group *orr_group;
-
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, orr_group)) {
- /* optimal route reflection configuration */
- vty_out(vty, " optimal-route-reflection %s", orr_group->name);
- if (orr_group->primary)
- vty_out(vty, " %s", orr_group->primary->host);
- if (orr_group->secondary)
- vty_out(vty, " %s", orr_group->secondary->host);
- if (orr_group->tertiary)
- vty_out(vty, " %s", orr_group->tertiary->host);
- vty_out(vty, "\n");
- }
-}
-
-static void bgp_show_orr_group(struct vty *vty, struct bgp_orr_group *orr_group,
- afi_t afi, safi_t safi)
-{
- char *rrclient = NULL;
- struct listnode *node;
- struct bgp_orr_igp_metric *igp_metric = NULL;
- struct list *orr_group_rrclient_list = NULL;
- struct list *orr_group_igp_metric_info = NULL;
-
- if (!orr_group)
- return;
-
- vty_out(vty, "\nORR group: %s, %s\n", orr_group->name,
- get_afi_safi_str(afi, safi, false));
- vty_out(vty, "Configured root:");
- vty_out(vty, " primary: %pBP,", orr_group->primary);
- vty_out(vty, " secondary: %pBP,", orr_group->secondary);
- vty_out(vty, " tertiary: %pBP\n", orr_group->tertiary);
- vty_out(vty, "Active Root: %pBP\n", orr_group->active);
-
- orr_group_rrclient_list = orr_group->rr_client_list;
- if (!orr_group_rrclient_list)
- return;
-
- vty_out(vty, "\nRR Clients mapped:\n");
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_rrclient_list, node, rrclient))
- vty_out(vty, "%s\n", rrclient);
-
- vty_out(vty, "\nNumber of mapping entries: %d\n\n",
- orr_group_rrclient_list->count);
-
-
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (!orr_group_igp_metric_info)
- return;
- vty_out(vty, "Prefix\t\t\t\t\t\tCost\n");
- for (ALL_LIST_ELEMENTS_RO(orr_group_igp_metric_info, node,
- igp_metric)) {
- vty_out(vty, "%pFX\t\t\t\t\t\t%d\n", &igp_metric->prefix,
- igp_metric->igp_metric);
- }
- vty_out(vty, "\nNumber of mapping entries: %d\n\n",
- orr_group_igp_metric_info->count);
-}
-
-int bgp_show_orr(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
- const char *orr_group_name, uint8_t show_flags)
-{
- struct listnode *node;
- struct bgp_orr_group *orr_group = NULL;
- struct list *orr_group_list = NULL;
- int ret = 0;
-
- assert(bgp);
-
- /* Display the matching entries for the given ORR Group */
- if (orr_group_name) {
- orr_group = bgp_orr_group_lookup_by_name(bgp, afi, safi,
- orr_group_name);
- if (!orr_group) {
- vty_out(vty, "%% ORR Group %s not found\n",
- orr_group_name);
- return CMD_WARNING;
- }
- bgp_show_orr_group(vty, orr_group, afi, safi);
- return ret;
- }
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return ret;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, orr_group))
- bgp_show_orr_group(vty, orr_group, afi, safi);
-
- return ret;
-}
-
-/* Check if the Route Reflector Client belongs to any ORR Group */
-bool peer_orr_rrclient_check(struct peer *peer, afi_t afi, safi_t safi)
-{
- char *rrclient = NULL;
- struct listnode *node;
- struct list *orr_group_list = NULL;
- struct list *orr_group_rrclient_list = NULL;
- struct bgp_orr_group *orr_group = NULL;
-
- assert(peer && peer->bgp);
-
- orr_group_list = peer->bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return false;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, orr_group)) {
- /* Check if peer configured as primary/secondary/tertiary root
- */
- if (is_orr_root_node(orr_group, peer->host))
- return true;
- /*
- * Check if peer is mapped to any ORR Group in this
- * Address Family.
- */
- orr_group_rrclient_list = orr_group->rr_client_list;
- if (!orr_group_rrclient_list)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_rrclient_list, node,
- rrclient))
- if (strmatch(rrclient, peer->host))
- return true;
- }
- return false;
-}
-
-static void
-bgp_peer_update_orr_group_active_root(struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_orr_group *orr_group)
-{
- assert(peer && orr_group);
-
- /* Nothing to do if this peer is not one of the root nodes */
- if (!is_orr_root_node(orr_group, peer->host))
- return;
-
- /* Root is reachable and group member, update Active Root if needed */
- if (is_peer_active_eligible(peer, afi, safi, orr_group->name)) {
- /* Nothing to do, if this is the current Active Root */
- if (is_orr_active_root(orr_group, peer->host))
- return;
-
- /* If Active is null, update this node as Active Root */
- if (!orr_group->active) {
- orr_group->active = peer;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
-
- /* If this is Primary and current Active is not Primary */
- if (is_orr_primary_root(orr_group, peer->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = peer;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
-
- /*
- * If this is Secondary and current Active is not
- * Primary/Secondary
- */
- if (is_orr_secondary_root(orr_group, peer->host)) {
- if (is_orr_active_root(orr_group,
- orr_group->primary->host))
- return;
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = peer;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
- return;
- }
-
- /* Non Active Root is unreachable, so nothing to do */
- if (!is_orr_active_root(orr_group, peer->host))
- return;
-
- if (is_orr_primary_root(orr_group, peer->host)) {
- /* If secondary is reachable, update it as Active */
- if (is_peer_active_eligible(orr_group->secondary, afi, safi,
- orr_group->name)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = orr_group->secondary;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
-
- /* If tertiary is reachable, update it as Active */
- if (is_peer_active_eligible(orr_group->tertiary, afi, safi,
- orr_group->name)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = orr_group->tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
- } else {
- if (is_orr_secondary_root(orr_group, peer->host)) {
- /* If tertiary is reachable, update it as Active */
- if (is_peer_active_eligible(orr_group->tertiary, afi,
- safi, orr_group->name)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = orr_group->tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
- }
- }
-
- /* Assign Active as null */
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = NULL;
-
- bgp_orr_debug("%s: For %s, ORR Group '%s' has no active root", __func__,
- get_afi_safi_str(afi, safi, false),
- peer->orr_group_name[afi][safi]);
-}
-
-void bgp_peer_update_orr_active_roots(struct peer *peer)
-{
- afi_t afi;
- safi_t safi;
- struct bgp_orr_group *orr_group;
-
- assert(peer && peer->bgp);
-
- FOREACH_AFI_SAFI (afi, safi) {
- if (!peer->orr_group_name[afi][safi])
- continue;
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(
- peer->bgp, afi, safi, peer->orr_group_name[afi][safi]);
- assert(orr_group);
-
- /* Free ORR related memory. */
- if (peer->status != Deleted) {
- bgp_peer_update_orr_group_active_root(peer, afi, safi,
- orr_group);
- continue;
- }
-
- if (!is_orr_root_node(orr_group, peer->host)) {
- peer_orr_group_unset(peer, afi, safi,
- peer->orr_group_name[afi][safi]);
- continue;
- }
-
- if (is_orr_primary_root(orr_group, peer->host)) {
- orr_group->primary = orr_group->secondary;
- orr_group->secondary = orr_group->tertiary;
- } else if (is_orr_secondary_root(orr_group, peer->host))
- orr_group->secondary = orr_group->tertiary;
- orr_group->tertiary = NULL;
-
- bgp_afi_safi_orr_group_set(peer->bgp, afi, safi,
- orr_group->name, orr_group->primary,
- orr_group->secondary,
- orr_group->tertiary);
- peer_orr_group_unset(peer, afi, safi,
- peer->orr_group_name[afi][safi]);
- }
-}
-
-/* IGP metric calculated from Active Root */
-static int bgp_orr_igp_metric_update(struct orr_igp_metric_info *table)
-{
- afi_t afi;
- safi_t safi;
- bool add = false;
- bool root_found = false;
- uint32_t instId = 0;
- uint32_t numEntries = 0;
- uint32_t entry = 0;
- uint8_t proto = ZEBRA_ROUTE_MAX;
- struct bgp *bgp = NULL;
- struct prefix pfx, root = {0};
-
- struct list *orr_group_list = NULL;
- struct bgp_orr_group *group = NULL;
- struct listnode *node, *nnode;
-
- struct bgp_orr_igp_metric *igp_metric = NULL;
- struct list *bgp_orr_igp_metric = NULL;
-
- bgp = bgp_get_default();
- assert(bgp && table);
-
- proto = table->proto;
- afi = family2afi(table->root.family);
- safi = table->safi;
- instId = table->instId;
- add = table->add;
- numEntries = table->num_entries;
- prefix_copy(&root, &table->root);
-
- if ((proto != ZEBRA_ROUTE_OSPF) && (proto != ZEBRA_ROUTE_OSPF6) &&
- (proto != ZEBRA_ROUTE_ISIS)) {
- bgp_orr_debug("%s: Message received from unsupported protocol",
- __func__);
- return -1;
- }
-
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list) {
- bgp_orr_debug(
- "%s: Address family %s has no ORR Groups configured",
- __func__, get_afi_safi_str(afi, safi, false));
- return -1;
- }
-
- if (BGP_DEBUG(optimal_route_reflection, ORR)) {
- zlog_debug(
- "[BGP-ORR] %s: Received metric update from protocol %s instance %d",
- __func__,
- proto == ZEBRA_ROUTE_ISIS
- ? "ISIS"
- : (proto == ZEBRA_ROUTE_OSPF ? "OSPF"
- : "OSPF6"),
- instId);
- zlog_debug("[BGP-ORR] %s: Address family %s", __func__,
- get_afi_safi_str(afi, safi, false));
- zlog_debug("[BGP-ORR] %s: Root %pFX", __func__, &root);
- zlog_debug("[BGP-ORR] %s: Number of entries to be %s %d",
- __func__, add ? "added" : "deleted", numEntries);
- zlog_debug("[BGP-ORR] %s: Prefix (Cost) :", __func__);
- for (entry = 0; entry < numEntries; entry++)
- zlog_debug("[BGP-ORR] %s: %pFX (%d)", __func__,
- &table->nexthop[entry].prefix,
- table->nexthop[entry].metric);
- }
- /*
- * Update IGP metric info of all ORR Groups having this as active root
- */
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, group)) {
- if (str2prefix(group->active->host, &pfx) == 0) {
- bgp_orr_debug("%s: Malformed prefix for %pBP", __func__,
- group->active);
- continue;
- }
- /*
- * Copy IGP info if root matches with the active root of the
- * group
- */
- if (prefix_cmp(&pfx, &root) == 0) {
- if (add) {
- /* Add new routes */
- if (!group->igp_metric_info)
- group->igp_metric_info = list_new();
-
- bgp_orr_igp_metric = group->igp_metric_info;
- if (!bgp_orr_igp_metric)
- bgp_orr_igp_metric_register(group,
- false);
- assert(bgp_orr_igp_metric);
-
- for (entry = 0; entry < numEntries; entry++) {
- igp_metric = XCALLOC(
- MTYPE_ORR_IGP_INFO,
- sizeof(struct
- bgp_orr_igp_metric));
- if (!igp_metric)
- bgp_orr_igp_metric_register(
- group, false);
-
- prefix_copy(
- &igp_metric->prefix,
- &table->nexthop[entry].prefix);
- igp_metric->igp_metric =
- table->nexthop[entry].metric;
- listnode_add(bgp_orr_igp_metric,
- igp_metric);
- }
- } else {
- /* Delete old routes */
- for (entry = 0; entry < numEntries; entry++) {
- for (ALL_LIST_ELEMENTS(
- group->igp_metric_info,
- node, nnode, igp_metric)) {
- if (prefix_cmp(
- &igp_metric->prefix,
- &table->nexthop[entry]
- .prefix))
- continue;
- listnode_delete(
- group->igp_metric_info,
- igp_metric);
- XFREE(MTYPE_ORR_IGP_INFO,
- igp_metric);
- }
- }
- }
- root_found = true;
- break;
- }
- }
- /* Received IGP for root node thats not found in ORR active roots */
- if (!root_found) {
- bgp_orr_debug(
- "%s: Received IGP SPF information for root %pFX which is not an ORR active root",
- __func__, &root);
- }
- assert(root_found);
- return 0;
-}
-
-/* Register with IGP for sending SPF info */
-static void bgp_orr_igp_metric_register(struct bgp_orr_group *orr_group,
- bool reg)
-{
- int ret;
- struct orr_igp_metric_reg msg;
- struct prefix p;
- char *rr_client = NULL;
-
- assert(orr_group);
-
- if (!orr_group->active)
- return;
-
- memset(&msg, 0, sizeof(msg));
- ret = str2prefix(orr_group->active->host, &p);
-
- /* Malformed prefix */
- assert(ret);
-
- /* Check if the active root is part of this ORR group */
- rr_client = bgp_orr_group_rrclient_lookup(orr_group,
- orr_group->active->host);
- if (reg && !rr_client) {
- bgp_orr_debug(
- "%s: active root %pBP is not part of this ORR group",
- __func__, orr_group->active);
- return;
- }
-
- msg.reg = reg;
- msg.proto = ZEBRA_ROUTE_BGP;
- msg.safi = orr_group->safi;
- prefix_copy(&msg.prefix, &p);
- strlcpy(msg.group_name, orr_group->name, sizeof(msg.group_name));
-
- bgp_orr_debug(
- "%s: %s with IGP for metric calculation from location %pFX",
- __func__, reg ? "Register" : "Unregister", &msg.prefix);
-
- if (zclient_send_opaque(zclient, ORR_IGP_METRIC_REGISTER,
- (uint8_t *)&msg,
- sizeof(msg)) == ZCLIENT_SEND_FAILURE)
- zlog_warn("[BGP-ORR] %s: Failed to send message to IGP.",
- __func__);
-
- /* Free IGP metric info calculated from previous active location */
- if (!reg && orr_group->igp_metric_info)
- list_delete(&orr_group->igp_metric_info);
-}
-
-/* BGP ORR message processing */
-int bgg_orr_message_process(enum bgp_orr_msg_type msg_type, void *msg)
-{
- int ret = 0;
-
- assert(msg && msg_type > BGP_ORR_IMSG_INVALID &&
- msg_type < BGP_ORR_IMSG_MAX);
- switch (msg_type) {
- case BGP_ORR_IMSG_GROUP_CREATE:
- break;
- case BGP_ORR_IMSG_GROUP_DELETE:
- break;
- case BGP_ORR_IMSG_GROUP_UPDATE:
- break;
- case BGP_ORR_IMSG_SET_ORR_ON_PEER:
- break;
- case BGP_ORR_IMSG_UNSET_ORR_ON_PEER:
- break;
- case BGP_ORR_IMSG_IGP_METRIC_UPDATE:
- ret = bgp_orr_igp_metric_update(
- (struct orr_igp_metric_info *)msg);
- break;
- case BGP_ORR_IMSG_SHOW_ORR:
- /* bgp_show_orr */
- break;
- case BGP_ORR_IMSG_SHOW_ORR_GROUP:
- /* bgp_show_orr_group */
- break;
- default:
- break;
- }
-
- /* Free Memory */
- return ret;
-}
-
-/*
- * Cleanup ORR information - invoked at the time of bgpd exit or
- * when the BGP instance (default) is being freed.
- */
-void bgp_orr_cleanup(struct bgp *bgp)
-{
- afi_t afi;
- safi_t safi;
- struct listnode *node, *nnode;
- struct bgp_orr_group *orr_group;
-
- assert(bgp);
-
- if (!bgp->orr_group_count)
- return;
-
- FOREACH_AFI_SAFI (afi, safi) {
- for (ALL_LIST_ELEMENTS(bgp->orr_group[afi][safi], node, nnode,
- orr_group))
- bgp_orr_group_free(orr_group);
- }
-}
diff --git a/bgpd/bgp_orr.h b/bgpd/bgp_orr.h
deleted file mode 100644
index 158de30342..0000000000
--- a/bgpd/bgp_orr.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * BGP Optimal Route Reflection
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _FRR_BGP_ORR_H
-#define _FRR_BGP_ORR_H
-#include <zebra.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Macro to log debug message */
-#define bgp_orr_debug(...) \
- do { \
- if (BGP_DEBUG(optimal_route_reflection, ORR)) \
- zlog_debug("[BGP-ORR] " __VA_ARGS__); \
- } while (0)
-
-
-/* BGP ORR Message Type */
-enum bgp_orr_msg_type {
- BGP_ORR_IMSG_INVALID = 0,
-
- /* ORR group update */
- BGP_ORR_IMSG_GROUP_CREATE = 1,
- BGP_ORR_IMSG_GROUP_DELETE,
- BGP_ORR_IMSG_GROUP_UPDATE,
-
- /* ORR group update on a BGP RR Client */
- BGP_ORR_IMSG_SET_ORR_ON_PEER = 4,
- BGP_ORR_IMSG_UNSET_ORR_ON_PEER,
-
- /* ORR IGP Metric Update from IGP from requested Location */
- BGP_ORR_IMSG_IGP_METRIC_UPDATE = 6,
-
- /* ORR Group Related Information display */
- BGP_ORR_IMSG_SHOW_ORR = 7,
- BGP_ORR_IMSG_SHOW_ORR_GROUP,
-
- /* Invalid Message Type*/
- BGP_ORR_IMSG_MAX
-};
-
-extern struct zclient *zclient;
-
-extern void bgp_config_write_orr(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi);
-
-extern int bgp_afi_safi_orr_group_set_vty(struct vty *vty, afi_t afi,
- safi_t safi, const char *name,
- const char *primary_str,
- const char *secondary_str,
- const char *tertiary_str, bool unset);
-extern int peer_orr_group_unset(struct peer *peer, afi_t afi, safi_t safi,
- const char *orr_group_name);
-extern int peer_orr_group_set_vty(struct vty *vty, const char *ip_str,
- afi_t afi, safi_t safi,
- const char *orr_group_name, bool unset);
-extern bool peer_orr_rrclient_check(struct peer *peer, afi_t afi, safi_t safi);
-
-extern int bgp_show_orr(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi, const char *orr_group_name,
- uint8_t show_flags);
-
-extern int bgp_afi_safi_orr_group_set(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name, struct peer *primary,
- struct peer *secondary,
- struct peer *tertiary);
-extern int bgp_afi_safi_orr_group_unset(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name);
-
-extern void bgp_peer_update_orr_active_roots(struct peer *peer);
-
-extern int bgg_orr_message_process(enum bgp_orr_msg_type msg_type, void *msg);
-
-extern struct bgp_orr_group *bgp_orr_group_lookup_by_name(struct bgp *bgp,
- afi_t afi,
- safi_t safi,
- const char *name);
-extern void bgp_orr_cleanup(struct bgp *bgp);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _FRR_BGP_ORR_H */
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 5d4cf2a6aa..9e7c75318e 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -487,6 +487,16 @@ void bgp_generate_updgrp_packets(struct thread *thread)
if (peer->t_routeadv)
return;
+ /*
+ * Since the following is a do while loop
+ * let's stop adding to the outq if we are
+ * already at the limit.
+ */
+ if (peer->obuf->count >= bm->outq_limit) {
+ bgp_write_proceed_actions(peer);
+ return;
+ }
+
do {
enum bgp_af_index index;
@@ -609,7 +619,8 @@ void bgp_generate_updgrp_packets(struct thread *thread)
bgp_packet_add(peer, s);
bpacket_queue_advance_peer(paf);
}
- } while (s && (++generated < wpq));
+ } while (s && (++generated < wpq) &&
+ (peer->obuf->count <= bm->outq_limit));
if (generated)
bgp_writes_on(peer);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0ef939875a..3f07e53bb6 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -72,7 +72,6 @@
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_mac.h"
#include "bgpd/bgp_network.h"
-#include "bgpd/bgp_orr.h"
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_rpki.h"
@@ -566,7 +565,6 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
enum bgp_path_selection_reason *reason)
{
const struct prefix *new_p;
- struct prefix exist_p;
struct attr *newattr, *existattr;
enum bgp_peer_sort new_sort;
enum bgp_peer_sort exist_sort;
@@ -599,11 +597,6 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
bool new_origin, exist_origin;
struct bgp_path_info *bpi_ultimate;
- struct bgp_orr_group *orr_group = NULL;
- struct listnode *node;
- struct bgp_orr_igp_metric *igp_metric = NULL;
- struct list *orr_group_igp_metric_info = NULL;
-
*paths_eq = 0;
/* 0. Null check. */
@@ -1139,49 +1132,6 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (exist->extra)
existm = exist->extra->igpmetric;
- if (new->peer->orr_group_name[afi][safi]) {
- ret = str2prefix(new->peer->host, &exist_p);
- orr_group = bgp_orr_group_lookup_by_name(
- bgp, afi, safi, new->peer->orr_group_name[afi][safi]);
- if (orr_group) {
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (orr_group_igp_metric_info) {
- for (ALL_LIST_ELEMENTS_RO(
- orr_group_igp_metric_info, node,
- igp_metric)) {
- if (ret &&
- prefix_cmp(&exist_p,
- &igp_metric->prefix) ==
- 0) {
- newm = igp_metric->igp_metric;
- break;
- }
- }
- }
- }
- }
- if (exist->peer->orr_group_name[afi][safi]) {
- ret = str2prefix(exist->peer->host, &exist_p);
- orr_group = bgp_orr_group_lookup_by_name(
- bgp, afi, safi, exist->peer->orr_group_name[afi][safi]);
- if (orr_group) {
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (orr_group_igp_metric_info) {
- for (ALL_LIST_ELEMENTS_RO(
- orr_group_igp_metric_info, node,
- igp_metric)) {
- if (ret &&
- prefix_cmp(&exist_p,
- &igp_metric->prefix) ==
- 0) {
- existm = igp_metric->igp_metric;
- break;
- }
- }
- }
- }
- }
-
if (newm < existm) {
if (debug && peer_sort_ret < 0)
zlog_debug(
@@ -2188,12 +2138,12 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* AS path loop check. */
- if (onlypeer && onlypeer->as_path_loop_detection
- && aspath_loop_check(piattr->aspath, onlypeer->as)) {
+ if (peer->as_path_loop_detection &&
+ aspath_loop_check(piattr->aspath, peer->as)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
"%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
- onlypeer, onlypeer->as);
+ peer, peer->as);
return false;
}
@@ -2323,8 +2273,12 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
&& peer->shared_network
&& (from == bgp->peer_self
|| peer->sort == BGP_PEER_EBGP))) {
- attr->mp_nexthop_len =
- BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
+ if (safi == SAFI_MPLS_VPN)
+ attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
+ else
+ attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
}
/* Clear off link-local nexthop in source, whenever it is not
@@ -8684,7 +8638,6 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
afi_t afi;
route_map_result_t ret;
struct bgp_redist *red;
- struct interface *ifp;
/* Make default attribute. */
bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
@@ -8734,11 +8687,6 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
}
attr.nh_type = nhtype;
attr.nh_ifindex = ifindex;
- ifp = if_lookup_by_index(ifindex, bgp->vrf_id);
- if (ifp && if_is_operative(ifp))
- SET_FLAG(attr.nh_flag, BGP_ATTR_NH_IF_OPERSTATE);
- else
- UNSET_FLAG(attr.nh_flag, BGP_ATTR_NH_IF_OPERSTATE);
attr.med = metric;
attr.distance = distance;
@@ -9425,10 +9373,9 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
"link-local");
if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
- &attr->mp_nexthop_local) !=
- 0) &&
- !CHECK_FLAG(attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ &attr->mp_nexthop_local)
+ != 0)
+ && !attr->mp_nexthop_prefer_global)
json_object_boolean_true_add(
json_nexthop_ll, "used");
else
@@ -9440,11 +9387,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
} else {
/* Display LL if LL/Global both in table unless
* prefer-global is set */
- if (((attr->mp_nexthop_len ==
- BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) &&
- !CHECK_FLAG(attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL)) ||
- (path->peer->conf_if)) {
+ if (((attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+ && !attr->mp_nexthop_prefer_global)
+ || (path->peer->conf_if)) {
if (path->peer->conf_if) {
len = vty_out(vty, "%s",
path->peer->conf_if);
@@ -10706,8 +10652,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object_boolean_true_add(json_nexthop_ll,
"accessible");
- if (!CHECK_FLAG(attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ if (!attr->mp_nexthop_prefer_global)
json_object_boolean_true_add(json_nexthop_ll,
"used");
else
@@ -10717,8 +10662,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, " (%s) %s\n",
inet_ntop(AF_INET6, &attr->mp_nexthop_local,
buf, INET6_ADDRSTRLEN),
- CHECK_FLAG(attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL)
+ attr->mp_nexthop_prefer_global
? "(prefer-global)"
: "(used)");
}
@@ -11812,6 +11756,9 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
1, NULL, NULL);
}
+ if (safi == SAFI_EVPN)
+ return bgp_evpn_show_all_routes(vty, bgp, type, use_json, 0);
+
return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
NULL, NULL, &json_header_depth, show_flags,
rpki_target_state);
@@ -12684,7 +12631,6 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
|alias ALIAS_NAME\
|A.B.C.D/M longer-prefixes\
|X:X::X:X/M longer-prefixes\
- |optimal-route-reflection [WORD$orr_group_name]\
|detail-routes$detail_routes\
] [json$uj [detail$detail_json] | wide$wide]",
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
@@ -12734,8 +12680,6 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
"Display route and more specific routes\n"
"IPv6 prefix\n"
"Display route and more specific routes\n"
- "Display Optimal Route Reflection RR Clients\n"
- "ORR Group name\n"
"Display detailed version of all routes\n"
JSON_STR
"Display detailed version of JSON output\n"
@@ -12753,7 +12697,6 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
uint16_t show_flags = 0;
enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
struct prefix p;
- bool orr_group = false;
if (uj) {
argc--;
@@ -12931,18 +12874,12 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
output_arg = &p;
}
- if (argv_find(argv, argc, "optimal-route-reflection", &idx))
- orr_group = true;
-
if (!all) {
/* show bgp: AFI_IP6, show ip bgp: AFI_IP */
if (community)
return bgp_show_community(vty, bgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
- show_flags);
else
return bgp_show(vty, bgp, afi, safi, sh_type,
output_arg, show_flags,
@@ -12988,11 +12925,6 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
vty, abgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- bgp_show_orr(vty, bgp, afi,
- safi,
- orr_group_name,
- show_flags);
else
bgp_show(vty, abgp, afi, safi,
sh_type, output_arg,
@@ -13032,11 +12964,6 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
vty, abgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- bgp_show_orr(vty, bgp, afi,
- safi,
- orr_group_name,
- show_flags);
else
bgp_show(vty, abgp, afi, safi,
sh_type, output_arg,
@@ -14010,7 +13937,8 @@ static void show_adj_route_header(struct vty *vty, struct peer *peer,
struct bgp_table *table, int *header1,
int *header2, json_object *json,
json_object *json_scode,
- json_object *json_ocode, bool wide)
+ json_object *json_ocode, bool wide,
+ bool detail)
{
uint64_t version = table ? table->version : 0;
@@ -14044,15 +13972,17 @@ static void show_adj_route_header(struct vty *vty, struct peer *peer,
vty_out(vty, "local AS %u\n",
peer->change_local_as ? peer->change_local_as
: peer->local_as);
- vty_out(vty, BGP_SHOW_SCODE_HEADER);
- vty_out(vty, BGP_SHOW_NCODE_HEADER);
- vty_out(vty, BGP_SHOW_OCODE_HEADER);
- vty_out(vty, BGP_SHOW_RPKI_HEADER);
+ if (!detail) {
+ vty_out(vty, BGP_SHOW_SCODE_HEADER);
+ vty_out(vty, BGP_SHOW_NCODE_HEADER);
+ vty_out(vty, BGP_SHOW_OCODE_HEADER);
+ vty_out(vty, BGP_SHOW_RPKI_HEADER);
+ }
}
*header1 = 0;
}
if (*header2) {
- if (!json)
+ if (!json && !detail)
vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
: BGP_SHOW_HEADER));
*header2 = 0;
@@ -14076,12 +14006,15 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
struct update_subgroup *subgrp;
struct peer_af *paf;
bool route_filtered;
+ bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
|| (safi == SAFI_EVPN))
? true
: false;
+ int display = 0;
+ json_object *json_net = NULL;
bgp = peer->bgp;
@@ -14122,10 +14055,12 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
vty_out(vty, "local AS %u\n",
peer->change_local_as ? peer->change_local_as
: peer->local_as);
- vty_out(vty, BGP_SHOW_SCODE_HEADER);
- vty_out(vty, BGP_SHOW_NCODE_HEADER);
- vty_out(vty, BGP_SHOW_OCODE_HEADER);
- vty_out(vty, BGP_SHOW_RPKI_HEADER);
+ if (!detail) {
+ vty_out(vty, BGP_SHOW_SCODE_HEADER);
+ vty_out(vty, BGP_SHOW_NCODE_HEADER);
+ vty_out(vty, BGP_SHOW_OCODE_HEADER);
+ vty_out(vty, BGP_SHOW_RPKI_HEADER);
+ }
vty_out(vty, "Originating default network %s\n\n",
(afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
@@ -14143,7 +14078,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
show_adj_route_header(vty, peer, table, header1,
header2, json, json_scode,
- json_ocode, wide);
+ json_ocode, wide, detail);
if ((safi == SAFI_MPLS_VPN)
|| (safi == SAFI_ENCAP)
@@ -14187,8 +14122,23 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
&& (route_filtered || ret == RMAP_DENY))
(*filtered_count)++;
- route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
- use_json, json_ar, wide);
+ if (detail) {
+ if (use_json)
+ json_net =
+ json_object_new_object();
+ bgp_show_path_info(
+ NULL /* prefix_rd */, dest, vty,
+ bgp, afi, safi, json_net,
+ BGP_PATH_SHOW_ALL, &display,
+ RPKI_NOT_BEING_USED);
+ if (use_json)
+ json_object_object_addf(
+ json_ar, json_net,
+ "%pFX", rn_p);
+ } else
+ route_vty_out_tmp(vty, dest, rn_p,
+ &attr, safi, use_json,
+ json_ar, wide);
bgp_attr_flush(&attr);
(*output_count)++;
}
@@ -14198,10 +14148,10 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (paf->peer != peer || !adj->attr)
continue;
- show_adj_route_header(vty, peer, table,
- header1, header2,
- json, json_scode,
- json_ocode, wide);
+ show_adj_route_header(
+ vty, peer, table, header1,
+ header2, json, json_scode,
+ json_ocode, wide, detail);
const struct prefix *rn_p =
bgp_dest_get_prefix(dest);
@@ -14228,10 +14178,32 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
show_rd = false;
}
}
- route_vty_out_tmp(
- vty, dest, rn_p, &attr,
- safi, use_json, json_ar,
- wide);
+ if (detail) {
+ if (use_json)
+ json_net =
+ json_object_new_object();
+ bgp_show_path_info(
+ NULL /* prefix_rd
+ */
+ ,
+ dest, vty, bgp,
+ afi, safi,
+ json_net,
+ BGP_PATH_SHOW_ALL,
+ &display,
+ RPKI_NOT_BEING_USED);
+ if (use_json)
+ json_object_object_addf(
+ json_ar,
+ json_net,
+ "%pFX",
+ rn_p);
+ } else
+ route_vty_out_tmp(
+ vty, dest, rn_p,
+ &attr, safi,
+ use_json,
+ json_ar, wide);
(*output_count)++;
} else {
(*filtered_count)++;
@@ -14244,7 +14216,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
show_adj_route_header(vty, peer, table, header1,
header2, json, json_scode,
- json_ocode, wide);
+ json_ocode, wide, detail);
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
pi = pi->next) {
@@ -14496,27 +14468,28 @@ DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
show_flags);
}
-DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
- show_ip_bgp_instance_neighbor_advertised_route_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [json$uj | wide$wide]",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- BGP_AFI_HELP_STR
- BGP_SAFI_WITH_LABEL_HELP_STR
- "Display the entries for all address families\n"
- "Detailed information on TCP and BGP neighbor connections\n"
- "Neighbor to display information about\n"
- "Neighbor to display information about\n"
- "Neighbor on BGP configured interface\n"
- "Display the routes advertised to a BGP neighbor\n"
- "Display the received routes from neighbor\n"
- "Display the filtered routes received from neighbor\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n"
- JSON_STR
- "Increase table width for longer prefixes\n")
+DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
+ show_ip_bgp_instance_neighbor_advertised_route_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [detail$detail] [json$uj | wide$wide]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ BGP_AFI_HELP_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ "Display the entries for all address families\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Neighbor to display information about\n"
+ "Neighbor on BGP configured interface\n"
+ "Display the routes advertised to a BGP neighbor\n"
+ "Display the received routes from neighbor\n"
+ "Display the filtered routes received from neighbor\n"
+ "Route-map to modify the attributes\n"
+ "Name of the route map\n"
+ "Display detailed version of routes\n"
+ JSON_STR
+ "Increase table width for longer prefixes\n")
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
@@ -14530,6 +14503,9 @@ DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
struct listnode *node;
struct bgp *abgp;
+ if (detail)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
+
if (uj) {
argc--;
SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
@@ -14970,6 +14946,7 @@ uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
struct bgp_distance *bdistance;
struct access_list *alist;
struct bgp_static *bgp_static;
+ struct bgp_path_info *bpi_ultimate;
if (!bgp)
return 0;
@@ -14979,6 +14956,12 @@ uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
if (pinfo->attr->distance)
return pinfo->attr->distance;
+ /* get peer origin to calculate appropriate distance */
+ if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
+ peer = bpi_ultimate->peer;
+ }
+
/* Check source address.
* Note: for aggregate route, peer can have unspec af type.
*/
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index f779b34371..d00bdd2571 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -3531,11 +3531,11 @@ route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
|| CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
/* Set next hop preference to global */
- SET_FLAG(path->attr->nh_flag, BGP_ATTR_NH_MP_PREFER_GLOBAL);
+ path->attr->mp_nexthop_prefer_global = true;
SET_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
} else {
- UNSET_FLAG(path->attr->nh_flag, BGP_ATTR_NH_MP_PREFER_GLOBAL);
+ path->attr->mp_nexthop_prefer_global = false;
SET_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
}
@@ -3585,7 +3585,8 @@ route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
path->attr->mp_nexthop_local = *address;
/* Set nexthop length. */
- if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+ if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
+ path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
SET_FLAG(path->attr->rmap_change_flags,
diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c
index fe0c33251e..d8d8549960 100644
--- a/bgpd/bgp_snmp_bgp4v2.c
+++ b/bgpd/bgp_snmp_bgp4v2.c
@@ -704,8 +704,7 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[],
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
return SNMP_INTEGER(2);
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- if (CHECK_FLAG(path->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ if (path->attr->mp_nexthop_prefer_global)
return SNMP_INTEGER(2);
else
return SNMP_INTEGER(4);
@@ -719,8 +718,7 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[],
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
return SNMP_IP6ADDRESS(path->attr->mp_nexthop_global);
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- if (CHECK_FLAG(path->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL))
+ if (path->attr->mp_nexthop_prefer_global)
return SNMP_IP6ADDRESS(
path->attr->mp_nexthop_global);
else
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index afd2107b48..9ca57f08da 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -164,6 +164,7 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
dst->change_local_as = src->change_local_as;
dst->shared_network = src->shared_network;
dst->local_role = src->local_role;
+ dst->as_path_loop_detection = src->as_path_loop_detection;
if (src->soo[afi][safi]) {
ecommunity_free(&dst->soo[afi][safi]);
@@ -360,6 +361,9 @@ static unsigned int updgrp_hash_key_make(const void *p)
key = jhash_1word(peer->max_packet_size, key);
key = jhash_1word(peer->pmax_out[afi][safi], key);
+ if (peer->as_path_loop_detection)
+ key = jhash_2words(peer->as, peer->as_path_loop_detection, key);
+
if (peer->group)
key = jhash_1word(jhash(peer->group->name,
strlen(peer->group->name), SEED1),
@@ -454,12 +458,13 @@ static unsigned int updgrp_hash_key_make(const void *p)
(intmax_t)CHECK_FLAG(peer->flags, PEER_UPDGRP_FLAGS),
(intmax_t)CHECK_FLAG(flags, PEER_UPDGRP_AF_FLAGS));
zlog_debug(
- "%pBP Update Group Hash: addpath: %u UpdGrpCapFlag: %u UpdGrpCapAFFlag: %u route_adv: %u change local as: %u",
+ "%pBP Update Group Hash: addpath: %u UpdGrpCapFlag: %u UpdGrpCapAFFlag: %u route_adv: %u change local as: %u, as_path_loop_detection: %d",
peer, (uint32_t)peer->addpath_type[afi][safi],
CHECK_FLAG(peer->cap, PEER_UPDGRP_CAP_FLAGS),
CHECK_FLAG(peer->af_cap[afi][safi],
PEER_UPDGRP_AF_CAP_FLAGS),
- peer->v_routeadv, peer->change_local_as);
+ peer->v_routeadv, peer->change_local_as,
+ peer->as_path_loop_detection);
zlog_debug(
"%pBP Update Group Hash: max packet size: %u pmax_out: %u Peer Group: %s rmap out: %s",
peer, peer->max_packet_size, peer->pmax_out[afi][safi],
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 8ea9c1996b..5772900ce4 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -78,8 +78,6 @@
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
#endif
-#include "bgpd/bgp_orr.h"
-
FRR_CFG_DEFAULT_BOOL(BGP_IMPORT_CHECK,
{
@@ -819,6 +817,9 @@ struct peer *peer_and_group_lookup_vty(struct vty *vty, const char *peer_str)
if (peer) {
if (peer_dynamic_neighbor(peer)) {
+ zlog_warn(
+ "%pBP: Operation not allowed on a dynamic neighbor",
+ peer);
vty_out(vty,
"%% Operation not allowed on a dynamic neighbor\n");
return NULL;
@@ -830,6 +831,8 @@ struct peer *peer_and_group_lookup_vty(struct vty *vty, const char *peer_str)
if (group)
return group->conf;
+ zlog_warn("Specify remote-as or peer-group commands first before: %s",
+ vty->buf);
vty_out(vty, "%% Specify remote-as or peer-group commands first\n");
return NULL;
@@ -943,9 +946,6 @@ int bgp_vty_return(struct vty *vty, enum bgp_create_error_code ret)
case BGP_ERR_INVALID_INTERNAL_ROLE:
str = "External roles can be set only on eBGP session";
break;
- case BGP_ERR_PEER_ORR_CONFIGURED:
- str = "Deconfigure optimal-route-reflection on this peer first";
- break;
}
if (str) {
vty_out(vty, "%% %s\n", str);
@@ -6249,43 +6249,6 @@ ALIAS_HIDDEN(no_neighbor_route_reflector_client,
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
"Configure a neighbor as Route Reflector client\n")
-/* optimal-route-reflection Root Routers configuration */
-DEFPY (optimal_route_reflection,
- optimal_route_reflection_cmd,
- "[no$no] optimal-route-reflection WORD$orr_group [<A.B.C.D|X:X::X:X>$primary [<A.B.C.D|X:X::X:X>$secondary [<A.B.C.D|X:X::X:X>$tertiary]]]",
- NO_STR
- "Create ORR group and assign root router(s)\n"
- "ORR Group name\n"
- "Primary Root address\n"
- "Primary Root IPv6 address\n"
- "Secondary Root address\n"
- "Secondary Root IPv6 address\n"
- "Tertiary Root address\n"
- "Tertiary Root IPv6 address\n")
-{
- if (!no && !primary) {
- vty_out(vty, "%% Specify Primary Root address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- return bgp_afi_safi_orr_group_set_vty(
- vty, bgp_node_afi(vty), bgp_node_safi(vty), orr_group,
- primary_str, secondary_str, tertiary_str, !!no);
-}
-
-/* neighbor optimal-route-reflection group*/
-DEFPY (neighbor_optimal_route_reflection,
- neighbor_optimal_route_reflection_cmd,
- "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor optimal-route-reflection WORD$orr_group",
- NO_STR
- NEIGHBOR_STR
- NEIGHBOR_ADDR_STR2
- "Apply ORR group configuration to the neighbor\n"
- "ORR group name\n")
-{
- return peer_orr_group_set_vty(vty, neighbor, bgp_node_afi(vty),
- bgp_node_safi(vty), orr_group, !!no);
-}
-
/* neighbor route-server-client. */
DEFUN (neighbor_route_server_client,
neighbor_route_server_client_cmd,
@@ -8803,6 +8766,32 @@ DEFPY(
return CMD_SUCCESS;
}
+DEFPY(neighbor_path_attribute_discard,
+ neighbor_path_attribute_discard_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute discard (1-255)...",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Manipulate path attributes from incoming UPDATE messages\n"
+ "Drop specified attributes from incoming UPDATE messages\n"
+ "Attribute number\n")
+{
+ struct peer *peer;
+ int idx = 0;
+ const char *discard_attrs = NULL;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ if (idx)
+ discard_attrs = argv_concat(argv, argc, idx);
+
+ bgp_path_attribute_discard_vty(vty, peer, discard_attrs);
+
+ return CMD_SUCCESS;
+}
+
static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
struct ecommunity **list, bool is_rt6)
{
@@ -10263,35 +10252,158 @@ DEFUN (show_bgp_views,
return CMD_SUCCESS;
}
-DEFUN (show_bgp_vrfs,
+static inline void calc_peers_cfgd_estbd(struct bgp *bgp, int *peers_cfgd,
+ int *peers_estbd)
+{
+ struct peer *peer;
+ struct listnode *node;
+
+ *peers_cfgd = *peers_estbd = 0;
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+ (*peers_cfgd)++;
+ if (peer_established(peer))
+ (*peers_estbd)++;
+ }
+}
+
+static void print_bgp_vrfs(struct bgp *bgp, struct vty *vty, json_object *json,
+ const char *type)
+{
+ int peers_cfg, peers_estb;
+
+ calc_peers_cfgd_estbd(bgp, &peers_cfg, &peers_estb);
+
+ if (json) {
+ int64_t vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
+ ? -1
+ : (int64_t)bgp->vrf_id;
+ json_object_string_add(json, "type", type);
+ json_object_int_add(json, "vrfId", vrf_id_ui);
+ json_object_string_addf(json, "routerId", "%pI4",
+ &bgp->router_id);
+ json_object_int_add(json, "numConfiguredPeers", peers_cfg);
+ json_object_int_add(json, "numEstablishedPeers", peers_estb);
+ json_object_int_add(json, "l3vni", bgp->l3vni);
+ json_object_string_addf(json, "rmac", "%pEA", &bgp->rmac);
+ json_object_string_add(
+ json, "interface",
+ ifindex2ifname(bgp->l3vni_svi_ifindex, bgp->vrf_id));
+ }
+}
+
+static int show_bgp_vrfs_detail_common(struct vty *vty, struct bgp *bgp,
+ json_object *json, const char *name,
+ const char *type, bool use_vrf)
+{
+ int peers_cfg, peers_estb;
+
+ calc_peers_cfgd_estbd(bgp, &peers_cfg, &peers_estb);
+
+ if (use_vrf) {
+ if (json) {
+ print_bgp_vrfs(bgp, vty, json, type);
+ } else {
+ vty_out(vty, "BGP instance %s VRF id %d\n",
+ bgp->name_pretty,
+ bgp->vrf_id == VRF_UNKNOWN ? -1
+ : (int)bgp->vrf_id);
+ vty_out(vty, "Router Id %pI4\n", &bgp->router_id);
+ vty_out(vty,
+ "Num Configured Peers %d, Established %d\n",
+ peers_cfg, peers_estb);
+ if (bgp->l3vni) {
+ vty_out(vty,
+ "L3VNI %u, L3VNI-SVI %s, Router MAC %pEA\n",
+ bgp->l3vni,
+ ifindex2ifname(bgp->l3vni_svi_ifindex,
+ bgp->vrf_id),
+ &bgp->rmac);
+ }
+ }
+ } else {
+ if (json) {
+ print_bgp_vrfs(bgp, vty, json, type);
+ } else {
+ vty_out(vty, "%4s %-5d %-16pI4 %-9u %-10u %-37s\n",
+ type,
+ bgp->vrf_id == VRF_UNKNOWN ? -1
+ : (int)bgp->vrf_id,
+ &bgp->router_id, peers_cfg, peers_estb, name);
+ vty_out(vty, "%11s %-16u %-21pEA %-20s\n", " ",
+ bgp->l3vni, &bgp->rmac,
+ ifindex2ifname(bgp->l3vni_svi_ifindex,
+ bgp->vrf_id));
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_bgp_vrfs,
show_bgp_vrfs_cmd,
- "show [ip] bgp vrfs [json]",
+ "show [ip] bgp vrfs [<VRFNAME$vrf_name>] [json]",
SHOW_STR
IP_STR
BGP_STR
"Show BGP VRFs\n"
+ "Specific VRF name\n"
JSON_STR)
{
- char buf[ETHER_ADDR_STRLEN];
struct list *inst = bm->bgp;
struct listnode *node;
struct bgp *bgp;
bool uj = use_json(argc, argv);
json_object *json = NULL;
json_object *json_vrfs = NULL;
+ json_object *json_vrf = NULL;
int count = 0;
+ const char *name = vrf_name;
+ const char *type;
- if (uj) {
+ if (uj)
json = json_object_new_object();
- json_vrfs = json_object_new_object();
+
+ if (name) {
+ if (strmatch(name, VRF_DEFAULT_NAME)) {
+ bgp = bgp_get_default();
+ type = "DFLT";
+ } else {
+ bgp = bgp_lookup_by_name(name);
+ type = "VRF";
+ }
+ if (!bgp) {
+ if (uj)
+ vty_json(vty, json);
+ else
+ vty_out(vty,
+ "%% Specified BGP instance not found\n");
+
+ return CMD_WARNING;
+ }
+ }
+
+ if (vrf_name) {
+ if (uj)
+ json_vrf = json_object_new_object();
+
+ show_bgp_vrfs_detail_common(vty, bgp, json_vrf, name, type,
+ true);
+
+ if (uj) {
+ json_object_object_add(json, name, json_vrf);
+ vty_json(vty, json);
+ }
+
+ return CMD_SUCCESS;
}
+ if (uj)
+ json_vrfs = json_object_new_object();
+
for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) {
- const char *name, *type;
- struct peer *peer;
- struct listnode *node2, *nnode2;
- int peers_cfg, peers_estb;
- json_object *json_vrf = NULL;
+ const char *name;
/* Skip Views. */
if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
@@ -10306,20 +10418,9 @@ DEFUN (show_bgp_vrfs,
vty_out(vty, "%11s %-16s %-21s %-6s\n", " ",
"L3-VNI", "RouterMAC", "Interface");
}
-
- peers_cfg = peers_estb = 0;
if (uj)
json_vrf = json_object_new_object();
-
- for (ALL_LIST_ELEMENTS(bgp->peer, node2, nnode2, peer)) {
- if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
- continue;
- peers_cfg++;
- if (peer_established(peer))
- peers_estb++;
- }
-
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
name = VRF_DEFAULT_NAME;
type = "DFLT";
@@ -10328,49 +10429,16 @@ DEFUN (show_bgp_vrfs,
type = "VRF";
}
+ show_bgp_vrfs_detail_common(vty, bgp, json_vrf, name, type,
+ false);
- if (uj) {
- int64_t vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
- ? -1
- : (int64_t)bgp->vrf_id;
- char buf[BUFSIZ] = {0};
-
- json_object_string_add(json_vrf, "type", type);
- json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
- json_object_string_addf(json_vrf, "routerId", "%pI4",
- &bgp->router_id);
- json_object_int_add(json_vrf, "numConfiguredPeers",
- peers_cfg);
- json_object_int_add(json_vrf, "numEstablishedPeers",
- peers_estb);
-
- json_object_int_add(json_vrf, "l3vni", bgp->l3vni);
- json_object_string_add(
- json_vrf, "rmac",
- prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
- json_object_string_add(json_vrf, "interface",
- ifindex2ifname(bgp->l3vni_svi_ifindex,
- bgp->vrf_id));
+ if (uj)
json_object_object_add(json_vrfs, name, json_vrf);
- } else {
- vty_out(vty, "%4s %-5d %-16pI4 %-9u %-10u %-37s\n",
- type,
- bgp->vrf_id == VRF_UNKNOWN ? -1
- : (int)bgp->vrf_id,
- &bgp->router_id, peers_cfg, peers_estb, name);
- vty_out(vty,"%11s %-16u %-21s %-20s\n", " ",
- bgp->l3vni,
- prefix_mac2str(&bgp->rmac, buf, sizeof(buf)),
- ifindex2ifname(bgp->l3vni_svi_ifindex,
- bgp->vrf_id));
- }
}
if (uj) {
json_object_object_add(json, "vrfs", json_vrfs);
-
json_object_int_add(json, "totalVrfs", count);
-
vty_json(vty, json);
} else {
if (count)
@@ -12632,11 +12700,6 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
if (CHECK_FLAG(p->af_flags[afi][safi],
PEER_FLAG_RSERVER_CLIENT))
vty_out(vty, " Route-Server Client\n");
-
- if (peer_af_flag_check(p, afi, safi, PEER_FLAG_ORR_GROUP))
- vty_out(vty, " ORR group (configured) : %s\n",
- p->orr_group_name[afi][safi]);
-
if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
vty_out(vty,
" Inbound soft reconfiguration allowed\n");
@@ -17360,6 +17423,15 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " neighbor %s sender-as-path-loop-detection\n",
addr);
+ /* path-attribute discard */
+ char discard_attrs_str[BUFSIZ] = {0};
+ bool discard_attrs = bgp_path_attribute_discard(
+ peer, discard_attrs_str, sizeof(discard_attrs_str));
+
+ if (discard_attrs)
+ vty_out(vty, " neighbor %s path-attribute discard %s\n", addr,
+ discard_attrs_str);
+
if (!CHECK_FLAG(peer->peer_gr_new_status_flag,
PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT)) {
@@ -17661,10 +17733,6 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
: "");
}
}
-
- if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP))
- vty_out(vty, " neighbor %s optimal-route-reflection %s\n",
- addr, peer->orr_group_name[afi][safi]);
}
static void bgp_vpn_config_write(struct vty *vty, struct bgp *bgp, afi_t afi,
@@ -17771,9 +17839,6 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
}
}
- /* Optimal Route Reflection */
- bgp_config_write_orr(vty, bgp, afi, safi);
-
vty_endframe(vty, " exit-address-family\n");
}
@@ -17817,9 +17882,12 @@ int bgp_config_write(struct vty *vty)
vty_out(vty, "bgp session-dscp %u\n", bm->tcp_dscp >> 2);
/* BGP InQ limit */
- if (bm->inq_limit != BM_DEFAULT_INQ_LIMIT)
+ if (bm->inq_limit != BM_DEFAULT_Q_LIMIT)
vty_out(vty, "bgp input-queue-limit %u\n", bm->inq_limit);
+ if (bm->outq_limit != BM_DEFAULT_Q_LIMIT)
+ vty_out(vty, "bgp output-queue-limit %u\n", bm->outq_limit);
+
/* BGP configuration. */
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
@@ -18554,11 +18622,37 @@ DEFPY (no_bgp_inq_limit,
"Set the BGP Input Queue limit for all peers when message parsing\n"
"Input-Queue limit\n")
{
- bm->inq_limit = BM_DEFAULT_INQ_LIMIT;
+ bm->inq_limit = BM_DEFAULT_Q_LIMIT;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (bgp_outq_limit,
+ bgp_outq_limit_cmd,
+ "bgp output-queue-limit (1-4294967295)$limit",
+ BGP_STR
+ "Set the BGP Output Queue limit for all peers when message parsing\n"
+ "Output-Queue limit\n")
+{
+ bm->outq_limit = limit;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (no_bgp_outq_limit,
+ no_bgp_outq_limit_cmd,
+ "no bgp output-queue-limit [(1-4294967295)$limit]",
+ NO_STR
+ BGP_STR
+ "Set the BGP Output Queue limit for all peers when message parsing\n"
+ "Output-Queue limit\n")
+{
+ bm->outq_limit = BM_DEFAULT_Q_LIMIT;
return CMD_SUCCESS;
}
+
/* Initialization of BGP interface. */
static void bgp_vty_if_init(void)
{
@@ -18611,6 +18705,8 @@ void bgp_vty_init(void)
/* "global bgp inq-limit command */
install_element(CONFIG_NODE, &bgp_inq_limit_cmd);
install_element(CONFIG_NODE, &no_bgp_inq_limit_cmd);
+ install_element(CONFIG_NODE, &bgp_outq_limit_cmd);
+ install_element(CONFIG_NODE, &no_bgp_outq_limit_cmd);
/* "bgp local-mac" hidden commands. */
install_element(CONFIG_NODE, &bgp_local_mac_cmd);
@@ -18813,10 +18909,6 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_graceful_restart_rib_stale_time_cmd);
install_element(BGP_NODE, &no_bgp_graceful_restart_rib_stale_time_cmd);
- /* "bgp inq-limit command */
- install_element(BGP_NODE, &bgp_inq_limit_cmd);
- install_element(BGP_NODE, &no_bgp_inq_limit_cmd);
-
/* "bgp graceful-shutdown" commands */
install_element(BGP_NODE, &bgp_graceful_shutdown_cmd);
install_element(BGP_NODE, &no_bgp_graceful_shutdown_cmd);
@@ -19339,34 +19431,6 @@ void bgp_vty_init(void)
install_element(BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd);
- /* "optimal-route-reflection" commands */
- install_element(BGP_IPV4_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV4M_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV4L_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV6_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV6M_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV6L_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_VPNV4_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_VPNV6_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV4_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV6_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_EVPN_NODE, &optimal_route_reflection_cmd);
-
- /* "neighbor optimal-route-reflection" commands */
- install_element(BGP_IPV4_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV4M_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV4L_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV6_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV6M_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV6L_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_VPNV4_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_VPNV6_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV4_NODE,
- &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV6_NODE,
- &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_EVPN_NODE, &neighbor_optimal_route_reflection_cmd);
-
/* "neighbor route-server" commands.*/
install_element(BGP_NODE, &neighbor_route_server_client_hidden_cmd);
install_element(BGP_NODE, &no_neighbor_route_server_client_hidden_cmd);
@@ -19475,6 +19539,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &neighbor_aspath_loop_detection_cmd);
install_element(BGP_NODE, &no_neighbor_aspath_loop_detection_cmd);
+ /* "neighbor path-attribute discard" commands. */
+ install_element(BGP_NODE, &neighbor_path_attribute_discard_cmd);
+
/* "neighbor passive" commands. */
install_element(BGP_NODE, &neighbor_passive_cmd);
install_element(BGP_NODE, &no_neighbor_passive_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index f6e7b444c6..95e80ba1bb 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -67,13 +67,10 @@
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_community.h"
#include "bgpd/bgp_lcommunity.h"
-#include "bgpd/bgp_orr.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
-static int bgp_opaque_msg_handler(ZAPI_CALLBACK_ARGS);
-
/* hook to indicate vrf status change for SNMP */
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
(bgp, ifp));
@@ -234,7 +231,6 @@ static int bgp_ifp_up(struct interface *ifp)
struct connected *c;
struct nbr_connected *nc;
struct listnode *node, *nnode;
- struct bgp *bgp_default = bgp_get_default();
struct bgp *bgp;
bgp = ifp->vrf->info;
@@ -257,14 +253,6 @@ static int bgp_ifp_up(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_up(ifp);
- if (bgp_default && if_is_loopback(ifp)) {
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
- vpn_leak_postchange_all();
- }
-
return 0;
}
@@ -273,7 +261,6 @@ static int bgp_ifp_down(struct interface *ifp)
struct connected *c;
struct nbr_connected *nc;
struct listnode *node, *nnode;
- struct bgp *bgp_default = bgp_get_default();
struct bgp *bgp;
struct peer *peer;
@@ -313,14 +300,6 @@ static int bgp_ifp_down(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_down(ifp);
- if (bgp_default && if_is_loopback(ifp)) {
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
- vpn_leak_postchange_all();
- }
-
return 0;
}
@@ -408,16 +387,10 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
{
struct listnode *node, *nnode;
- struct bgp_path_info *pi;
- struct bgp_table *table;
- struct bgp_dest *dest;
struct connected *ifc;
struct peer *peer;
- struct bgp *bgp, *from_bgp, *bgp_default;
- struct listnode *next;
+ struct bgp *bgp;
struct prefix *addr;
- afi_t afi;
- safi_t safi;
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -445,6 +418,9 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
* we do not want the peering to bounce.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ afi_t afi;
+ safi_t safi;
+
if (addr->family == AF_INET)
continue;
@@ -460,44 +436,6 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
}
}
- bgp_default = bgp_get_default();
- afi = family2afi(addr->family);
- safi = SAFI_UNICAST;
-
- /* When the last IPv4 address was deleted, Linux removes all routes
- * using the interface so that bgpd needs to re-send them.
- */
- if (bgp_default && afi == AFI_IP) {
- for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, from_bgp)) {
- table = from_bgp->rib[afi][safi];
- if (!table)
- continue;
-
- for (dest = bgp_table_top(table); dest;
- dest = bgp_route_next(dest)) {
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
- if (pi->type == ZEBRA_ROUTE_BGP &&
- pi->attr &&
- pi->attr->nh_ifindex ==
- ifc->ifp->ifindex) {
- SET_FLAG(pi->attr->nh_flag,
- BGP_ATTR_NH_REFRESH);
- }
- }
- }
-
- if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
- continue;
-
- vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
- bgp_default, from_bgp);
-
- vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
- bgp_default, from_bgp);
- }
- }
-
connected_free(&ifc);
return 0;
@@ -1066,8 +1004,7 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex)
|| path->attr->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
/* Check if route-map is set to prefer global over link-local */
- if (CHECK_FLAG(path->attr->nh_flag,
- BGP_ATTR_NH_MP_PREFER_GLOBAL)) {
+ if (path->attr->mp_nexthop_prefer_global) {
nexthop = &path->attr->mp_nexthop_global;
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
*ifindex = path->attr->nh_ifindex;
@@ -1367,7 +1304,6 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
uint8_t distance;
struct peer *peer;
struct bgp_path_info *mpinfo;
- struct bgp_path_info *bpi_ultimate;
struct bgp *bgp_orig;
uint32_t metric;
struct attr local_attr;
@@ -1416,9 +1352,13 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
peer = info->peer;
- if (info->type == ZEBRA_ROUTE_BGP) {
- bpi_ultimate = bgp_get_imported_bpi_ultimate(info);
- peer = bpi_ultimate->peer;
+ if (info->type == ZEBRA_ROUTE_BGP
+ && info->sub_type == BGP_ROUTE_IMPORTED) {
+
+ /* Obtain peer from parent */
+ if (info->extra && info->extra->parent)
+ peer = ((struct bgp_path_info *)(info->extra->parent))
+ ->peer;
}
tag = info->attr->tag;
@@ -3250,7 +3190,6 @@ extern struct zebra_privs_t bgpd_privs;
static int bgp_ifp_create(struct interface *ifp)
{
- struct bgp *bgp_default = bgp_get_default();
struct bgp *bgp;
if (BGP_DEBUG(zebra, ZEBRA))
@@ -3265,17 +3204,6 @@ static int bgp_ifp_create(struct interface *ifp)
bgp_update_interface_nbrs(bgp, ifp, ifp);
hook_call(bgp_vrf_status_changed, bgp, ifp);
-
- if (bgp_default &&
- (if_is_loopback_exact(ifp) ||
- (if_is_vrf(ifp) && ifp->vrf->vrf_id != VRF_DEFAULT))) {
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
- vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
- vpn_leak_postchange_all();
- }
-
return 0;
}
@@ -3486,7 +3414,6 @@ static zclient_handler *const bgp_handlers[] = {
[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
bgp_zebra_process_srv6_locator_chunk,
- [ZEBRA_OPAQUE_MESSAGE] = bgp_opaque_msg_handler,
};
static int bgp_if_new_hook(struct interface *ifp)
@@ -3939,34 +3866,3 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)
{
return srv6_manager_release_locator_chunk(zclient, name);
}
-
-/*
- * ORR messages between processes
- */
-static int bgp_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
-{
- struct stream *s;
- struct zapi_opaque_msg info;
- struct orr_igp_metric_info table;
- int ret = 0;
-
- s = zclient->ibuf;
-
- if (zclient_opaque_decode(s, &info) != 0) {
- bgp_orr_debug("%s: opaque decode failed", __func__);
- return -1;
- }
-
- switch (info.type) {
- case ORR_IGP_METRIC_UPDATE:
- STREAM_GET(&table, s, sizeof(table));
- ret = bgg_orr_message_process(BGP_ORR_IMSG_IGP_METRIC_UPDATE,
- (void *)&table);
- break;
- default:
- break;
- }
-
-stream_failure:
- return ret;
-}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 9b4aa38d7a..1fd394a849 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -92,7 +92,6 @@
#include "bgpd/bgp_evpn_private.h"
#include "bgpd/bgp_evpn_mh.h"
#include "bgpd/bgp_mac.h"
-#include "bgpd/bgp_orr.h"
#include "bgp_trace.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
@@ -1896,8 +1895,6 @@ bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
/* Change peer's AS number. */
void peer_as_change(struct peer *peer, as_t as, int as_specified)
{
- afi_t afi;
- safi_t safi;
enum bgp_peer_sort origtype, newtype;
/* Stop peer. */
@@ -1936,11 +1933,6 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
/* reflector-client reset */
if (newtype != BGP_PEER_IBGP) {
-
- FOREACH_AFI_SAFI (afi, safi)
- UNSET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ORR_GROUP);
-
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST],
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST],
@@ -3576,7 +3568,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("%s: Registering BGP instance %s to zebra",
- __func__, name);
+ __func__, bgp->name_pretty);
bgp_zebra_instance_register(bgp);
}
@@ -3932,8 +3924,6 @@ void bgp_free(struct bgp *bgp)
ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
}
- bgp_orr_cleanup(bgp);
-
XFREE(MTYPE_BGP, bgp->name);
XFREE(MTYPE_BGP, bgp->name_pretty);
XFREE(MTYPE_BGP, bgp->snmp_stats);
@@ -4203,6 +4193,25 @@ static void peer_drop_dynamic_neighbor(struct peer *peer)
peer->group->name, dncount);
}
+bool bgp_path_attribute_discard(struct peer *peer, char *buf, size_t size)
+{
+ if (!buf)
+ return false;
+
+ buf[0] = '\0';
+
+ for (unsigned int i = 0; i < BGP_ATTR_MAX; i++) {
+ if (peer->discard_attrs[i])
+ snprintf(buf + strlen(buf), size - strlen(buf), "%s%d",
+ (strlen(buf) > 0) ? " " : "", i);
+ }
+
+ if (strlen(buf) > 0)
+ return true;
+
+ return false;
+}
+
/* If peer is configured at least one address family return 1. */
bool peer_active(struct peer *peer)
{
@@ -4719,11 +4728,6 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
return BGP_ERR_NOT_INTERNAL_PEER;
- /* Do not remove reflector client when ORR is configured on this peer */
- if (flag & PEER_FLAG_REFLECTOR_CLIENT && !set &&
- peer_orr_rrclient_check(peer, afi, safi))
- return BGP_ERR_PEER_ORR_CONFIGURED;
-
/* Special check for remove-private-AS. */
if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
return BGP_ERR_REMOVE_PRIVATE_AS;
@@ -7940,7 +7944,8 @@ void bgp_master_init(struct thread_master *master, const int buffer_size,
bm->socket_buffer = buffer_size;
bm->wait_for_fib = false;
bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
- bm->inq_limit = BM_DEFAULT_INQ_LIMIT;
+ bm->inq_limit = BM_DEFAULT_Q_LIMIT;
+ bm->outq_limit = BM_DEFAULT_Q_LIMIT;
bgp_mac_init();
/* init the rd id space.
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index a75bfdf746..4c4c81f997 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -47,7 +47,6 @@
#include "bgp_io.h"
#include "lib/bfd.h"
-#include "lib/orr_msg.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
#define BGP_PEER_MAX_HASH_SIZE 16384
@@ -177,8 +176,9 @@ struct bgp_master {
/* DSCP value for TCP sessions */
uint8_t tcp_dscp;
-#define BM_DEFAULT_INQ_LIMIT 10000
+#define BM_DEFAULT_Q_LIMIT 10000
uint32_t inq_limit;
+ uint32_t outq_limit;
QOBJ_FIELDS;
};
@@ -201,40 +201,6 @@ struct bgp_redist {
struct bgp_rmap rmap;
};
-struct bgp_orr_igp_metric {
- struct prefix prefix;
- uint32_t igp_metric;
-};
-
-struct bgp_orr_group {
- /* Name of this ORR group */
- char *name;
-
- /* Address Family Identifiers */
- afi_t afi;
- safi_t safi;
-
- /* Pointer to BGP */
- struct bgp *bgp;
-
- /* Root Routers of the group */
- struct peer *primary;
- struct peer *secondary;
- struct peer *tertiary;
-
- /* Active Root Router of the group */
- struct peer *active;
-
- /* RR clients belong to this group */
- struct list *rr_client_list;
-
- /* IGP metric data from active root */
- struct list *igp_metric_info;
-
- /* Route table calculated from active root for this group */
- struct bgp_table *route_table;
-};
-
enum vpn_policy_direction {
BGP_VPN_POLICY_DIR_FROMVPN = 0,
BGP_VPN_POLICY_DIR_TOVPN = 1,
@@ -831,10 +797,6 @@ struct bgp {
bool allow_martian;
- /* BGP optimal route reflection group and Root Router configuration */
- uint32_t orr_group_count;
- struct list *orr_group[AFI_MAX][SAFI_MAX];
-
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp);
@@ -1480,11 +1442,7 @@ struct peer {
#define PEER_FLAG_MAX_PREFIX_FORCE (1ULL << 28)
#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 29)
#define PEER_FLAG_SOO (1ULL << 30)
-#define PEER_FLAG_ORR_GROUP (1ULL << 31) /* Optimal-Route-Reflection */
-#define PEER_FLAG_ACCEPT_OWN (1ULL << 32)
-
- /* BGP Optimal Route Reflection Group name */
- char *orr_group_name[AFI_MAX][SAFI_MAX];
+#define PEER_FLAG_ACCEPT_OWN (1ULL << 31)
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
@@ -1806,6 +1764,10 @@ struct peer {
bool shut_during_cfg;
+#define BGP_ATTR_MAX 255
+ /* Path attributes discard */
+ bool discard_attrs[BGP_ATTR_MAX];
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(peer);
@@ -1887,7 +1849,6 @@ struct bgp_nlri {
#define BGP_MSG_ROUTE_REFRESH_OLD 128
/* BGP open optional parameter. */
-#define BGP_OPEN_OPT_AUTH 1
#define BGP_OPEN_OPT_CAP 2
/* BGP4 attribute type codes. */
@@ -1906,7 +1867,6 @@ struct bgp_nlri {
#define BGP_ATTR_EXT_COMMUNITIES 16
#define BGP_ATTR_AS4_PATH 17
#define BGP_ATTR_AS4_AGGREGATOR 18
-#define BGP_ATTR_AS_PATHLIMIT 21
#define BGP_ATTR_PMSI_TUNNEL 22
#define BGP_ATTR_ENCAP 23
#define BGP_ATTR_IPV6_EXT_COMMUNITIES 25
@@ -1953,7 +1913,6 @@ struct bgp_nlri {
#define BGP_NOTIFY_OPEN_BAD_PEER_AS 2
#define BGP_NOTIFY_OPEN_BAD_BGP_IDENT 3
#define BGP_NOTIFY_OPEN_UNSUP_PARAM 4
-#define BGP_NOTIFY_OPEN_AUTH_FAILURE 5
#define BGP_NOTIFY_OPEN_UNACEP_HOLDTIME 6
#define BGP_NOTIFY_OPEN_UNSUP_CAPBL 7
#define BGP_NOTIFY_OPEN_ROLE_MISMATCH 11
@@ -1965,7 +1924,6 @@ struct bgp_nlri {
#define BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR 4
#define BGP_NOTIFY_UPDATE_ATTR_LENG_ERR 5
#define BGP_NOTIFY_UPDATE_INVAL_ORIGIN 6
-#define BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP 7
#define BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP 8
#define BGP_NOTIFY_UPDATE_OPT_ATTR_ERR 9
#define BGP_NOTIFY_UPDATE_INVAL_NETWORK 10
@@ -2103,10 +2061,7 @@ enum bgp_create_error_code {
/*BGP Open Policy ERRORS */
BGP_ERR_INVALID_ROLE_NAME = -35,
- BGP_ERR_INVALID_INTERNAL_ROLE = -36,
-
- /* BGP ORR ERRORS */
- BGP_ERR_PEER_ORR_CONFIGURED = -37,
+ BGP_ERR_INVALID_INTERNAL_ROLE = -36
};
/*
@@ -2158,7 +2113,6 @@ extern struct peer_group *peer_group_lookup_dynamic_neighbor(struct bgp *,
extern struct peer *peer_lookup_dynamic_neighbor(struct bgp *,
union sockunion *);
-extern bool peer_orr_rrclient_check(struct peer *peer, afi_t afi, safi_t safi);
/*
* Peers are incredibly easy to memory leak
* due to the various ways that they are actually used
@@ -2411,12 +2365,6 @@ extern void bgp_shutdown_disable(struct bgp *bgp);
extern void bgp_close(void);
extern void bgp_free(struct bgp *);
void bgp_gr_apply_running_config(void);
-extern int bgp_afi_safi_orr_group_set(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name, struct peer *primary,
- struct peer *secondary,
- struct peer *tertiary);
-extern int bgp_afi_safi_orr_group_unset(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name);
/* BGP GR */
int bgp_global_gr_init(struct bgp *bgp);
@@ -2670,6 +2618,8 @@ extern void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
safi_t safi);
extern void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
int outbound);
+extern bool bgp_path_attribute_discard(struct peer *peer, char *buf,
+ size_t size);
#ifdef _FRR_ATTRIBUTE_PRINTFRR
/* clang-format off */
#pragma FRR printfrr_ext "%pBP" (struct peer *)
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index c1f5a61438..c2dd207a49 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -76,7 +76,6 @@ bgpd_libbgp_a_SOURCES = \
bgpd/bgp_vty.c \
bgpd/bgp_zebra.c \
bgpd/bgpd.c \
- bgpd/bgp_orr.c \
bgpd/bgp_trace.c \
# end
@@ -160,7 +159,6 @@ noinst_HEADERS += \
bgpd/bgp_vty.h \
bgpd/bgp_zebra.h \
bgpd/bgpd.h \
- bgpd/bgp_orr.h \
bgpd/bgp_trace.h \
\
bgpd/rfapi/bgp_rfapi_cfg.h \
diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am
index 9cf14a1966..b4c752a473 100644
--- a/doc/developer/subdir.am
+++ b/doc/developer/subdir.am
@@ -71,6 +71,7 @@ EXTRA_DIST += \
doc/developer/draft-zebra-00.ms \
doc/developer/ldpd-basic-test-setup.md \
doc/developer/release-announcement-template.md \
+ doc/developer/_static/overrides.css \
# end
DEVBUILD = doc/developer/_build
diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst
index 0eb1064519..1a42996771 100644
--- a/doc/user/bfd.rst
+++ b/doc/user/bfd.rst
@@ -353,6 +353,54 @@ The following commands are available inside the interface configuration node.
that interface.
+.. _bfd-static-peer-config:
+
+BFD Static Route Monitoring Configuration
+-----------------------------------------
+
+A monitored static route conditions the installation to the RIB on the
+BFD session running state: when BFD session is up the route is installed
+to RIB, but when the BFD session is down it is removed from the RIB.
+
+The following commands are available inside the configuration node:
+
+.. clicmd:: ip route A.B.C.D/M A.B.C.D bfd [{multi-hop|source A.B.C.D|profile BFDPROF}]
+
+ Configure a static route for ``A.B.C.D/M`` using gateway ``A.B.C.D`` and use
+ the gateway address as BFD peer destination address.
+
+.. clicmd:: ipv6 route X:X::X:X/M [from X:X::X:X/M] X:X::X:X bfd [{multi-hop|source X:X::X:X|profile BFDPROF}]
+
+ Configure a static route for ``X:X::X:X/M`` using gateway
+ ``X:X::X:X`` and use the gateway address as BFD peer destination
+ address.
+
+The static routes when uninstalled will no longer show up in the output of
+the command ``show ip route`` or ``show ipv6 route``, instead we must use the
+BFD static route show command to see these monitored route status.
+
+.. clicmd:: show bfd static route [json]
+
+ Show all monitored static routes and their status.
+
+ Example output:
+
+ ::
+
+ Showing BFD monitored static routes:
+
+ Route groups:
+ rtg1 peer 172.16.0.1 (status: uninstalled):
+ 2001:db8::100/128
+
+ Next hops:
+ VRF default IPv4 Unicast:
+ 192.168.100.0/24 peer 172.16.0.1 (status: uninstalled)
+
+ VRF default IPv4 Multicast:
+
+ VRF default IPv6 Unicast:
+
.. _bfd-configuration:
Configuration
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 0c51ce2d21..9c69848258 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1704,6 +1704,13 @@ Configuring Peers
Default: disabled.
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> path-attribute discard (1-255)...
+
+ Drops specified path attributes from BGP UPDATE messages from the specified neighbor.
+
+ If you do not want specific attributes, you can drop them using this command, and
+ let the BGP proceed by ignoring those attributes.
+
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> graceful-shutdown
Mark all routes from this neighbor as less preferred by setting ``graceful-shutdown``
@@ -3559,319 +3566,6 @@ When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2
Total number of prefixes 3
Router2#
-.. _bgp-optimal-route-reflection:
-
-BGP Optimal Route Reflection
-----------------------------
-BGP Route Reflectors (RRs) are used to improve network scalability by reducing
-or eliminating the need for a full-mesh of IBGP sessions.
-
-When a BGP RR receives multiple paths for the same IP prefix, it typically
-selects a single best path to send for all its clients.
-If the RR has multiple nearly-equal best paths and the tie-break is determined
-by the next-hop cost, the RR advertises the path based on its view of next-hop
-costs, which leads to a non-optimal routing.
-The advertised route may differ from the path that a client would select
-if it had the visibility of the same set of candidate paths and used
-its own view of next-hop costs.
-
-Non-optimal advertisements by the RR can be a problem in hot-potato routing.
-Hot-potato routing aims to hand off traffic to the next AS using the closest
-possible exit point from the local AS.
-In this context, the closest exit point implies minimum IGP cost to
-reach the BGP next-hop.
-
-The BGP Optimal Route Reflection allows the RR to choose and send a different
-best path to a different or a set of RR clients.
-
-A link-state protocol is required. It can be OSPF or IS-IS.
-Current implementation of BGP ORR is based on the IGP cost to the BGP next hop,
-and not based on some configured policy.
-
-RR runs Shortest Path First (SPF) calculation with the selected
-router as the root of the tree and calculates the cost to every other router.
-
-This special SPF calculation with another router as the root, is referred to as
-a Reverse SPF (rSPF). This can only be done if the RR learns all the BGP paths
-from all the BGP border routers.
-
-There could be as many rSPFs run as there are RR clients.
-This will increase the CPU load somewhat on the RR.
-
-Current implementation allows up to three root nodes for the rSPF calculation.
-There is no need to configure each RR client as a root and run rSPF.
-Current implementation allows to configure three, the primary, the secondary,
-and the tertiary root, per set of RR clients, for redundancy purposes.
-For the BGP ORR feature to apply to any RR client, that RR client must be
-configured to be part of an ORR policy group.
-
-The BGP ORR feature is enabled per address family.
-
-The minimal configuration needed:
-
-1. ORR needs to be enabled for specific groups of BGP neighbors.
-2. For each group of BGP neighbors, at least one root needs to be configured.
- Optionally, a secondary and tertiary root can be configured.
-3. For OSPF, the root routers(RR clients) need additional configuration
- to make BGP ORR work.
- i.e. The MPLS TE configuration on the root router needs to have the minimal
- configuration for MPLS TE enabled so that OSPF advertises the MPLS TE
- router ID in an opaque-area LSA (type 10).
- Once the RR has an opaque-area LSA with the MPLS TE router-ID matching the
- configured root router address, rSPF can run and BGP on the RR can
- advertise the optimal route.
-
-.. clicmd:: neighbor A.B.C.D optimal-route-reflection NAME
-
- This command allows the neighbor to be part of the ORR group.
-
-.. clicmd:: optimal-route-reflection orr-1 A.B.C.D [A.B.C.D] [A.B.C.D]
-
- This command creates an ORR group with a mandatory primary root
- and optional secondary and/or tertiary roots.
- When primary is reachable it will be the active root.
- when primary goes down, secondary followed by tertiary takes over
- the active root's role.
- Always rSPF calculation runs active root as the root.
- Which means the RR advertises the path based on active root's
- view of next-hop costs.
-
-Sample Configuration
-^^^^^^^^^^^^^^^^^^^^
-
-Sample configuration on Route Reflector
-
-.. code-block:: frr
-
- !
- debug ospf 8 orr
- debug bgp optimal-route-reflection
- !
- interface enp0s8
- ip address 10.10.68.8/24
- ip ospf 8 area 0
- exit
- !
- interface lo
- ip address 10.100.1.8/32
- ip ospf 8 area 0
- exit
- !
- router bgp 1
- neighbor 10.100.1.1 remote-as 1
- neighbor 10.100.1.1 update-source lo
- neighbor 10.100.1.2 remote-as 1
- neighbor 10.100.1.2 update-source lo
- neighbor 10.100.1.3 remote-as 1
- neighbor 10.100.1.3 update-source lo
- neighbor 10.100.1.4 remote-as 1
- neighbor 10.100.1.4 update-source lo
- !
- address-family ipv4 unicast
- neighbor 10.100.1.1 route-reflector-client
- neighbor 10.100.1.1 optimal-route-reflection orr-1
- neighbor 10.100.1.2 route-reflector-client
- neighbor 10.100.1.2 optimal-route-reflection orr-1
- neighbor 10.100.1.3 route-reflector-client
- neighbor 10.100.1.3 optimal-route-reflection orr-1
- neighbor 10.100.1.4 route-reflector-client
- neighbor 10.100.1.4 optimal-route-reflection orr-1
- optimal-route-reflection orr-1 10.100.1.4 10.100.1.3 10.100.1.1
- exit-address-family
- exit
- !
- router ospf 8
- ospf router-id 8.8.8.8
- area 0 authentication
- capability opaque
- exit
- !
- end
-
-Sample configuration on RR clients
-
-.. code-block:: frr
-
- interface enp0s8
- ip address 10.10.34.4/24
- ip ospf 4 area 0
- link-params
- enable
- exit-link-params
- exit
- !
- interface enp0s9
- ip address 10.10.74.4/24
- ip ospf 4 area 0
- link-params
- enable
- exit-link-params
- exit
- !
- interface lo
- ip address 10.100.1.4/32
- ip ospf 4 area 0
- exit
- !
- router bgp 1
- neighbor 10.100.1.8 remote-as 1
- neighbor 10.100.1.8 update-source lo
- !
- address-family ipv4 unicast
- neighbor 10.100.1.8 soft-reconfiguration inbound
- exit-address-family
- exit
- !
- router ospf 4
- ospf router-id 4.4.4.4
- area 0 authentication
- capability opaque
- mpls-te on
- mpls-te router-address 10.100.1.4
- mpls-te inter-as area 0.0.0.0
- mpls-te export
- exit
- !
- end
-
-Sample Output
-^^^^^^^^^^^^^
-
-When Optimal Route Reflection is not enabled on RR, it sends 10.100.1.1 as the best path to its clients.
-
-.. code-block:: frr
-
- Router-RR# show ip bgp neighbors 10.100.1.4
-
- !--- Output suppressed.
-
- For address family: IPv4 Unicast
- Update group 2, subgroup 2
- Packet Queue length 0
- Route-Reflector Client
- Community attribute sent to this neighbor(all)
- 0 accepted prefixes
-
- !--- Output suppressed.
-
- Router-RR#
- Router-RR# show ip bgp
- BGP table version is 3, local router ID is 10.100.1.8, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- * i203.0.113.0/24 10.100.1.2 0 100 0 i
- *>i 10.100.1.1 0 100 0 i
- *=i 10.100.1.3 0 100 0 i
-
- Displayed 1 routes and 3 total paths
- Router-RR#
-
- Router-PE4# show ip bgp
- BGP table version is 5, local router ID is 10.100.1.4, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- *>i203.0.113.0/24 10.100.1.1 0 100 0 i
-
- Displayed 1 routes and 1 total paths
- Router-PE4#
-
-When Optimal Route Reflection is enabled on RR, it sends 10.100.1.3 as the best path to its clients.
-
-.. code-block:: frr
-
- Router-RR# show ip bgp neighbors 10.100.1.4
-
- !--- Output suppressed.
-
- For address family: IPv4 Unicast
- Update group 1, subgroup 1
- Packet Queue length 0
- Route-Reflector Client
- ORR group (configured) : orr-1
- Community attribute sent to this neighbor(all)
- 0 accepted prefixes
-
- !--- Output suppressed.
-
- Router-RR#
- Router-RR# show ip bgp
- BGP table version is 1, local router ID is 10.100.1.8, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- * i203.0.113.0/24 10.100.1.2 0 100 0 i
- *>i 10.100.1.3 0 100 0 i
- * i 10.100.1.1 0 100 0 i
-
- Displayed 1 routes and 3 total paths
- Router-RR#
-
- Router-RR# show ip bgp optimal-route-reflection
-
- ORR group: orr-1, IPv4 Unicast
- Configured root: primary: 10.100.1.4(Router-PE4), secondary: 10.100.1.3(Router-PE3), tertiary: 10.100.1.1(Router-PE1)
- Active Root: 10.100.1.4(Router-PE4)
-
- RR Clients mapped:
- 10.100.1.1
- 10.100.1.2
- 10.100.1.3
- 10.100.1.4
-
- Number of mapping entries: 4
-
- Prefix Cost
- 10.10.34.0/24 100
- 10.10.61.0/24 300
- 10.10.63.0/24 200
- 10.10.67.0/24 200
- 10.10.68.0/24 300
- 10.10.72.0/24 200
- 10.10.74.0/24 100
- 10.100.1.1/32 300
- 10.100.1.2/32 200
- 10.100.1.3/32 100
- 10.100.1.4/32 0
- 10.100.1.6/32 200
- 10.100.1.7/32 100
- 10.100.1.8/32 300
-
- Number of mapping entries: 14
-
- Router-RR#
-
- Router-PE4# show ip bgp
- BGP table version is 3, local router ID is 10.100.1.4, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- *>i203.0.113.0/24 10.100.1.3 0 100 0 i
-
- Displayed 1 routes and 1 total paths
- Router-PE4#
-
.. _bgp-debugging:
Debugging
@@ -3937,10 +3631,6 @@ Debugging
Enable or disable debugging of communications between *bgpd* and *zebra*.
-.. clicmd:: debug bgp optimal-route-reflection
-
- Enable or disable debugging of BGP Optimal Route Reflection.
-
Dumping Messages and Routing Tables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -4065,6 +3755,11 @@ The following command is available in ``config`` mode as well as in the
Set the BGP Input Queue limit for all peers when messaging parsing. Increase
this only if you have the memory to handle large queues of messages at once.
+.. clicmd:: bgp output-queue-limit (1-4294967295)
+
+ Set the BGP Output Queue limit for all peers when messaging parsing. Increase
+ this only if you have the memory to handle large queues of messages at once.
+
.. _bgp-displaying-bgp-information:
Displaying BGP Information
@@ -4150,6 +3845,28 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
.. clicmd:: show bgp [afi] [safi] [all] [wide|json]
+.. clicmd:: show bgp vrfs [<VRFNAME$vrf_name>] [json]
+
+ The command displays all bgp vrf instances basic info like router-id,
+ configured and established neighbors,
+ evpn related basic info like l3vni, router-mac, vxlan-interface.
+ User can get that information as JSON format when ``json`` keyword
+ at the end of cli is presented.
+
+ .. code-block:: frr
+
+ torc-11# show bgp vrfs
+ Type Id routerId #PeersCfg #PeersEstb Name
+ L3-VNI RouterMAC Interface
+ DFLT 0 17.0.0.6 3 3 default
+ 0 00:00:00:00:00:00 unknown
+ VRF 21 17.0.0.6 0 0 sym_1
+ 8888 34:11:12:22:22:01 vlan4034_l3
+ VRF 32 17.0.0.6 0 0 sym_2
+ 8889 34:11:12:22:22:01 vlan4035_l3
+
+ Total number of VRFs (including default): 3
+
.. clicmd:: show bgp [<ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast|flowspec> | l2vpn evpn]
These commands display BGP routes for the specific routing table indicated by
@@ -4199,7 +3916,7 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
The ``terse`` option can be used in combination with the remote-as, neighbor,
failed and established filters, and with the ``wide`` option as well.
-.. clicmd:: show bgp [afi] [safi] [neighbor [PEER] [routes|advertised-routes|received-routes] [json]
+.. clicmd:: show bgp [afi] [safi] [neighbor [PEER] [routes|advertised-routes|received-routes] [detail] [json]
This command shows information on a specific BGP peer of the relevant
afi and safi selected.
@@ -4214,6 +3931,13 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
The ``received-routes`` keyword displays all routes belonging to this
address-family (prior to inbound policy) that were received by this peer.
+ If ``detail`` option is specified, the detailed version of all routes
+ will be displayed. The same format as ``show [ip] bgp [afi] [safi] PREFIX``
+ will be used, but for the whole table of received, advertised or filtered
+ prefixes.
+
+ If ``json`` option is specified, output is displayed in JSON format.
+
.. clicmd:: show bgp [<view|vrf> VIEWVRFNAME] [afi] [safi] neighbors PEER received prefix-filter [json]
Display Address Prefix ORFs received from this peer.
@@ -4306,7 +4030,7 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
If the ``json`` option is specified, output is displayed in JSON format.
-.. clicmd:: show [ip] bgp [afi] [safi] [all] neighbors A.B.C.D [advertised-routes|received-routes|filtered-routes] [json|wide]
+.. clicmd:: show [ip] bgp [afi] [safi] [all] neighbors A.B.C.D [advertised-routes|received-routes|filtered-routes] [detail] [json|wide]
Display the routes advertised to a BGP neighbor or received routes
from neighbor or filtered routes received from neighbor based on the
@@ -4323,6 +4047,11 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
if afi is specified, with ``all`` option, routes will be displayed for
each SAFI in the selcted AFI
+ If ``detail`` option is specified, the detailed version of all routes
+ will be displayed. The same format as ``show [ip] bgp [afi] [safi] PREFIX``
+ will be used, but for the whole table of received, advertised or filtered
+ prefixes.
+
If ``json`` option is specified, output is displayed in JSON format.
.. clicmd:: show [ip] bgp [afi] [safi] [all] detail-routes
@@ -4493,7 +4222,7 @@ Displaying Update Group Information
Display Information about update-group events in FRR.
Displaying Nexthop Information
---------------------
+------------------------------
.. clicmd:: show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop ipv4 [A.B.C.D] [detail] [json]
.. clicmd:: show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop ipv6 [X:X::X:X] [detail] [json]
diff --git a/doc/user/evpn.rst b/doc/user/evpn.rst
index c8052803cc..7c4d9fe7d9 100644
--- a/doc/user/evpn.rst
+++ b/doc/user/evpn.rst
@@ -502,3 +502,29 @@ the creation of the VLAN subinterfaces and directly enslave "eth0" to "br10".
ip link set eth0 master br10
This completes the necessary configuration for an L2VNI.
+
+Displaying EVPN information
+---------------------------
+
+.. clicmd:: show evpn mac vni (1-16777215) detail [json]
+
+ Display detailed information about MAC addresses for
+ a specified VNI.
+
+.. clicmd:: show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]
+
+ Displays VRF to L3VNI mapping. It also displays L3VNI associated
+ router-mac, svi interface and vxlan interface.
+ User can get that information as JSON format when ``json`` keyword
+ at the end of cli is presented.
+
+ .. code-block:: frr
+
+ tor2# show vrf vni
+ VRF VNI VxLAN IF L3-SVI State Rmac
+ sym_1 9288 vxlan21 vlan210_l3 Up 21:31:36:ff:ff:20
+ sym_2 9289 vxlan21 vlan210_l3 Up 21:31:36:ff:ff:20
+ sym_3 9290 vxlan21 vlan210_l3 Up 21:31:36:ff:ff:20
+ tor2# show vrf sym_1 vni
+ VRF VNI VxLAN IF L3-SVI State Rmac
+ sym_1 9288 vxlan21 vlan210_l3 Up 44:38:36:ff:ff:20
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 0dff2ea448..b69230b99d 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -838,12 +838,6 @@ Showing Information
User can get that information as JSON format when ``json`` keyword
at the end of cli is presented.
-.. clicmd:: show ip ospf (1-65535) route orr [NAME]
-
-.. clicmd:: show ip ospf [vrf <NAME|all>] route orr [NAME]
-
- Show the OSPF routing table, calculated from the active root of all ORR groups or specified ORR group.
-
.. clicmd:: show ip ospf graceful-restart helper [detail] [json]
Displays the Grcaeful Restart Helper details including helper
@@ -1151,10 +1145,6 @@ Debugging OSPF
.. clicmd:: show debugging ospf
-.. clicmd:: debug ospf orr
-
- Enable or disable debugging of BGP Optimal Route Reflection.
-
Sample Configuration
====================
diff --git a/doc/user/subdir.am b/doc/user/subdir.am
index e07c9b6dc3..706e1ea449 100644
--- a/doc/user/subdir.am
+++ b/doc/user/subdir.am
@@ -58,6 +58,8 @@ user_RSTFILES = \
EXTRA_DIST += \
$(user_RSTFILES) \
doc/user/Useful_Sysctl_Settings.md \
+ doc/user/_static/overrides.css \
+ doc/user/_static/overrides.js \
# end
USERBUILD = doc/user/_build
diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c
index 4f4e6dc730..c5653d0348 100644
--- a/isisd/isis_nb.c
+++ b/isisd/isis_nb.c
@@ -1107,6 +1107,66 @@ const struct frr_yang_module_info frr_isisd_info = {
}
},
{
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid",
+ .cbs = {
+ .get_next = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid",
+ .cbs = {
+ .get_next = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested",
+ .cbs = {
+ .get_elem = lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem,
+ }
+ },
+ {
.xpath = "/frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes",
.cbs = {
.get_elem = lib_interface_state_isis_event_counters_adjacency_changes_get_elem,
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index a9f2eaea95..380ce4f251 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -369,6 +369,36 @@ lib_interface_state_isis_adjacencies_adjacency_neighbor_priority_get_elem(
struct nb_cb_get_elem_args *args);
struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem(
struct nb_cb_get_elem_args *args);
+const void *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args);
+const void *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args);
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args);
struct yang_data *
lib_interface_state_isis_event_counters_adjacency_changes_get_elem(
struct nb_cb_get_elem_args *args);
diff --git a/isisd/isis_nb_state.c b/isisd/isis_nb_state.c
index 4e325ed8da..5b1fc6e1d2 100644
--- a/isisd/isis_nb_state.c
+++ b/isisd/isis_nb_state.c
@@ -216,6 +216,228 @@ struct yang_data *lib_interface_state_isis_adjacencies_adjacency_state_get_elem(
/*
* XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid
+ */
+const void *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ const struct isis_adjacency *adj = args->parent_list_entry;
+ const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
+ struct listnode *node, *node_next;
+
+ if (args->list_entry == NULL)
+ sra_next = listnode_head(adj->adj_sids);
+ else {
+ node = listnode_lookup(adj->adj_sids, sra);
+ node_next = listnextnode(node);
+ if (node_next)
+ sra_next = listgetdata(node_next);
+ }
+
+ return sra_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/af
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint8(args->xpath, sra->u.adj_sid->family);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/value
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint32(args->xpath, sra->u.adj_sid->sid);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/weight
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_uint8(args->xpath, sra->u.adj_sid->weight);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/adjacency-sids/adjacency-sid/protection-requested
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_adjacency_sids_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ /* Adjacency SID is not published with circuit type Broadcast */
+ return NULL;
+ case CIRCUIT_T_P2P:
+ return yang_data_new_bool(args->xpath,
+ sra->u.adj_sid->flags &
+ EXT_SUBTLV_LINK_ADJ_SID_BFLG);
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid
+ */
+const void *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_get_next(
+ struct nb_cb_get_next_args *args)
+{
+ const struct isis_adjacency *adj = args->parent_list_entry;
+ const struct sr_adjacency *sra = args->list_entry, *sra_next = NULL;
+ struct listnode *node, *node_next;
+
+ if (args->list_entry == NULL)
+ sra_next = listnode_head(adj->adj_sids);
+ else {
+ node = listnode_lookup(adj->adj_sids, sra);
+ node_next = listnextnode(node);
+ if (node_next)
+ sra_next = listgetdata(node_next);
+ }
+
+ return sra_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/af
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_af_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint8(args->xpath,
+ sra->u.ladj_sid->family);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/value
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_value_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint32(args->xpath, sra->u.ladj_sid->sid);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/weight
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_weight_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_uint8(args->xpath,
+ sra->u.ladj_sid->weight);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/state/frr-isisd:isis/adjacencies/adjacency/lan-adjacency-sids/lan-adjacency-sid/protection-requested
+ */
+struct yang_data *
+lib_interface_state_isis_adjacencies_adjacency_lan_adjacency_sids_lan_adjacency_sid_protection_requested_get_elem(
+ struct nb_cb_get_elem_args *args)
+{
+ const struct sr_adjacency *sra = args->list_entry;
+
+ switch (sra->adj->circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ return yang_data_new_bool(args->xpath,
+ sra->u.ladj_sid->flags &
+ EXT_SUBTLV_LINK_ADJ_SID_BFLG);
+ case CIRCUIT_T_P2P:
+ /* LAN adjacency SID is not published with circuit type P2P */
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * XPath:
* /frr-interface:lib/interface/state/frr-isisd:isis/event-counters/adjacency-changes
*/
struct yang_data *
diff --git a/lib/bfd.c b/lib/bfd.c
index 29b8d85d8d..ae402ec5cb 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -29,11 +29,13 @@
#include "stream.h"
#include "vrf.h"
#include "zclient.h"
+#include "libfrr.h"
#include "table.h"
#include "vty.h"
#include "bfd.h"
DEFINE_MTYPE_STATIC(LIB, BFD_INFO, "BFD info");
+DEFINE_MTYPE_STATIC(LIB, BFD_SOURCE, "BFD source cache");
/**
* BFD protocol integration configuration.
@@ -48,6 +50,29 @@ enum bfd_session_event {
};
/**
+ * BFD source selection result cache.
+ *
+ * This structure will keep track of the result based on the destination
+ * prefix. When the result changes all related BFD sessions with automatic
+ * source will be updated.
+ */
+struct bfd_source_cache {
+ /** Address VRF belongs. */
+ vrf_id_t vrf_id;
+ /** Destination network address. */
+ struct prefix address;
+ /** Source selected. */
+ struct prefix source;
+ /** Is the source address valid? */
+ bool valid;
+ /** BFD sessions using this. */
+ size_t refcount;
+
+ SLIST_ENTRY(bfd_source_cache) entry;
+};
+SLIST_HEAD(bfd_source_list, bfd_source_cache);
+
+/**
* Data structure to do the necessary tricks to hide the BFD protocol
* integration internals.
*/
@@ -82,6 +107,11 @@ struct bfd_session_params {
/** BFD session installation state. */
bool installed;
+ /** Automatic source selection. */
+ bool auto_source;
+ /** Currently selected source. */
+ struct bfd_source_cache *source_cache;
+
/** Global BFD paramaters list. */
TAILQ_ENTRY(bfd_session_params) entry;
};
@@ -92,11 +122,15 @@ struct bfd_sessions_global {
* without code duplication among daemons.
*/
TAILQ_HEAD(bsplist, bfd_session_params) bsplist;
+ /** BFD automatic source selection cache. */
+ struct bfd_source_list source_list;
/** Pointer to FRR's event manager. */
struct thread_master *tm;
/** Pointer to zebra client data structure. */
struct zclient *zc;
+ /** Zebra next hop tracking (NHT) client. */
+ struct zclient *nht_zclient;
/** Debugging state. */
bool debugging;
@@ -111,6 +145,34 @@ static struct bfd_sessions_global bsglobal;
static const struct in6_addr i6a_zero;
/*
+ * Prototypes
+ */
+static void bfd_nht_zclient_connect(struct thread *thread);
+
+static void bfd_nht_zclient_connected(struct zclient *zclient);
+static int bfd_nht_update(ZAPI_CALLBACK_ARGS);
+
+static void bfd_source_cache_get(struct bfd_session_params *session);
+static void bfd_source_cache_put(struct bfd_session_params *session);
+
+static inline void
+bfd_source_cache_register(const struct bfd_source_cache *source)
+{
+ zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_REGISTER,
+ &source->address, SAFI_UNICAST, false, false,
+ source->vrf_id);
+}
+
+static inline void
+bfd_source_cache_unregister(const struct bfd_source_cache *source)
+{
+ zclient_send_rnh(bsglobal.nht_zclient, ZEBRA_NEXTHOP_UNREGISTER,
+ &source->address, SAFI_UNICAST, false, false,
+ source->vrf_id);
+}
+
+
+/*
* bfd_get_peer_info - Extract the Peer information for which the BFD session
* went down from the message sent from Zebra to clients.
*/
@@ -531,6 +593,8 @@ void bfd_sess_free(struct bfd_session_params **bsp)
/* Remove from global list. */
TAILQ_REMOVE(&bsglobal.bsplist, (*bsp), entry);
+ bfd_source_cache_put(*bsp);
+
/* Free the memory and point to NULL. */
XFREE(MTYPE_BFD_INFO, (*bsp));
}
@@ -565,6 +629,8 @@ void bfd_sess_set_ipv4_addrs(struct bfd_session_params *bsp,
/* If already installed, remove the old setting. */
_bfd_sess_remove(bsp);
+ /* Address changed so we must reapply auto source. */
+ bfd_source_cache_put(bsp);
bsp->args.family = AF_INET;
@@ -578,6 +644,9 @@ void bfd_sess_set_ipv4_addrs(struct bfd_session_params *bsp,
assert(dst);
memcpy(&bsp->args.dst, dst, sizeof(struct in_addr));
+
+ if (bsp->auto_source)
+ bfd_source_cache_get(bsp);
}
void bfd_sess_set_ipv6_addrs(struct bfd_session_params *bsp,
@@ -589,6 +658,8 @@ void bfd_sess_set_ipv6_addrs(struct bfd_session_params *bsp,
/* If already installed, remove the old setting. */
_bfd_sess_remove(bsp);
+ /* Address changed so we must reapply auto source. */
+ bfd_source_cache_put(bsp);
bsp->args.family = AF_INET6;
@@ -600,6 +671,9 @@ void bfd_sess_set_ipv6_addrs(struct bfd_session_params *bsp,
assert(dst);
bsp->args.dst = *dst;
+
+ if (bsp->auto_source)
+ bfd_source_cache_get(bsp);
}
void bfd_sess_set_interface(struct bfd_session_params *bsp, const char *ifname)
@@ -646,8 +720,13 @@ void bfd_sess_set_vrf(struct bfd_session_params *bsp, vrf_id_t vrf_id)
/* If already installed, remove the old setting. */
_bfd_sess_remove(bsp);
+ /* Address changed so we must reapply auto source. */
+ bfd_source_cache_put(bsp);
bsp->args.vrf_id = vrf_id;
+
+ if (bsp->auto_source)
+ bfd_source_cache_get(bsp);
}
void bfd_sess_set_hop_count(struct bfd_session_params *bsp, uint8_t hops)
@@ -677,6 +756,18 @@ void bfd_sess_set_timers(struct bfd_session_params *bsp,
bsp->args.min_tx = min_tx;
}
+void bfd_sess_set_auto_source(struct bfd_session_params *bsp, bool enable)
+{
+ if (bsp->auto_source == enable)
+ return;
+
+ bsp->auto_source = enable;
+ if (enable)
+ bfd_source_cache_get(bsp);
+ else
+ bfd_source_cache_put(bsp);
+}
+
void bfd_sess_install(struct bfd_session_params *bsp)
{
bsp->lastev = BSE_INSTALL;
@@ -746,6 +837,11 @@ void bfd_sess_timers(const struct bfd_session_params *bsp,
*min_tx = bsp->args.min_tx;
}
+bool bfd_sess_auto_source(const struct bfd_session_params *bsp)
+{
+ return bsp->auto_source;
+}
+
void bfd_sess_show(struct vty *vty, struct json_object *json,
struct bfd_session_params *bsp)
{
@@ -950,10 +1046,51 @@ int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
return 0;
}
+/**
+ * Frees all allocated resources and stops any activity.
+ *
+ * Must be called after every BFD session has been successfully
+ * unconfigured otherwise this function will `free()` any available
+ * session causing existing pointers to dangle.
+ *
+ * This is just a comment, in practice it will be called by the FRR
+ * library late finish hook. \see `bfd_protocol_integration_init`.
+ */
+static int bfd_protocol_integration_finish(void)
+{
+ if (bsglobal.zc == NULL)
+ return 0;
+
+ while (!TAILQ_EMPTY(&bsglobal.bsplist)) {
+ struct bfd_session_params *session =
+ TAILQ_FIRST(&bsglobal.bsplist);
+ bfd_sess_free(&session);
+ }
+
+ /*
+ * BFD source cache is linked to sessions, if all sessions are gone
+ * then the source cache must be empty.
+ */
+ if (!SLIST_EMPTY(&bsglobal.source_list))
+ zlog_warn("BFD integration source cache not empty");
+
+ zclient_stop(bsglobal.nht_zclient);
+ zclient_free(bsglobal.nht_zclient);
+
+ return 0;
+}
+
+static zclient_handler *const bfd_nht_handlers[] = {
+ [ZEBRA_NEXTHOP_UPDATE] = bfd_nht_update,
+};
+
void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)
{
+ struct zclient_options bfd_nht_options = zclient_options_default;
+
/* Initialize data structure. */
TAILQ_INIT(&bsglobal.bsplist);
+ SLIST_INIT(&bsglobal.source_list);
/* Copy pointers. */
bsglobal.zc = zc;
@@ -964,6 +1101,18 @@ void bfd_protocol_integration_init(struct zclient *zc, struct thread_master *tm)
/* Send the client registration */
bfd_client_sendmsg(zc, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
+
+ /* Start NHT client (for automatic source decisions). */
+ bsglobal.nht_zclient =
+ zclient_new(tm, &bfd_nht_options, bfd_nht_handlers,
+ array_size(bfd_nht_handlers));
+ bsglobal.nht_zclient->sock = -1;
+ bsglobal.nht_zclient->privs = zc->privs;
+ bsglobal.nht_zclient->zebra_connected = bfd_nht_zclient_connected;
+ thread_add_timer(tm, bfd_nht_zclient_connect, bsglobal.nht_zclient, 1,
+ &bsglobal.nht_zclient->t_connect);
+
+ hook_register(frr_fini, bfd_protocol_integration_finish);
}
void bfd_protocol_integration_set_debug(bool enable)
@@ -985,3 +1134,305 @@ bool bfd_protocol_integration_shutting_down(void)
{
return bsglobal.shutting_down;
}
+
+/*
+ * BFD automatic source selection
+ *
+ * This feature will use the next hop tracking (NHT) provided by zebra
+ * to find out the source address by looking at the output interface.
+ *
+ * When the interface address / routing table change we'll be notified
+ * and be able to update the source address accordingly.
+ *
+ * <daemon> zebra
+ * |
+ * +-----------------+
+ * | BFD session set |
+ * | to auto source |
+ * +-----------------+
+ * |
+ * \ +-----------------+
+ * --------------> | Resolves |
+ * | destination |
+ * | address |
+ * +-----------------+
+ * |
+ * +-----------------+ /
+ * | Sets resolved | <----------
+ * | source address |
+ * +-----------------+
+ */
+static bool
+bfd_source_cache_session_match(const struct bfd_source_cache *source,
+ const struct bfd_session_params *session)
+{
+ const struct in_addr *address;
+ const struct in6_addr *address_v6;
+
+ if (session->args.vrf_id != source->vrf_id)
+ return false;
+ if (session->args.family != source->address.family)
+ return false;
+
+ switch (session->args.family) {
+ case AF_INET:
+ address = (const struct in_addr *)&session->args.dst;
+ if (address->s_addr != source->address.u.prefix4.s_addr)
+ return false;
+ break;
+ case AF_INET6:
+ address_v6 = &session->args.dst;
+ if (memcmp(address_v6, &source->address.u.prefix6,
+ sizeof(struct in6_addr)))
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static struct bfd_source_cache *
+bfd_source_cache_find(vrf_id_t vrf_id, const struct prefix *prefix)
+{
+ struct bfd_source_cache *source;
+
+ SLIST_FOREACH (source, &bsglobal.source_list, entry) {
+ if (source->vrf_id != vrf_id)
+ continue;
+ if (!prefix_same(&source->address, prefix))
+ continue;
+
+ return source;
+ }
+
+ return NULL;
+}
+
+static void bfd_source_cache_get(struct bfd_session_params *session)
+{
+ struct bfd_source_cache *source;
+ struct prefix target = {};
+
+ switch (session->args.family) {
+ case AF_INET:
+ target.family = AF_INET;
+ target.prefixlen = IPV4_MAX_BITLEN;
+ memcpy(&target.u.prefix4, &session->args.dst,
+ sizeof(struct in_addr));
+ break;
+ case AF_INET6:
+ target.family = AF_INET6;
+ target.prefixlen = IPV6_MAX_BITLEN;
+ memcpy(&target.u.prefix6, &session->args.dst,
+ sizeof(struct in6_addr));
+ break;
+ default:
+ return;
+ }
+
+ source = bfd_source_cache_find(session->args.vrf_id, &target);
+ if (source) {
+ if (session->source_cache == source)
+ return;
+
+ bfd_source_cache_put(session);
+ session->source_cache = source;
+ source->refcount++;
+ return;
+ }
+
+ source = XCALLOC(MTYPE_BFD_SOURCE, sizeof(*source));
+ prefix_copy(&source->address, &target);
+ source->vrf_id = session->args.vrf_id;
+ SLIST_INSERT_HEAD(&bsglobal.source_list, source, entry);
+
+ bfd_source_cache_put(session);
+ session->source_cache = source;
+ source->refcount = 1;
+
+ bfd_source_cache_register(source);
+
+ return;
+}
+
+static void bfd_source_cache_put(struct bfd_session_params *session)
+{
+ if (session->source_cache == NULL)
+ return;
+
+ session->source_cache->refcount--;
+ if (session->source_cache->refcount > 0) {
+ session->source_cache = NULL;
+ return;
+ }
+
+ bfd_source_cache_unregister(session->source_cache);
+ SLIST_REMOVE(&bsglobal.source_list, session->source_cache,
+ bfd_source_cache, entry);
+ XFREE(MTYPE_BFD_SOURCE, session->source_cache);
+}
+
+/** Updates BFD running session if source address has changed. */
+static void
+bfd_source_cache_update_session(const struct bfd_source_cache *source,
+ struct bfd_session_params *session)
+{
+ const struct in_addr *address;
+ const struct in6_addr *address_v6;
+
+ switch (session->args.family) {
+ case AF_INET:
+ address = (const struct in_addr *)&session->args.src;
+ if (memcmp(address, &source->source.u.prefix4,
+ sizeof(struct in_addr)) == 0)
+ return;
+
+ _bfd_sess_remove(session);
+ memcpy(&session->args.src, &source->source.u.prefix4,
+ sizeof(struct in_addr));
+ break;
+ case AF_INET6:
+ address_v6 = &session->args.src;
+ if (memcmp(address_v6, &source->source.u.prefix6,
+ sizeof(struct in6_addr)) == 0)
+ return;
+
+ _bfd_sess_remove(session);
+ memcpy(&session->args.src, &source->source.u.prefix6,
+ sizeof(struct in6_addr));
+ break;
+ default:
+ return;
+ }
+
+ bfd_sess_install(session);
+}
+
+static void
+bfd_source_cache_update_sessions(const struct bfd_source_cache *source)
+{
+ struct bfd_session_params *session;
+
+ if (!source->valid)
+ return;
+
+ TAILQ_FOREACH (session, &bsglobal.bsplist, entry) {
+ if (!session->auto_source)
+ continue;
+ if (!bfd_source_cache_session_match(source, session))
+ continue;
+
+ bfd_source_cache_update_session(source, session);
+ }
+}
+
+/**
+ * Try to translate next hop information into source address.
+ *
+ * \returns `true` if source changed otherwise `false`.
+ */
+static bool bfd_source_cache_update(struct bfd_source_cache *source,
+ const struct zapi_route *route)
+{
+ size_t nh_index;
+
+ for (nh_index = 0; nh_index < route->nexthop_num; nh_index++) {
+ const struct zapi_nexthop *nh = &route->nexthops[nh_index];
+ const struct interface *interface;
+ const struct connected *connected;
+ const struct listnode *node;
+
+ interface = if_lookup_by_index(nh->ifindex, nh->vrf_id);
+ if (interface == NULL) {
+ zlog_err("next hop interface not found (index %d)",
+ nh->ifindex);
+ continue;
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(interface->connected, node,
+ connected)) {
+ if (source->address.family !=
+ connected->address->family)
+ continue;
+ if (prefix_same(connected->address, &source->source))
+ return false;
+ /*
+ * Skip link-local as it is only useful for single hop
+ * and in that case no source is specified usually.
+ */
+ if (source->address.family == AF_INET6 &&
+ IN6_IS_ADDR_LINKLOCAL(
+ &connected->address->u.prefix6))
+ continue;
+
+ prefix_copy(&source->source, connected->address);
+ source->valid = true;
+ return true;
+ }
+ }
+
+ memset(&source->source, 0, sizeof(source->source));
+ source->valid = false;
+ return false;
+}
+
+static void bfd_nht_zclient_connect(struct thread *thread)
+{
+ struct zclient *zclient = THREAD_ARG(thread);
+
+ if (bsglobal.debugging)
+ zlog_debug("BFD NHT zclient connection attempt");
+
+ if (zclient_start(zclient) == -1) {
+ if (bsglobal.debugging)
+ zlog_debug("BFD NHT zclient connection failed");
+
+ thread_add_timer(bsglobal.tm, bfd_nht_zclient_connect, zclient,
+ 3, &zclient->t_connect);
+ return;
+ }
+
+ if (bsglobal.debugging)
+ zlog_debug("BFD NHT zclient connection succeeded");
+}
+
+static void bfd_nht_zclient_connected(struct zclient *zclient)
+{
+ struct bfd_source_cache *source;
+
+ if (bsglobal.debugging)
+ zlog_debug("BFD NHT zclient connected");
+
+ SLIST_FOREACH (source, &bsglobal.source_list, entry)
+ bfd_source_cache_register(source);
+}
+
+static int bfd_nht_update(ZAPI_CALLBACK_ARGS)
+{
+ struct bfd_source_cache *source;
+ struct zapi_route route;
+ struct prefix match;
+
+ if (!zapi_nexthop_update_decode(zclient->ibuf, &match, &route)) {
+ zlog_warn("BFD NHT update decode failure");
+ return 0;
+ }
+ if (cmd != ZEBRA_NEXTHOP_UPDATE)
+ return 0;
+
+ if (bsglobal.debugging)
+ zlog_debug("BFD NHT update for %pFX", &route.prefix);
+
+ SLIST_FOREACH (source, &bsglobal.source_list, entry) {
+ if (source->vrf_id != route.vrf_id)
+ continue;
+ if (!prefix_same(&match, &source->address))
+ continue;
+ if (bfd_source_cache_update(source, &route))
+ bfd_source_cache_update_sessions(source);
+ }
+
+ return 0;
+}
diff --git a/lib/bfd.h b/lib/bfd.h
index 344ecc2c4d..b7e4eea5f3 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -222,6 +222,18 @@ void bfd_sess_set_timers(struct bfd_session_params *bsp,
uint32_t min_tx);
/**
+ * Configures the automatic source selection for the BFD session.
+ *
+ * NOTE:
+ * Setting this configuration will override the IP source value set by
+ * `bfd_sess_set_ipv4_addrs` or `bfd_sess_set_ipv6_addrs`.
+ *
+ * \param bsp BFD session parameters
+ * \param enable BFD automatic source selection state.
+ */
+void bfd_sess_set_auto_source(struct bfd_session_params *bsp, bool enable);
+
+/**
* Installs or updates the BFD session based on the saved session arguments.
*
* NOTE:
@@ -331,6 +343,11 @@ void bfd_sess_timers(const struct bfd_session_params *bsp,
uint32_t *min_tx);
/**
+ * Gets the automatic source selection state.
+ */
+bool bfd_sess_auto_source(const struct bfd_session_params *bsp);
+
+/**
* Show BFD session configuration and status. If `json` is provided (e.g. not
* `NULL`) then information will be inserted in object, otherwise printed to
* `vty`.
diff --git a/lib/command.h b/lib/command.h
index 0f9715e81c..bce4fb9e1c 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -398,7 +398,6 @@ struct cmd_node {
#define BGP_SOFT_IN_STR "Send route-refresh unless using 'soft-reconfiguration inbound'\n"
#define BGP_SOFT_OUT_STR "Resend all outbound updates\n"
#define BGP_SOFT_RSCLIENT_RIB_STR "Soft reconfig for rsclient RIB\n"
-#define BGP_ORR_DEBUG "Enable Optimal Route Reflection Debugging logs\n"
#define OSPF_STR "OSPF information\n"
#define NEIGHBOR_STR "Specify neighbor router\n"
#define DEBUG_STR "Debugging functions\n"
@@ -497,6 +496,13 @@ struct cmd_node {
#define ROLE_STR \
"Providing transit\nRoute server\nRS client\nUsing transit\nPublic/private peering\n"
+/* BFD protocol integration strings. */
+#define BFD_INTEGRATION_STR "BFD monitoring\n"
+#define BFD_INTEGRATION_MULTI_HOP_STR "Use BFD multi hop session\n"
+#define BFD_INTEGRATION_SOURCE_STR "Use source for BFD session\n"
+#define BFD_INTEGRATION_SOURCEV4_STR "Use IPv4 source for BFD session\n"
+#define BFD_INTEGRATION_SOURCEV6_STR "Use IPv4 source for BFD session\n"
+
/* Prototypes. */
extern void install_node(struct cmd_node *node);
extern void install_default(enum node_type);
diff --git a/lib/elf_py.c b/lib/elf_py.c
index 75d2d6007f..7c503cfb9d 100644
--- a/lib/elf_py.c
+++ b/lib/elf_py.c
@@ -293,7 +293,7 @@ static PyObject *elfreloc_getsection(PyObject *self, PyObject *args)
if (!w->es)
Py_RETURN_NONE;
- if (w->symidx == 0) {
+ if (!w->symvalid || w->symidx == 0) {
size_t idx = 0;
Elf_Scn *scn;
diff --git a/lib/if.c b/lib/if.c
index 6766a04b37..db73210036 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -580,8 +580,7 @@ struct interface *if_get_vrf_loopback(vrf_id_t vrf_id)
}
/* Get interface by name if given name interface doesn't exist create
- * one.
- */
+ one. */
struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
const char *vrf_name)
{
diff --git a/lib/orr_msg.h b/lib/orr_msg.h
deleted file mode 100644
index b0c4c48df8..0000000000
--- a/lib/orr_msg.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Structures common to BGP, OSPF and ISIS for BGP Optimal Route Reflection
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _FRR_ORR_MSG_H
-#define _FRR_ORR_MSG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* REVISIT: Need to check if we can use zero length array */
-#define ORR_MAX_PREFIX 100
-#define ORR_GROUP_NAME_SIZE 32
-
-struct orr_prefix_metric {
- struct prefix prefix;
- uint32_t metric;
-};
-
-/* BGP-IGP Register for IGP metric */
-struct orr_igp_metric_reg {
- bool reg;
- uint8_t proto;
- safi_t safi;
- struct prefix prefix;
- char group_name[ORR_GROUP_NAME_SIZE];
-};
-
-/* IGP-BGP message structures */
-struct orr_igp_metric_info {
- /* IGP instance data. */
- uint8_t proto;
- uint32_t instId;
-
- safi_t safi;
-
- /* Add or delete routes */
- bool add;
-
- /* IGP metric from Active Root. */
- struct prefix root;
- uint32_t num_entries;
- struct orr_prefix_metric nexthop[ORR_MAX_PREFIX];
-};
-
-/* BGP ORR Root node */
-struct orr_root {
- afi_t afi;
- safi_t safi;
-
- char group_name[ORR_GROUP_NAME_SIZE];
-
- /* MPLS_TE prefix and router ID */
- struct prefix prefix;
- struct in_addr router_id;
-
- /* Advertising OSPF Router ID. */
- struct in_addr adv_router;
-
- /* BGP-ORR Received LSAs */
- struct ospf_lsa *router_lsa_rcvd;
-
- /* Routing tables from root node */
- struct route_table *old_table; /* Old routing table. */
- struct route_table *new_table; /* Current routing table. */
-
- struct route_table *old_rtrs; /* Old ABR/ASBR RT. */
- struct route_table *new_rtrs; /* New ABR/ASBR RT. */
-};
-
-/* Prototypes. */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _FRR_ORR_MSG_H */
diff --git a/lib/prefix.c b/lib/prefix.c
index 4642f14d35..1d098f78c5 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1489,7 +1489,7 @@ static ssize_t printfrr_ia(struct fbuf *buf, struct printfrr_eargs *ea,
ea->fmt++;
}
- if (!ipa)
+ if (!ipa || !ipa->ipa_type)
return bputs(buf, "(null)");
if (use_star) {
diff --git a/lib/subdir.am b/lib/subdir.am
index 1a8c184823..754a7da638 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -225,7 +225,6 @@ pkginclude_HEADERS += \
lib/ns.h \
lib/openbsd-queue.h \
lib/openbsd-tree.h \
- lib/orr_msg.h \
lib/plist.h \
lib/prefix.h \
lib/printfrr.h \
diff --git a/lib/vrf.c b/lib/vrf.c
index 5878c1734f..2ac7ef7a97 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -1000,8 +1000,7 @@ lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args *args)
struct vrf *vrfp = (struct vrf *)args->list_entry;
if (vrfp->status == VRF_ACTIVE)
- return yang_data_new_bool(
- args->xpath, vrfp->status == VRF_ACTIVE ? true : false);
+ return yang_data_new_bool(args->xpath, true);
return NULL;
}
diff --git a/lib/xref.h b/lib/xref.h
index 0e3f00f690..37242bd79e 100644
--- a/lib/xref.h
+++ b/lib/xref.h
@@ -208,8 +208,19 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
* some build issue with it just add -DFRR_XREF_NO_NOTE to your build flags
* to disable it.
*/
-#ifdef FRR_XREF_NO_NOTE
+#if defined(FRR_XREF_NO_NOTE) || defined(__mips64)
#define XREF_NOTE ""
+
+/* mips64 note: MIPS64 (regardless of endianness, both mips64 & mips64el)
+ * does not have a 64-bit PC-relative relocation type. Unfortunately, a
+ * 64-bit PC-relative relocation is exactly what the below asm magic emits.
+ * Therefore, the xref ELF note is permanently disabled on MIPS64.
+ *
+ * For some context, refer to https://reviews.llvm.org/D80390
+ *
+ * As noted above, xref extraction still works through the section header
+ * path, so no functionality is lost.
+ */
#else
#if __SIZEOF_POINTER__ == 4
diff --git a/lib/zclient.h b/lib/zclient.h
index 584a42194d..8c4ce1b777 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -102,8 +102,6 @@ enum zserv_client_capabilities {
extern struct sockaddr_storage zclient_addr;
extern socklen_t zclient_addr_len;
-#define ZAPI_ORR_FLAG_UNICAST 0x01
-
/* Zebra message types. */
typedef enum {
ZEBRA_INTERFACE_ADD,
@@ -1248,10 +1246,6 @@ enum zapi_opaque_registry {
LDP_RLFA_UNREGISTER_ALL = 8,
/* Announce LDP labels associated to a previously registered RLFA */
LDP_RLFA_LABELS = 9,
- /* Register for IGP METRIC with OSPF/ISIS */
- ORR_IGP_METRIC_REGISTER = 10,
- /* Send SPF data to BGP */
- ORR_IGP_METRIC_UPDATE = 11
};
/* Send the hello message.
diff --git a/lib/zlog_5424.c b/lib/zlog_5424.c
index 9da7c55fc5..60feca7fcb 100644
--- a/lib/zlog_5424.c
+++ b/lib/zlog_5424.c
@@ -605,12 +605,13 @@ static void gmtime_assafe(time_t ts, struct tm *res)
if (ts >= 306) /* Jan 1 of next year */
res->tm_year++;
- static unsigned int months[13] = {
+ static time_t months[13] = {
0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337, 365,
};
+ const size_t month_max = array_size(months) - 1;
- for (size_t i = 0; i < array_size(months); i++) {
- if ((unsigned int)ts < months[i + 1]) {
+ for (size_t i = 0; i < month_max; i++) {
+ if (ts < months[i + 1]) {
res->tm_mon = ((i + 2) % 12);
res->tm_mday = 1 + ts - months[i];
break;
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index a47ed8d67a..c1f4b23069 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -61,7 +61,6 @@ unsigned long conf_debug_ospf_ldp_sync;
unsigned long conf_debug_ospf_gr;
unsigned long conf_debug_ospf_bfd;
unsigned long conf_debug_ospf_client_api;
-unsigned long conf_debug_ospf_orr;
/* Enable debug option variables -- valid only session. */
unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
@@ -80,7 +79,6 @@ unsigned long term_debug_ospf_ldp_sync;
unsigned long term_debug_ospf_gr;
unsigned long term_debug_ospf_bfd;
unsigned long term_debug_ospf_client_api;
-unsigned long term_debug_ospf_orr;
const char *ospf_redist_string(unsigned int route_type)
{
@@ -1601,33 +1599,6 @@ DEFPY (debug_ospf_client_api,
return CMD_SUCCESS;
}
-DEFPY (debug_ospf_orr,
- debug_ospf_orr_cmd,
- "[no$no] debug ospf [(1-65535)$instance] orr",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "Instance ID\n"
- "OSPF ORR information\n")
-{
- if (instance && instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- if (vty->node == CONFIG_NODE) {
- if (no)
- DEBUG_OFF(orr, ORR);
- else
- DEBUG_ON(orr, ORR);
- } else {
- if (no)
- TERM_DEBUG_OFF(orr, ORR);
- else
- TERM_DEBUG_ON(orr, ORR);
- }
-
- return CMD_SUCCESS;
-}
-
DEFUN (no_debug_ospf,
no_debug_ospf_cmd,
"no debug ospf",
@@ -1670,8 +1641,6 @@ DEFUN (no_debug_ospf,
for (i = 0; i < 5; i++)
DEBUG_PACKET_OFF(i, flag);
-
- DEBUG_OFF(orr, ORR);
}
for (i = 0; i < 5; i++)
@@ -1702,7 +1671,6 @@ DEFUN (no_debug_ospf,
TERM_DEBUG_OFF(ti_lfa, TI_LFA);
TERM_DEBUG_OFF(bfd, BFD_LIB);
TERM_DEBUG_OFF(client_api, CLIENT_API);
- TERM_DEBUG_OFF(orr, ORR);
return CMD_SUCCESS;
}
@@ -1832,12 +1800,6 @@ static int show_debugging_ospf_common(struct vty *vty)
if (IS_DEBUG_OSPF(client_api, CLIENT_API) == OSPF_DEBUG_CLIENT_API)
vty_out(vty, " OSPF client-api debugging is on\n");
- /* Show debug status for ORR. */
- if (IS_DEBUG_OSPF(orr, ORR) == OSPF_DEBUG_ORR)
- vty_out(vty, " OSPF ORR debugging is on\n");
-
- vty_out(vty, "\n");
-
return CMD_SUCCESS;
}
@@ -2050,12 +2012,6 @@ static int config_write_debug(struct vty *vty)
write = 1;
}
- /* debug ospf orr */
- if (IS_CONF_DEBUG_OSPF(orr, ORR) == OSPF_DEBUG_ORR) {
- vty_out(vty, "debug ospf%s orr\n", str);
- write = 1;
- }
-
return write;
}
@@ -2077,7 +2033,6 @@ void ospf_debug_init(void)
install_element(ENABLE_NODE, &debug_ospf_default_info_cmd);
install_element(ENABLE_NODE, &debug_ospf_ldp_sync_cmd);
install_element(ENABLE_NODE, &debug_ospf_client_api_cmd);
- install_element(ENABLE_NODE, &debug_ospf_orr_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd);
@@ -2117,7 +2072,6 @@ void ospf_debug_init(void)
install_element(CONFIG_NODE, &debug_ospf_default_info_cmd);
install_element(CONFIG_NODE, &debug_ospf_ldp_sync_cmd);
install_element(CONFIG_NODE, &debug_ospf_client_api_cmd);
- install_element(CONFIG_NODE, &debug_ospf_orr_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd);
diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h
index e9ba8fc798..251be7c8d1 100644
--- a/ospfd/ospf_dump.h
+++ b/ospfd/ospf_dump.h
@@ -70,8 +70,6 @@
#define OSPF_DEBUG_CLIENT_API 0x01
-#define OSPF_DEBUG_ORR 0x01
-
/* Macro for setting debug option. */
#define CONF_DEBUG_PACKET_ON(a, b) conf_debug_ospf_packet[a] |= (b)
#define CONF_DEBUG_PACKET_OFF(a, b) conf_debug_ospf_packet[a] &= ~(b)
@@ -131,8 +129,6 @@
#define AREA_NAME(A) ospf_area_name_string ((A))
#define IF_NAME(I) ospf_if_name_string ((I))
-#define IS_DEBUG_OSPF_ORR IS_DEBUG_OSPF(orr, ORR)
-
/* Extern debug flag. */
extern unsigned long term_debug_ospf_packet[];
extern unsigned long term_debug_ospf_event;
@@ -150,7 +146,6 @@ extern unsigned long term_debug_ospf_ldp_sync;
extern unsigned long term_debug_ospf_gr;
extern unsigned long term_debug_ospf_bfd;
extern unsigned long term_debug_ospf_client_api;
-extern unsigned long term_debug_ospf_orr;
/* Message Strings. */
extern char *ospf_lsa_type_str[];
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index ad4a9fd142..3e8b7b283d 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -52,8 +52,6 @@
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_errors.h"
-#include "ospfd/ospf_te.h"
-#include "ospfd/ospf_orr.h"
static struct ospf_lsa *ospf_handle_summarylsa_lsId_chg(struct ospf *ospf,
struct prefix_ipv4 *p,
@@ -2645,13 +2643,6 @@ ospf_router_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc)
ospf_refresher_register_lsa(ospf, new);
}
- /* For BGP ORR SPF should be calculated from specified root(s) */
- else if (ospf->orr_spf_request) {
- ospf_lsa_unlock(&area->router_lsa_rcvd);
- area->router_lsa_rcvd = ospf_lsa_lock(new);
- ospf_orr_root_update_rcvd_lsa(area->router_lsa_rcvd);
- }
-
if (rt_recalc)
ospf_spf_calculate_schedule(ospf, SPF_FLAG_ROUTER_LSA_INSTALL);
return new;
@@ -2663,6 +2654,7 @@ static struct ospf_lsa *ospf_network_lsa_install(struct ospf *ospf,
struct ospf_lsa *new,
int rt_recalc)
{
+
/* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
The entire routing table must be recalculated, starting with
the shortest path calculations for each area (not just the
@@ -3411,82 +3403,6 @@ struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *area, uint32_t type,
return NULL;
}
-struct ospf_lsa *ospf_lsa_lookup_by_adv_rid(struct ospf_area *area,
- uint32_t type, struct in_addr id)
-{
- struct ospf_lsa *lsa = NULL;
- struct route_node *rn = NULL;
-
- switch (type) {
- case OSPF_ROUTER_LSA:
- for (rn = route_top(ROUTER_LSDB(area)); rn;
- rn = route_next(rn)) {
- lsa = rn->info;
- if (lsa) {
- if (IPV4_ADDR_SAME(&lsa->data->adv_router,
- &id)) {
- route_unlock_node(rn);
- return lsa;
- }
- }
- }
- break;
- case OSPF_NETWORK_LSA:
- case OSPF_SUMMARY_LSA:
- case OSPF_ASBR_SUMMARY_LSA:
- case OSPF_AS_EXTERNAL_LSA:
- case OSPF_AS_NSSA_LSA:
- case OSPF_OPAQUE_LINK_LSA:
- case OSPF_OPAQUE_AREA_LSA:
- case OSPF_OPAQUE_AS_LSA:
- /* Currently not used. */
- break;
- default:
- break;
- }
-
- return NULL;
-}
-
-struct ospf_lsa *ospf_lsa_lookup_by_mpls_te_rid(struct ospf_area *area,
- uint32_t type,
- struct in_addr id)
-{
- struct ospf_lsa *lsa = NULL;
- struct route_node *rn = NULL;
- struct lsa_header *lsah = NULL;
- uint32_t lsid;
- uint8_t opaque_type;
- struct tlv_header *tlvh = NULL;
- struct te_tlv_router_addr *router_addr = NULL;
-
- if (type != OSPF_OPAQUE_AREA_LSA)
- return NULL;
-
- for (rn = route_top(OPAQUE_AREA_LSDB(area)); rn; rn = route_next(rn)) {
- lsa = rn->info;
- if (lsa) {
- lsah = lsa->data;
- lsid = ntohl(lsah->id.s_addr);
- opaque_type = GET_OPAQUE_TYPE(lsid);
- if (opaque_type != OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA)
- continue;
-
- tlvh = TLV_HDR_TOP(lsah);
- if (!tlvh ||
- (ntohs(tlvh->type) != TE_TLV_ROUTER_ADDR) ||
- (ntohs(tlvh->length) != TE_LINK_SUBTLV_DEF_SIZE))
- continue;
- router_addr = (struct te_tlv_router_addr *)tlvh;
- if (IPV4_ADDR_SAME(&router_addr->value, &id)) {
- route_unlock_node(rn);
- return lsa;
- }
- }
- }
- return NULL;
-}
-
struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *area,
struct lsa_header *lsah)
{
@@ -3918,9 +3834,8 @@ struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa)
struct as_external_lsa *al;
struct prefix_ipv4 p;
- if (!CHECK_FLAG(lsa->flags, OSPF_LSA_SELF) && !IS_LSA_SELF(lsa) &&
- !IS_LSA_ORR(lsa))
- return NULL;
+ assert(CHECK_FLAG(lsa->flags, OSPF_LSA_SELF));
+ assert(IS_LSA_SELF(lsa));
assert(lsa->lock > 0);
switch (lsa->data->type) {
@@ -3990,8 +3905,7 @@ void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
uint16_t index, current_index;
assert(lsa->lock > 0);
- if (!IS_LSA_SELF(lsa) && !IS_LSA_ORR(lsa))
- return;
+ assert(IS_LSA_SELF(lsa));
if (lsa->refresh_list < 0) {
int delay;
@@ -4040,8 +3954,7 @@ void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
void ospf_refresher_unregister_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
{
assert(lsa->lock > 0);
- if (!IS_LSA_SELF(lsa) || !IS_LSA_ORR(lsa))
- return;
+ assert(IS_LSA_SELF(lsa));
if (lsa->refresh_list >= 0) {
struct list *refresh_list =
ospf->lsa_refresh_queue.qs[lsa->refresh_list];
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 4e884fa89b..1caf8047e4 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -74,16 +74,15 @@ struct vertex;
/* OSPF LSA. */
struct ospf_lsa {
/* LSA origination flag. */
- uint16_t flags;
-#define OSPF_LSA_SELF 0x0001
-#define OSPF_LSA_SELF_CHECKED 0x0002
-#define OSPF_LSA_RECEIVED 0x0004
-#define OSPF_LSA_APPROVED 0x0008
-#define OSPF_LSA_DISCARD 0x0010
-#define OSPF_LSA_LOCAL_XLT 0x0020
-#define OSPF_LSA_PREMATURE_AGE 0x0040
-#define OSPF_LSA_IN_MAXAGE 0x0080
-#define OSPF_LSA_ORR 0x0100
+ uint8_t flags;
+#define OSPF_LSA_SELF 0x01
+#define OSPF_LSA_SELF_CHECKED 0x02
+#define OSPF_LSA_RECEIVED 0x04
+#define OSPF_LSA_APPROVED 0x08
+#define OSPF_LSA_DISCARD 0x10
+#define OSPF_LSA_LOCAL_XLT 0x20
+#define OSPF_LSA_PREMATURE_AGE 0x40
+#define OSPF_LSA_IN_MAXAGE 0x80
/* LSA data. and size */
struct lsa_header *data;
@@ -226,7 +225,6 @@ enum lsid_status { LSID_AVAILABLE = 0, LSID_CHANGE, LSID_NOT_AVAILABLE };
#define IS_LSA_MAXAGE(L) (LS_AGE ((L)) == OSPF_LSA_MAXAGE)
#define IS_LSA_MAX_SEQ(L) \
((L)->data->ls_seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))
-#define IS_LSA_ORR(L) (CHECK_FLAG ((L)->flags, OSPF_LSA_ORR))
#define OSPF_LSA_UPDATE_DELAY 2
@@ -297,12 +295,6 @@ extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *,
struct in_addr);
extern struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *, uint32_t,
struct in_addr);
-extern struct ospf_lsa *ospf_lsa_lookup_by_adv_rid(struct ospf_area *area,
- uint32_t type,
- struct in_addr id);
-extern struct ospf_lsa *ospf_lsa_lookup_by_mpls_te_rid(struct ospf_area *area,
- uint32_t type,
- struct in_addr id);
extern struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *,
struct lsa_header *);
extern int ospf_lsa_more_recent(struct ospf_lsa *, struct ospf_lsa *);
diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c
index 3c65ac388d..f4fb858a5f 100644
--- a/ospfd/ospf_lsdb.c
+++ b/ospfd/ospf_lsdb.c
@@ -30,7 +30,6 @@
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
-#include "ospfd/ospf_orr.h"
struct ospf_lsdb *ospf_lsdb_new(void)
{
@@ -88,10 +87,6 @@ static void ospf_lsdb_delete_entry(struct ospf_lsdb *lsdb,
assert(rn->table == lsdb->type[lsa->data->type].db);
- /* Update ORR Root table MPLS-TE Router address's advertise router */
- if (lsa->data->type == OSPF_OPAQUE_AREA_LSA)
- ospf_orr_root_table_update(lsa, false);
-
if (IS_LSA_SELF(lsa))
lsdb->type[lsa->data->type].count_self--;
lsdb->type[lsa->data->type].count--;
@@ -139,10 +134,6 @@ void ospf_lsdb_add(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
#endif /* MONITOR_LSDB_CHANGE */
lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum);
rn->info = ospf_lsa_lock(lsa); /* lsdb */
-
- /* Update ORR Root table MPLS-TE Router address's advertise router */
- if (lsa->data->type == OSPF_OPAQUE_AREA_LSA)
- ospf_orr_root_table_update(lsa, true);
}
void ospf_lsdb_delete(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
diff --git a/ospfd/ospf_memory.c b/ospfd/ospf_memory.c
index 5577a291be..2838443892 100644
--- a/ospfd/ospf_memory.c
+++ b/ospfd/ospf_memory.c
@@ -60,4 +60,3 @@ DEFINE_MTYPE(OSPFD, OSPF_GR_HELPER, "OSPF Graceful Restart Helper");
DEFINE_MTYPE(OSPFD, OSPF_EXTERNAL_RT_AGGR, "OSPF External Route Summarisation");
DEFINE_MTYPE(OSPFD, OSPF_P_SPACE, "OSPF TI-LFA P-Space");
DEFINE_MTYPE(OSPFD, OSPF_Q_SPACE, "OSPF TI-LFA Q-Space");
-DEFINE_MTYPE(OSPFD, OSPF_ORR_ROOT, "OSPF ORR Root");
diff --git a/ospfd/ospf_memory.h b/ospfd/ospf_memory.h
index 3d2133b11a..9bd0a844af 100644
--- a/ospfd/ospf_memory.h
+++ b/ospfd/ospf_memory.h
@@ -59,6 +59,5 @@ DECLARE_MTYPE(OSPF_GR_HELPER);
DECLARE_MTYPE(OSPF_EXTERNAL_RT_AGGR);
DECLARE_MTYPE(OSPF_P_SPACE);
DECLARE_MTYPE(OSPF_Q_SPACE);
-DECLARE_MTYPE(OSPF_ORR_ROOT);
#endif /* _QUAGGA_OSPF_MEMORY_H */
diff --git a/ospfd/ospf_orr.c b/ospfd/ospf_orr.c
deleted file mode 100644
index eed948b190..0000000000
--- a/ospfd/ospf_orr.c
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * OSPF BGP-IGP IGP metric update handling routines
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-#include <string.h>
-
-#include "monotime.h"
-#include "memory.h"
-#include "thread.h"
-#include "prefix.h"
-#include "table.h"
-#include "vty.h"
-#include "command.h"
-#include "plist.h"
-#include "log.h"
-#include "zclient.h"
-#include <lib/json.h>
-#include "defaults.h"
-#include "orr_msg.h"
-
-#include "ospfd.h"
-#include "ospf_asbr.h"
-#include "ospf_dump.h"
-#include "ospf_lsa.h"
-#include "ospf_orr.h"
-#include "ospf_route.h"
-#include "ospf_spf.h"
-#include "ospf_te.h"
-
-static void ospf_show_orr_root(struct orr_root *root);
-static void ospf_show_orr(struct ospf *ospf, afi_t afi, safi_t safi);
-static struct orr_root *ospf_orr_root_new(struct ospf *ospf, afi_t afi,
- safi_t safi, struct prefix *p,
- char *group_name)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
-
- if (!ospf->orr_root[afi][safi])
- ospf->orr_root[afi][safi] = list_new();
-
- orr_root_list = ospf->orr_root[afi][safi];
- root = XCALLOC(MTYPE_OSPF_ORR_ROOT, sizeof(struct orr_root));
-
- listnode_add(orr_root_list, root);
-
- root->afi = afi;
- root->safi = safi;
- prefix_copy(&root->prefix, p);
- IPV4_ADDR_COPY(&root->router_id, &p->u.prefix4);
- strlcpy(root->group_name, group_name, sizeof(root->group_name));
- root->new_rtrs = NULL;
- root->new_table = NULL;
-
- ospf_orr_debug(
- "%s: For %s %s, ORR Group %s, created ORR Root entry %pFX.",
- __func__, afi2str(afi), safi2str(safi), root->group_name, p);
-
- return root;
-}
-
-static struct orr_root *ospf_orr_root_lookup(struct ospf *ospf, afi_t afi,
- safi_t safi, struct in_addr *rid)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
- struct listnode *node;
-
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root))
- if (IPV4_ADDR_SAME(&root->router_id, rid))
- return root;
-
- ospf_orr_debug("%s: For %s %s, ORR Root '%pI4' not found.", __func__,
- afi2str(afi), safi2str(safi), rid);
-
- return NULL;
-}
-
-static struct orr_root *ospf_orr_root_lookup_by_adv_rid(struct ospf *ospf,
- afi_t afi, safi_t safi,
- struct in_addr *rid)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
- struct listnode *node;
-
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root))
- if (IPV4_ADDR_SAME(&root->adv_router, rid))
- return root;
-
- return NULL;
-}
-
-/*
- * Lookup each area's LSDB if is there is any opaque area LSA received and
- * update the root database with the advertising router.
- */
-static struct ospf_lsa *
-ospf_orr_lookup_opaque_area_lsa_by_id(struct in_addr rid)
-{
- struct ospf_lsa *lsa = NULL;
- struct ospf_area *area = NULL;
- struct ospf *ospf = NULL;
- struct listnode *node = NULL, *nnode = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return NULL;
-
- /* Lookup for Opaque area LSA in each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- lsa = ospf_lsa_lookup_by_mpls_te_rid(area, OSPF_OPAQUE_AREA_LSA,
- rid);
- if (!lsa)
- continue;
- ospf_orr_debug(
- "%s: Opaque Area LSA found in area %pI4 for %pI4",
- __func__, &area->area_id, &rid);
- return lsa;
- }
- return NULL;
-}
-
-/*
- * Lookup each area's LSDB if is there is any opaque area LSA received and
- * update the root database with the advertising router.
- */
-static struct ospf_lsa *ospf_orr_lookup_router_lsa_by_id(struct in_addr rid)
-{
- struct ospf_lsa *lsa = NULL;
- struct ospf_area *area = NULL;
- struct ospf *ospf = NULL;
- struct listnode *node = NULL, *nnode = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return NULL;
-
- /* Lookup for Router LSA in each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- lsa = ospf_lsa_lookup_by_adv_rid(area, OSPF_ROUTER_LSA, rid);
- if (!lsa)
- continue;
- ospf_orr_debug("%s: Router LSA found in area %pI4 for %pI4",
- __func__, &area->area_id, &rid);
- return lsa;
- }
- return NULL;
-}
-
-/*
- * BGP-IGP IGP metric msg between BGP and IGP
- */
-int ospf_orr_igp_metric_register(struct orr_igp_metric_reg msg)
-{
- afi_t afi;
- safi_t safi;
- struct ospf *ospf = NULL;
- struct ospf_lsa *lsa = NULL;
- struct orr_root *root = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return -1;
-
- if (msg.proto != ZEBRA_ROUTE_BGP)
- return -1;
-
- afi = family2afi(msg.prefix.family);
- safi = msg.safi;
-
- ospf_orr_debug(
- "%s: Received IGP metric %s message from BGP for ORR Group %s from location %pFX",
- __func__, msg.reg ? "Register" : "Unregister", msg.group_name,
- &msg.prefix);
-
- /* Get ORR Root entry for the given address-family */
- root = ospf_orr_root_lookup(ospf, afi, safi, &msg.prefix.u.prefix4);
-
- /* Should not hit this condition */
- if ((root && msg.reg) || (!root && !msg.reg))
- return -1;
-
- /* Create ORR Root entry and calculate SPF from root */
- if (!root) {
- root = ospf_orr_root_new(ospf, afi, safi, &msg.prefix,
- msg.group_name);
- if (!root) {
- ospf_orr_debug(
- "%s: For %s %s, Failed to create ORR Root entry %pFX.",
- __func__, afi2str(afi), safi2str(safi),
- &msg.prefix);
- return -1;
- }
- ospf->orr_spf_request++;
-
- lsa = ospf_orr_lookup_opaque_area_lsa_by_id(root->router_id);
- if (!lsa || !lsa->data)
- return -1;
-
- IPV4_ADDR_COPY(&root->adv_router, &lsa->data->adv_router);
-
- /* Lookup LSDB for Router LSA */
- if (!root->router_lsa_rcvd) {
- lsa = ospf_orr_lookup_router_lsa_by_id(
- root->adv_router);
- if (!lsa || !lsa->data)
- return -1;
- root->router_lsa_rcvd = lsa;
- }
-
- /* Compute SPF for all root nodes */
- ospf_orr_spf_calculate_schedule(ospf);
- }
- /* Delete ORR Root entry. SPF calculation not required. */
- else {
- listnode_delete(ospf->orr_root[afi][safi], root);
- XFREE(MTYPE_OSPF_ORR_ROOT, root);
-
- /* If last node is deleted in the list */
- if (!ospf->orr_root[afi][safi]->count)
- list_delete(&ospf->orr_root[afi][safi]);
-
- ospf->orr_spf_request--;
- }
-
- if (IS_DEBUG_OSPF_ORR)
- ospf_show_orr(ospf, afi, safi);
-
- return 0;
-}
-
-void ospf_orr_igp_metric_send_update_add(struct orr_root *root,
- unsigned short instance)
-{
- int ret;
- uint8_t count = 0;
- struct route_node *rn;
- struct ospf_route *or;
- struct orr_igp_metric_info msg;
-
- memset(&msg, 0, sizeof(msg));
- msg.proto = ZEBRA_ROUTE_OSPF;
- msg.safi = root->safi;
- msg.instId = instance;
- msg.add = true;
- prefix_copy(&msg.root, &root->prefix);
-
- /* Update prefix table from ORR Route table */
- for (rn = route_top(root->new_table); rn; rn = route_next(rn)) {
- or = rn->info;
- if (!or)
- continue;
-
- if (or->type != OSPF_DESTINATION_NETWORK &&
- or->type != OSPF_DESTINATION_DISCARD)
- continue;
-
- if (ospf_route_match_same(root->old_table,
- (struct prefix_ipv4 *)&rn->p, or))
- continue;
-
- if (count < ORR_MAX_PREFIX) {
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- } else {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient,
- ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug(
- "%s: Failed to send message to BGP.",
- __func__);
- count = 0;
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- }
- }
- if (count > 0 && count <= ORR_MAX_PREFIX) {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient, ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug("%s: Failed to send message to BGP.",
- __func__);
- }
-}
-
-void ospf_orr_igp_metric_send_update_delete(struct orr_root *root,
- unsigned short instance)
-{
- int ret;
- uint8_t count = 0;
- struct route_node *rn;
- struct ospf_route *or;
- struct orr_igp_metric_info msg;
-
- if (!root->old_table)
- return;
-
- memset(&msg, 0, sizeof(msg));
- msg.proto = ZEBRA_ROUTE_OSPF;
- msg.instId = instance;
- msg.safi = root->safi;
- msg.add = false;
- prefix_copy(&msg.root, &root->prefix);
-
- /* Update prefix table from ORR Route table */
- for (rn = route_top(root->old_table); rn; rn = route_next(rn)) {
- or = rn->info;
- if (!or)
- continue;
-
- if (or->path_type != OSPF_PATH_INTRA_AREA &&
- or->path_type != OSPF_PATH_INTER_AREA)
- continue;
-
- if (or->type != OSPF_DESTINATION_NETWORK &&
- or->type != OSPF_DESTINATION_DISCARD)
- continue;
-
- if (ospf_route_exist_new_table(root->new_table,
- (struct prefix_ipv4 *)&rn->p))
- continue;
-
- if (count < ORR_MAX_PREFIX) {
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- } else {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient,
- ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug(
- "%s: Failed to send message to BGP.",
- __func__);
- count = 0;
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- }
- }
- if (count > 0 && count <= ORR_MAX_PREFIX) {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient, ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug("%s: Failed to send message to BGP.",
- __func__);
- }
-}
-
-static void ospf_show_orr_root(struct orr_root *root)
-{
- if (!root)
- return;
-
- ospf_orr_debug("%s: Address Family: %s %s", __func__,
- afi2str(root->afi), safi2str(root->safi));
- ospf_orr_debug("%s: ORR Group: %s", __func__, root->group_name);
- ospf_orr_debug("%s: Router-Address: %pI4:", __func__, &root->router_id);
- ospf_orr_debug("%s: Advertising Router: %pI4:", __func__,
- &root->adv_router);
-}
-
-static void ospf_show_orr(struct ospf *ospf, afi_t afi, safi_t safi)
-{
- struct listnode *node = NULL;
- struct orr_root *orr_root = NULL;
- struct list *orr_root_list = NULL;
-
- FOREACH_AFI_SAFI (afi, safi) {
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, orr_root))
- ospf_show_orr_root(orr_root);
- }
-}
-
-void ospf_orr_root_table_update(struct ospf_lsa *lsa, bool add)
-{
- afi_t afi;
- safi_t safi;
- struct lsa_header *lsah = lsa->data;
- uint32_t lsid = ntohl(lsah->id.s_addr);
- uint8_t opaque_type = GET_OPAQUE_TYPE(lsid);
- uint32_t opaque_id = GET_OPAQUE_ID(lsid);
- struct tlv_header *tlvh = TLV_HDR_TOP(lsah);
- struct te_tlv_router_addr *router_addr = NULL;
- struct orr_root *root = NULL;
- struct ospf *ospf = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return;
-
- if (opaque_type != OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA)
- return;
-
- if (!tlvh || (ntohs(tlvh->type) != TE_TLV_ROUTER_ADDR) ||
- (ntohs(tlvh->length) != TE_LINK_SUBTLV_DEF_SIZE))
- return;
-
- router_addr = (struct te_tlv_router_addr *)tlvh;
- if (IS_DEBUG_OSPF_ORR) {
- zlog_debug("[OSPF-ORR] %s: Opaque-area LSA %s LSDB", __func__,
- add ? "added to" : "deleted from");
- zlog_debug("[OSPF-ORR] %s: Opaque-Type %u (%s)", __func__,
- opaque_type, "Traffic Engineering LSA");
- zlog_debug("[OSPF-ORR] %s: Opaque-ID 0x%x", __func__,
- opaque_id);
- zlog_debug("[OSPF-ORR] %s: Opaque-Info: %u octets of data%s",
- __func__, ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE,
- VALID_OPAQUE_INFO_LEN(lsah) ? ""
- : "(Invalid length?)");
- zlog_debug("[OSPF-ORR] %s: Router-Address: %pI4", __func__,
- &router_addr->value);
- zlog_debug("[OSPF-ORR] %s: Advertising Router: %pI4", __func__,
- &lsa->data->adv_router);
- }
- /*
- * When Opaque LSA is added or removed from LSDB check if there is any
- * change in MPLS-TE Router address and Advertising router address and
- * update the table accordingly if there is no change in the mapping
- * ignore update
- *
- * Get ORR Root entry for the given address-family
- */
- FOREACH_AFI_SAFI (afi, safi) {
- root = ospf_orr_root_lookup(ospf, afi, safi,
- &router_addr->value);
- if (root) {
- IPV4_ADDR_COPY(&root->adv_router,
- &lsa->data->adv_router);
- if (IS_DEBUG_OSPF_ORR)
- ospf_show_orr(ospf, afi, safi);
- break;
- }
- }
-}
-
-void ospf_orr_root_update_rcvd_lsa(struct ospf_lsa *lsa)
-{
- afi_t afi;
- safi_t safi;
- struct orr_root *root = NULL;
-
- if (!lsa || !lsa->area || !lsa->area->ospf)
- return;
-
- FOREACH_AFI_SAFI (afi, safi) {
- root = ospf_orr_root_lookup_by_adv_rid(
- lsa->area->ospf, afi, safi, &lsa->data->adv_router);
- if (root) {
- SET_FLAG(lsa->flags, OSPF_LSA_ORR);
- ospf_refresher_register_lsa(lsa->area->ospf, lsa);
- root->router_lsa_rcvd = lsa;
- }
-
- ospf_orr_debug("%s: Received LSA[Type%d:%pI4]", __func__,
- lsa->data->type, &lsa->data->adv_router);
-
- /* Compute SPF for all root nodes */
- ospf_orr_spf_calculate_schedule(lsa->area->ospf);
- return;
- }
-}
-
-/* Do not Install routes to root table. Just update table ponters */
-void ospf_orr_route_install(struct orr_root *root, struct route_table *rt,
- unsigned short instance)
-{
- /*
- * rt contains new routing table, new_table contains an old one.
- * updating pointers
- */
- if (root->old_table)
- ospf_route_table_free(root->old_table);
-
- root->old_table = root->new_table;
- root->new_table = rt;
-
- /* Send update to BGP to delete old routes. */
- ospf_orr_igp_metric_send_update_delete(root, instance);
-
- /* REVISIT: Skipping external route table for now */
-
- /* Send update to BGP to add new routes. */
- ospf_orr_igp_metric_send_update_add(root, instance);
-}
-
-void ospf_orr_spf_calculate_schedule(struct ospf *ospf)
-{
- /* OSPF instance does not exist. */
- if (ospf == NULL)
- return;
-
- /* No roots nodes rgistered for rSPF */
- if (!ospf->orr_spf_request)
- return;
-
- /* ORR SPF calculation timer is already scheduled. */
- if (ospf->t_orr_calc) {
- ospf_orr_debug(
- "SPF: calculation timer is already scheduled: %p",
- (void *)ospf->t_orr_calc);
- return;
- }
-
- ospf->t_orr_calc = NULL;
-
- ospf_orr_debug("%s: SPF: calculation timer scheduled", __func__);
-
- thread_add_timer(master, ospf_orr_spf_calculate_schedule_worker, ospf,
- OSPF_ORR_CALC_INTERVAL, &ospf->t_orr_calc);
-}
-
-void ospf_orr_spf_calculate_area(struct ospf *ospf, struct ospf_area *area,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd)
-{
- ospf_spf_calculate(area, lsa_rcvd, new_table, all_rtrs, new_rtrs, false,
- true);
-}
-
-void ospf_orr_spf_calculate_areas(struct ospf *ospf,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd)
-{
- struct ospf_area *area;
- struct listnode *node, *nnode;
-
- /* Calculate SPF for each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- /*
- * Do backbone last, so as to first discover intra-area paths
- * for any back-bone virtual-links
- */
- if (ospf->backbone && ospf->backbone == area)
- continue;
-
- ospf_orr_spf_calculate_area(ospf, area, new_table, all_rtrs,
- new_rtrs, lsa_rcvd);
- }
-
- /* SPF for backbone, if required */
- if (ospf->backbone)
- ospf_orr_spf_calculate_area(ospf, ospf->backbone, new_table,
- all_rtrs, new_rtrs, lsa_rcvd);
-}
diff --git a/ospfd/ospf_orr.h b/ospfd/ospf_orr.h
deleted file mode 100644
index d0a6f6e790..0000000000
--- a/ospfd/ospf_orr.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * OSPF BGP-IGP IGP metric update handling routines
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ZEBRA_OSPF_ORR_H
-#define _ZEBRA_OSPF_ORR_H
-
-#define BGP_OSPF_LSINFINITY 65535
-#define OSPF_ORR_CALC_INTERVAL 1
-
-/* Macro to log debug message */
-#define ospf_orr_debug(...) \
- do { \
- if (IS_DEBUG_OSPF_ORR) \
- zlog_debug("[OSPF-ORR] "__VA_ARGS__); \
- } while (0)
-
-extern struct zclient *zclient;
-
-extern int ospf_orr_igp_metric_register(struct orr_igp_metric_reg orr_reg);
-extern void ospf_orr_igp_metric_send_update_add(struct orr_root *root,
- unsigned short instance);
-extern void ospf_orr_igp_metric_send_update_delete(struct orr_root *root,
- unsigned short instance);
-extern void ospf_orr_root_table_update(struct ospf_lsa *lsa, bool add);
-extern void ospf_orr_root_update_rcvd_lsa(struct ospf_lsa *lsa);
-extern void ospf_orr_route_install(struct orr_root *root,
- struct route_table *rt,
- unsigned short instance);
-extern void ospf_orr_spf_calculate_schedule(struct ospf *ospf);
-extern void ospf_orr_spf_calculate_area(struct ospf *ospf,
- struct ospf_area *area,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd);
-extern void ospf_orr_spf_calculate_areas(struct ospf *ospf,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd);
-#endif /* _ZEBRA_OSPF_ORR_H */
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index 26f593f089..6360d8ec60 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -151,8 +151,8 @@ void ospf_route_table_free(struct route_table *rt)
otherwise return 0. Since the ZEBRA-RIB does an implicit
withdraw, it is not necessary to send a delete, an add later
will act like an implicit delete. */
-int ospf_route_exist_new_table(struct route_table *rt,
- struct prefix_ipv4 *prefix)
+static int ospf_route_exist_new_table(struct route_table *rt,
+ struct prefix_ipv4 *prefix)
{
struct route_node *rn;
diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h
index e7e2b651c5..fa9478fced 100644
--- a/ospfd/ospf_route.h
+++ b/ospfd/ospf_route.h
@@ -172,6 +172,5 @@ extern void ospf_delete_discard_route(struct ospf *, struct route_table *,
struct prefix_ipv4 *);
extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *,
struct ospf_route *);
-extern int ospf_route_exist_new_table(struct route_table *rt,
- struct prefix_ipv4 *prefix);
+
#endif /* _ZEBRA_OSPF_ROUTE_H */
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 58fcbfa4a9..48499938ca 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -53,8 +53,6 @@
#include "ospfd/ospf_apiserver.h"
#endif
-#include "ospfd/ospf_orr.h"
-
/* Variables to ensure a SPF scheduled log message is printed only once */
static unsigned int spf_reason_flags = 0;
@@ -1857,36 +1855,6 @@ void ospf_spf_calculate_areas(struct ospf *ospf, struct route_table *new_table,
all_rtrs, new_rtrs);
}
-/* Print Reason for SPF calculation */
-static void ospf_spf_calculation_reason2str(char *rbuf, size_t len)
-{
- rbuf[0] = '\0';
- if (spf_reason_flags) {
- if (spf_reason_flags & (1 << SPF_FLAG_ROUTER_LSA_INSTALL))
- strlcat(rbuf, "R, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_NETWORK_LSA_INSTALL))
- strlcat(rbuf, "N, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_SUMMARY_LSA_INSTALL))
- strlcat(rbuf, "S, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL))
- strlcat(rbuf, "AS, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ABR_STATUS_CHANGE))
- strlcat(rbuf, "ABR, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ASBR_STATUS_CHANGE))
- strlcat(rbuf, "ASBR, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
- strlcat(rbuf, "M, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ORR_ROOT_CHANGE))
- strlcat(rbuf, "ORR, ", len);
-
- size_t rbuflen = strlen(rbuf);
- if (rbuflen >= 2)
- rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
- else
- rbuf[0] = '\0';
- }
-}
-
/* Worker for SPF calculation scheduler. */
static void ospf_spf_calculate_schedule_worker(struct thread *thread)
{
@@ -1942,8 +1910,6 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
ospf_ase_calculate_schedule(ospf);
ospf_ase_calculate_timer_add(ospf);
- ospf_orr_spf_calculate_schedule(ospf);
-
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"%s: ospf install new route, vrf %s id %u new_table count %lu",
@@ -1967,6 +1933,7 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
#ifdef SUPPORT_OSPF_API
ospf_apiserver_notify_reachable(ospf->oall_rtrs, ospf->all_rtrs);
#endif
+
/* Free old ABR/ASBR routing table */
if (ospf->old_rtrs) {
ospf_rtrs_free(ospf->old_rtrs);
@@ -1992,7 +1959,31 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
total_spf_time =
monotime_since(&spf_start_time, &ospf->ts_spf_duration);
- ospf_spf_calculation_reason2str(rbuf, sizeof(rbuf));
+ rbuf[0] = '\0';
+ if (spf_reason_flags) {
+ if (spf_reason_flags & (1 << SPF_FLAG_ROUTER_LSA_INSTALL))
+ strlcat(rbuf, "R, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_NETWORK_LSA_INSTALL))
+ strlcat(rbuf, "N, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_SUMMARY_LSA_INSTALL))
+ strlcat(rbuf, "S, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL))
+ strlcat(rbuf, "AS, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ABR_STATUS_CHANGE))
+ strlcat(rbuf, "ABR, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ASBR_STATUS_CHANGE))
+ strlcat(rbuf, "ASBR, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
+ strlcat(rbuf, "M, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_GR_FINISH))
+ strlcat(rbuf, "GR, ", sizeof(rbuf));
+
+ size_t rbuflen = strlen(rbuf);
+ if (rbuflen >= 2)
+ rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
+ else
+ rbuf[0] = '\0';
+ }
if (IS_DEBUG_OSPF_EVENT) {
zlog_info("SPF Processing Time(usecs): %ld", total_spf_time);
@@ -2009,145 +2000,6 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
ospf_clear_spf_reason_flags();
}
-/* Worker for ORR SPF calculation scheduler. */
-void ospf_orr_spf_calculate_schedule_worker(struct thread *thread)
-{
- afi_t afi;
- safi_t safi;
- struct ospf *ospf = THREAD_ARG(thread);
- struct route_table *new_table, *new_rtrs;
- struct route_table *all_rtrs = NULL;
- struct timeval start_time, spf_start_time;
- unsigned long ia_time, rt_time;
- unsigned long abr_time, total_spf_time, spf_time;
- struct listnode *rnode;
- struct list *orr_root_list;
- struct orr_root *root;
- char rbuf[32]; /* reason_buf */
-
- ospf_orr_debug("%s: SPF: Timer (SPF calculation expire)", __func__);
-
- ospf->t_orr_calc = NULL;
-
- /* Execute SPF for each ORR Root node */
- FOREACH_AFI_SAFI (afi, safi) {
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- continue;
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, rnode, root)) {
- if (!root || !root->router_lsa_rcvd)
- continue;
- ospf_orr_debug(
- "%s: For %s %s, MPLS TE Router address %pI4 advertised by %pI4",
- __func__, afi2str(afi), safi2str(safi),
- &root->router_id, &root->adv_router);
-
- ospf_vl_unapprove(ospf);
-
- /*
- * Execute SPF for each area including backbone, see RFC
- * 2328 16.1.
- */
- monotime(&spf_start_time);
- new_table = route_table_init(); /* routing table */
- new_rtrs =
- route_table_init(); /* ABR/ASBR routing table */
-
- /*
- * If we have opaque enabled then track all router
- * reachability
- */
- if (CHECK_FLAG(ospf->opaque,
- OPAQUE_OPERATION_READY_BIT))
- all_rtrs = route_table_init();
- ospf_orr_spf_calculate_areas(ospf, new_table, all_rtrs,
- new_rtrs,
- root->router_lsa_rcvd);
-
- spf_time = monotime_since(&spf_start_time, NULL);
-
- ospf_vl_shut_unapproved(ospf);
-
- /* Calculate inter-area routes, see RFC 2328 16.2. */
- monotime(&start_time);
- ospf_ia_routing(ospf, new_table, new_rtrs);
- ia_time = monotime_since(&start_time, NULL);
-
- /*
- * REVISIT :
- * Pruning of unreachable networks, routers skipped.
- */
-
- /* Note: RFC 2328 16.3. is apparently missing. */
- /* Calculate AS external routes, see RFC 2328 16.4.
- * There is a dedicated routing table for external
- * routes which is not handled here directly
- */
- ospf_ase_calculate_schedule(ospf);
- ospf_ase_calculate_timer_add(ospf);
-
- ospf_orr_debug(
- "%s: ospf install new route, vrf %s id %u new_table count %lu",
- __func__, ospf_vrf_id_to_name(ospf->vrf_id),
- ospf->vrf_id, new_table->count);
-
- /* Update routing table. */
- monotime(&start_time);
- ospf_orr_route_install(root, new_table, ospf->instance);
- rt_time = monotime_since(&start_time, NULL);
-
- /*
- * REVISIT :
- * Freeing up and Updating old all routers routing table
- * skipped.
- */
-
- /* Free old ABR/ASBR routing table */
- if (root->old_rtrs)
- /* ospf_route_delete (ospf->old_rtrs); */
- ospf_rtrs_free(root->old_rtrs);
-
- /* Update ABR/ASBR routing table */
- root->old_rtrs = root->new_rtrs;
- root->new_rtrs = new_rtrs;
-
- /*
- * ABRs may require additional changes, see RFC
- * 2328 16.7.
- */
- monotime(&start_time);
- if (IS_OSPF_ABR(ospf)) {
- if (ospf->anyNSSA)
- ospf_abr_nssa_check_status(ospf);
- ospf_abr_task(ospf);
- }
- abr_time = monotime_since(&start_time, NULL);
-
- /* Schedule Segment Routing update */
- ospf_sr_update_task(ospf);
-
- total_spf_time = monotime_since(&spf_start_time,
- &ospf->ts_spf_duration);
-
- ospf_spf_calculation_reason2str(rbuf, sizeof(rbuf));
-
- if (IS_DEBUG_OSPF_ORR) {
- zlog_info("SPF Processing Time(usecs): %ld",
- total_spf_time);
- zlog_info(" SPF Time: %ld",
- spf_time);
- zlog_info(" InterArea: %ld", ia_time);
- zlog_info(" RouteInstall: %ld", rt_time);
- if (IS_OSPF_ABR(ospf))
- zlog_info(
- " ABR: %ld (%d areas)",
- abr_time, ospf->areas->count);
- zlog_info("Reason(s) for SPF: %s", rbuf);
- }
- } /* ALL_LIST_ELEMENTS_RO() */
- } /* FOREACH_AFI_SAFI() */
-}
-
/*
* Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer
* for SPF calc.
@@ -2206,7 +2058,6 @@ void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason)
zlog_debug("SPF: calculation timer delay = %ld msec", delay);
ospf->t_spf_calc = NULL;
-
thread_add_timer_msec(master, ospf_spf_calculate_schedule_worker, ospf,
delay, &ospf->t_spf_calc);
}
diff --git a/ospfd/ospf_spf.h b/ospfd/ospf_spf.h
index 2578051c2c..834bfd0bb0 100644
--- a/ospfd/ospf_spf.h
+++ b/ospfd/ospf_spf.h
@@ -70,10 +70,8 @@ typedef enum {
SPF_FLAG_ASBR_STATUS_CHANGE,
SPF_FLAG_CONFIG_CHANGE,
SPF_FLAG_GR_FINISH,
- SPF_FLAG_ORR_ROOT_CHANGE,
} ospf_spf_reason_t;
-extern unsigned int ospf_get_spf_reason_flags(void);
extern void ospf_spf_calculate_schedule(struct ospf *, ospf_spf_reason_t);
extern void ospf_spf_calculate(struct ospf_area *area,
struct ospf_lsa *root_lsa,
@@ -105,6 +103,5 @@ extern int vertex_parent_cmp(void *aa, void *bb);
extern void ospf_spf_print(struct vty *vty, struct vertex *v, int i);
extern void ospf_restart_spf(struct ospf *ospf);
-extern void ospf_orr_spf_calculate_schedule_worker(struct thread *thread);
/* void ospf_spf_calculate_timer_add (); */
#endif /* _QUAGGA_OSPF_SPF_H */
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 828a5cb1ee..0b0b9d81ee 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -55,7 +55,6 @@
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_bfd.h"
#include "ospfd/ospf_ldp_sync.h"
-#include "ospfd/ospf_orr.h"
FRR_CFG_DEFAULT_BOOL(OSPF_LOG_ADJACENCY_CHANGES,
@@ -7315,16 +7314,26 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty,
type = OSPF_OPAQUE_AREA_LSA;
else if (strncmp(argv[arg_base + idx_type]->text, "opaque-as", 9) == 0)
type = OSPF_OPAQUE_AS_LSA;
- else
+ else {
+ if (uj) {
+ if (use_vrf)
+ json_object_free(json_vrf);
+ }
return CMD_WARNING;
+ }
/* `show ip ospf database LSA adv-router ADV_ROUTER'. */
if (strncmp(argv[arg_base + 5]->text, "s", 1) == 0)
adv_router = ospf->router_id;
else {
ret = inet_aton(argv[arg_base + 6]->arg, &adv_router);
- if (!ret)
+ if (!ret) {
+ if (uj) {
+ if (use_vrf)
+ json_object_free(json_vrf);
+ }
return CMD_WARNING;
+ }
}
show_lsa_detail_adv_router(vty, ospf, type, &adv_router, json_vrf);
@@ -7388,9 +7397,12 @@ DEFUN (show_ip_ospf_database_type_adv_router,
} else {
ospf = ospf_lookup_by_inst_name(inst, vrf_name);
if ((ospf == NULL) || !ospf->oi_running) {
- vty_out(vty,
- "%% OSPF is not enabled in vrf %s\n",
- vrf_name);
+ if (uj)
+ vty_json(vty, json);
+ else
+ vty_out(vty,
+ "%% OSPF is not enabled in vrf %s\n",
+ vrf_name);
return CMD_SUCCESS;
}
@@ -7401,7 +7413,11 @@ DEFUN (show_ip_ospf_database_type_adv_router,
/* Display default ospf (instance 0) info */
ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if (ospf == NULL || !ospf->oi_running) {
- vty_out(vty, "%% OSPF is not enabled on vrf default\n");
+ if (uj)
+ vty_json(vty, json);
+ else
+ vty_out(vty,
+ "%% OSPF is not enabled on vrf default\n");
return CMD_SUCCESS;
}
@@ -10979,131 +10995,6 @@ static void show_ip_ospf_route_external(struct vty *vty, struct ospf *ospf,
vty_out(vty, "\n");
}
-static void show_ip_ospf_route_orr_root(struct vty *vty, struct ospf *ospf,
- struct orr_root *root, bool use_vrf)
-{
- if (ospf->instance)
- vty_out(vty, "\nOSPF Instance: %d\n", ospf->instance);
-
- ospf_show_vrf_name(ospf, vty, NULL, use_vrf);
-
- vty_out(vty, "ORR Group: %s\n", root->group_name);
- vty_out(vty, "Active Root: %pI4\n\n", &root->router_id);
- vty_out(vty, "SPF calculated from %pI4\n\n", &root->router_id);
-
- if (root->new_table)
- show_ip_ospf_route_network(vty, ospf, root->new_table, NULL);
-
- if (root->new_rtrs)
- show_ip_ospf_route_router(vty, ospf, root->new_rtrs, NULL);
-
- vty_out(vty, "\n");
-}
-
-static void show_ip_ospf_route_orr_common(struct vty *vty, struct ospf *ospf,
- const char *orr_group, bool use_vrf)
-{
- afi_t afi;
- safi_t safi;
- struct orr_root *root = NULL;
- struct listnode *node = NULL;
- struct list *orr_root_list = NULL;
-
- if (!ospf->orr_spf_request)
- return;
-
- FOREACH_AFI_SAFI (afi, safi) {
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- continue;
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root)) {
- if (orr_group) {
- if (!strmatch(root->group_name, orr_group))
- continue;
- show_ip_ospf_route_orr_root(vty, ospf, root,
- use_vrf);
- } else
- show_ip_ospf_route_orr_root(vty, ospf, root,
- use_vrf);
- }
- }
-}
-
-DEFPY (show_ip_ospf_instance_route_orr,
- show_ip_ospf_instance_route_orr_cmd,
- "show ip ospf (1-65535)$instance route orr [WORD$orr_group]",
- SHOW_STR
- IP_STR
- OSPF_STR
- "Instance ID\n"
- "OSPF routing table\n"
- "Optimal Route Reflection\n"
- "ORR Group name\n")
-{
- struct ospf *ospf;
-
- if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- ospf = ospf_lookup_instance(instance);
- if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- show_ip_ospf_route_orr_common(vty, ospf, orr_group, false);
-
- return CMD_SUCCESS;
-}
-
-DEFPY (show_ip_ospf_route_orr,
- show_ip_ospf_route_orr_cmd,
- "show ip ospf [vrf <NAME$vrf_name|all$all_vrf>] route orr [WORD$orr_group]",
- SHOW_STR
- IP_STR
- OSPF_STR
- VRF_CMD_HELP_STR
- "All VRFs\n"
- "OSPF routing table\n"
- "Optimal Route Reflection\n"
- "ORR Group name\n")
-{
- struct ospf *ospf = NULL;
- struct listnode *node = NULL;
- int ret = CMD_SUCCESS;
- int inst = 0;
- bool use_vrf = vrf_name || all_vrf;
-
- if (all_vrf) {
- bool ospf_output = false;
-
- for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
- if (!ospf->oi_running)
- continue;
- ospf_output = true;
-
- show_ip_ospf_route_orr_common(vty, ospf, orr_group,
- use_vrf);
- }
- if (!ospf_output)
- vty_out(vty, "%% OSPF is not enabled\n");
- return ret;
- }
-
- if (vrf_name)
- ospf = ospf_lookup_by_inst_name(inst, vrf_name);
- else
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
-
- if (!ospf || !ospf->oi_running) {
- vty_out(vty, "%% OSPF is not enabled in vrf %s\n",
- vrf_name ? vrf_name : "default");
- return CMD_SUCCESS;
- }
-
- show_ip_ospf_route_orr_common(vty, ospf, orr_group, use_vrf);
-
- return ret;
-}
-
static int show_ip_ospf_reachable_routers_common(struct vty *vty,
struct ospf *ospf,
uint8_t use_vrf)
@@ -11243,7 +11134,8 @@ static int show_ip_ospf_border_routers_common(struct vty *vty,
vty_out(vty, "No OSPF routing information exist\n");
else {
json_object_free(json_router);
- json_object_free(json_vrf);
+ if (use_vrf)
+ json_object_free(json_vrf);
}
return CMD_SUCCESS;
}
@@ -11399,7 +11291,12 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf);
if (ospf->new_table == NULL) {
- vty_out(vty, "No OSPF routing information exist\n");
+ if (json) {
+ if (use_vrf)
+ json_object_free(json_vrf);
+ } else {
+ vty_out(vty, "No OSPF routing information exist\n");
+ }
return CMD_SUCCESS;
}
@@ -12871,13 +12768,11 @@ void ospf_vty_show_init(void)
install_element(VIEW_NODE, &show_ip_ospf_route_cmd);
install_element(VIEW_NODE, &show_ip_ospf_border_routers_cmd);
install_element(VIEW_NODE, &show_ip_ospf_reachable_routers_cmd);
- install_element(VIEW_NODE, &show_ip_ospf_route_orr_cmd);
install_element(VIEW_NODE, &show_ip_ospf_instance_route_cmd);
install_element(VIEW_NODE, &show_ip_ospf_instance_border_routers_cmd);
install_element(VIEW_NODE,
&show_ip_ospf_instance_reachable_routers_cmd);
- install_element(VIEW_NODE, &show_ip_ospf_instance_route_orr_cmd);
/* "show ip ospf vrfs" commands. */
install_element(VIEW_NODE, &show_ip_ospf_vrfs_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 4615864244..1754512b5b 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -53,7 +53,6 @@
#include "ospfd/ospf_te.h"
#include "ospfd/ospf_sr.h"
#include "ospfd/ospf_ldp_sync.h"
-#include "ospfd/ospf_orr.h"
DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table");
DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute");
@@ -2082,7 +2081,6 @@ static void ospf_zebra_connected(struct zclient *zclient)
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
zclient_send_reg_requests(zclient, VRF_DEFAULT);
- zclient_register_opaque(zclient, ORR_IGP_METRIC_REGISTER);
}
/*
@@ -2095,7 +2093,6 @@ static int ospf_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
struct ldp_igp_sync_if_state state;
struct ldp_igp_sync_announce announce;
struct zapi_opaque_reg_info dst;
- struct orr_igp_metric_reg orr_reg;
int ret = 0;
s = zclient->ibuf;
@@ -2119,10 +2116,6 @@ static int ospf_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
STREAM_GET(&announce, s, sizeof(announce));
ret = ospf_ldp_sync_announce_update(announce);
break;
- case ORR_IGP_METRIC_REGISTER:
- STREAM_GET(&orr_reg, s, sizeof(orr_reg));
- ret = ospf_orr_igp_metric_register(orr_reg);
- break;
default:
break;
}
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index a5d40ad176..023dc32a7b 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -814,7 +814,6 @@ static void ospf_finish_final(struct ospf *ospf)
THREAD_OFF(ospf->t_write);
THREAD_OFF(ospf->t_spf_calc);
THREAD_OFF(ospf->t_ase_calc);
- THREAD_OFF(ospf->t_orr_calc);
THREAD_OFF(ospf->t_maxage);
THREAD_OFF(ospf->t_maxage_walker);
THREAD_OFF(ospf->t_abr_task);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index c7735136bc..3a43010f85 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -35,8 +35,6 @@
#include "ospf_memory.h"
#include "ospf_dump_api.h"
-#include "orr_msg.h"
-
#define OSPF_VERSION 2
/* VTY port number. */
@@ -263,7 +261,6 @@ struct ospf {
struct thread *t_distribute_update; /* Distirbute list update timer. */
struct thread *t_spf_calc; /* SPF calculation timer. */
struct thread *t_ase_calc; /* ASE calculation timer. */
- struct thread *t_orr_calc; /* ORR calculation timer. */
struct thread
*t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
struct thread *t_sr_update; /* Segment Routing update timer */
@@ -409,10 +406,6 @@ struct ospf {
bool ti_lfa_enabled;
enum protection_type ti_lfa_protection_type;
- /* BGP ORR Root node list */
- uint32_t orr_spf_request;
- struct list *orr_root[AFI_MAX][SAFI_MAX];
-
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(ospf);
@@ -598,9 +591,6 @@ struct ospf_area {
uint32_t act_ints; /* Active interfaces. */
uint32_t full_nbrs; /* Fully adjacent neighbors. */
uint32_t full_vls; /* Fully adjacent virtual neighbors. */
-
- /* BGP-ORR Received LSAs */
- struct ospf_lsa *router_lsa_rcvd;
};
/* OSPF config network structure. */
diff --git a/ospfd/subdir.am b/ospfd/subdir.am
index e45f617dfa..44ee3b0f13 100644
--- a/ospfd/subdir.am
+++ b/ospfd/subdir.am
@@ -42,7 +42,6 @@ ospfd_libfrrospf_a_SOURCES = \
ospfd/ospf_network.c \
ospfd/ospf_nsm.c \
ospfd/ospf_opaque.c \
- ospfd/ospf_orr.c \
ospfd/ospf_packet.c \
ospfd/ospf_ri.c \
ospfd/ospf_route.c \
@@ -96,7 +95,6 @@ noinst_HEADERS += \
ospfd/ospf_memory.h \
ospfd/ospf_neighbor.h \
ospfd/ospf_network.h \
- ospfd/ospf_orr.h \
ospfd/ospf_packet.h \
ospfd/ospf_ri.h \
ospfd/ospf_gr.h \
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 3310009c02..082862709d 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -711,6 +711,8 @@ static void on_ifjoin_prune_pending_timer(struct thread *t)
pim_channel_del_oif(
ch->upstream->channel_oil, ifp,
PIM_OIF_FLAG_PROTO_STAR, __func__);
+ pim_channel_del_oif(ch->upstream->channel_oil, ifp,
+ PIM_OIF_FLAG_PROTO_PIM, __func__);
if (!ch->upstream->channel_oil->installed)
pim_upstream_mroute_add(
ch->upstream->channel_oil,
diff --git a/staticd/static_bfd.c b/staticd/static_bfd.c
new file mode 100644
index 0000000000..fc8b518e11
--- /dev/null
+++ b/staticd/static_bfd.c
@@ -0,0 +1,390 @@
+/*
+ * Static daemon BFD integration.
+ *
+ * Copyright (C) 2020-2022 Network Device Education Foundation, Inc. ("NetDEF")
+ * Rafael Zalamena
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+#include <zebra.h>
+
+#include "lib/bfd.h"
+#include "lib/printfrr.h"
+#include "lib/srcdest_table.h"
+
+#include "staticd/static_routes.h"
+#include "staticd/static_zebra.h"
+#include "staticd/static_debug.h"
+
+#include "lib/openbsd-queue.h"
+
+/*
+ * Next hop BFD monitoring settings.
+ */
+static void static_next_hop_bfd_change(struct static_nexthop *sn,
+ const struct bfd_session_status *bss)
+{
+ switch (bss->state) {
+ case BSS_UNKNOWN:
+ /* FALLTHROUGH: no known state yet. */
+ case BSS_ADMIN_DOWN:
+ /* NOTHING: we or the remote end administratively shutdown. */
+ break;
+ case BSS_DOWN:
+ /* Peer went down, remove this next hop. */
+ DEBUGD(&static_dbg_bfd,
+ "%s: next hop is down, remove it from RIB", __func__);
+ sn->path_down = true;
+ static_zebra_route_add(sn->pn, true);
+ break;
+ case BSS_UP:
+ /* Peer is back up, add this next hop. */
+ DEBUGD(&static_dbg_bfd, "%s: next hop is up, add it to RIB",
+ __func__);
+ sn->path_down = false;
+ static_zebra_route_add(sn->pn, true);
+ break;
+ }
+}
+
+static void static_next_hop_bfd_updatecb(
+ __attribute__((unused)) struct bfd_session_params *bsp,
+ const struct bfd_session_status *bss, void *arg)
+{
+ static_next_hop_bfd_change(arg, bss);
+}
+
+static inline int
+static_next_hop_type_to_family(const struct static_nexthop *sn)
+{
+ switch (sn->type) {
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ case STATIC_IPV4_GATEWAY:
+ case STATIC_IPV6_GATEWAY:
+ if (sn->type == STATIC_IPV4_GATEWAY ||
+ sn->type == STATIC_IPV4_GATEWAY_IFNAME)
+ return AF_INET;
+ else
+ return AF_INET6;
+ break;
+ case STATIC_IFNAME:
+ case STATIC_BLACKHOLE:
+ default:
+ zlog_err("%s: invalid next hop type", __func__);
+ break;
+ }
+
+ return AF_UNSPEC;
+}
+
+void static_next_hop_bfd_monitor_enable(struct static_nexthop *sn,
+ const struct lyd_node *dnode)
+{
+ bool use_interface;
+ bool use_profile;
+ bool use_source;
+ bool onlink;
+ bool mhop;
+ int family;
+ struct ipaddr source;
+
+ use_interface = false;
+ use_source = yang_dnode_exists(dnode, "./source");
+ use_profile = yang_dnode_exists(dnode, "./profile");
+ onlink = yang_dnode_exists(dnode, "../onlink") &&
+ yang_dnode_get_bool(dnode, "../onlink");
+ mhop = yang_dnode_get_bool(dnode, "./multi-hop");
+
+
+ family = static_next_hop_type_to_family(sn);
+ if (family == AF_UNSPEC)
+ return;
+
+ if (sn->type == STATIC_IPV4_GATEWAY_IFNAME ||
+ sn->type == STATIC_IPV6_GATEWAY_IFNAME)
+ use_interface = true;
+
+ /* Reconfigure or allocate new memory. */
+ if (sn->bsp == NULL)
+ sn->bsp = bfd_sess_new(static_next_hop_bfd_updatecb, sn);
+
+ /* Configure the session. */
+ if (use_source)
+ yang_dnode_get_ip(&source, dnode, "./source");
+
+ if (onlink || mhop == false)
+ bfd_sess_set_auto_source(sn->bsp, false);
+ else
+ bfd_sess_set_auto_source(sn->bsp, !use_source);
+
+ /* Configure the session.*/
+ if (family == AF_INET)
+ bfd_sess_set_ipv4_addrs(sn->bsp,
+ use_source ? &source.ip._v4_addr : NULL,
+ &sn->addr.ipv4);
+ else if (family == AF_INET6)
+ bfd_sess_set_ipv6_addrs(sn->bsp,
+ use_source ? &source.ip._v6_addr : NULL,
+ &sn->addr.ipv6);
+
+ bfd_sess_set_interface(sn->bsp, use_interface ? sn->ifname : NULL);
+
+ bfd_sess_set_profile(sn->bsp, use_profile ? yang_dnode_get_string(
+ dnode, "./profile")
+ : NULL);
+
+ bfd_sess_set_hop_count(sn->bsp, (onlink || mhop == false) ? 1 : 254);
+
+ /* Install or update the session. */
+ bfd_sess_install(sn->bsp);
+
+ /* Update current path status. */
+ sn->path_down = (bfd_sess_status(sn->bsp) != BSS_UP);
+}
+
+void static_next_hop_bfd_monitor_disable(struct static_nexthop *sn)
+{
+ bfd_sess_free(&sn->bsp);
+
+ /* Reset path status. */
+ sn->path_down = false;
+}
+
+void static_next_hop_bfd_source(struct static_nexthop *sn,
+ const struct ipaddr *source)
+{
+ int family;
+
+ if (sn->bsp == NULL)
+ return;
+
+ family = static_next_hop_type_to_family(sn);
+ if (family == AF_UNSPEC)
+ return;
+
+ bfd_sess_set_auto_source(sn->bsp, false);
+ if (family == AF_INET)
+ bfd_sess_set_ipv4_addrs(sn->bsp, &source->ip._v4_addr,
+ &sn->addr.ipv4);
+ else if (family == AF_INET6)
+ bfd_sess_set_ipv6_addrs(sn->bsp, &source->ip._v6_addr,
+ &sn->addr.ipv6);
+
+ bfd_sess_install(sn->bsp);
+}
+
+void static_next_hop_bfd_auto_source(struct static_nexthop *sn)
+{
+ if (sn->bsp == NULL)
+ return;
+
+ bfd_sess_set_auto_source(sn->bsp, true);
+ bfd_sess_install(sn->bsp);
+}
+
+void static_next_hop_bfd_multi_hop(struct static_nexthop *sn, bool mhop)
+{
+ if (sn->bsp == NULL)
+ return;
+
+ bfd_sess_set_hop_count(sn->bsp, mhop ? 254 : 1);
+ bfd_sess_install(sn->bsp);
+}
+
+void static_next_hop_bfd_profile(struct static_nexthop *sn, const char *name)
+{
+ if (sn->bsp == NULL)
+ return;
+
+ bfd_sess_set_profile(sn->bsp, name);
+ bfd_sess_install(sn->bsp);
+}
+
+void static_bfd_initialize(struct zclient *zc, struct thread_master *tm)
+{
+ /* Initialize BFD integration library. */
+ bfd_protocol_integration_init(zc, tm);
+}
+
+/*
+ * Display functions
+ */
+static void static_bfd_show_nexthop_json(struct vty *vty,
+ struct json_object *jo,
+ const struct static_nexthop *sn)
+{
+ const struct prefix *dst_p, *src_p;
+ struct json_object *jo_nh;
+
+ jo_nh = json_object_new_object();
+
+ srcdest_rnode_prefixes(sn->rn, &dst_p, &src_p);
+ if (src_p)
+ json_object_string_addf(jo_nh, "from", "%pFX", src_p);
+
+ json_object_string_addf(jo_nh, "prefix", "%pFX", dst_p);
+ json_object_string_add(jo_nh, "vrf", sn->nh_vrfname);
+
+ json_object_boolean_add(jo_nh, "installed", !sn->path_down);
+
+ json_object_array_add(jo, jo_nh);
+}
+
+static void static_bfd_show_path_json(struct vty *vty, struct json_object *jo,
+ struct route_table *rt)
+{
+ struct route_node *rn;
+
+ for (rn = route_top(rt); rn; rn = srcdest_route_next(rn)) {
+ struct static_route_info *si = static_route_info_from_rnode(rn);
+ struct static_path *sp;
+
+ if (si == NULL)
+ continue;
+
+ frr_each (static_path_list, &si->path_list, sp) {
+ struct static_nexthop *sn;
+
+ frr_each (static_nexthop_list, &sp->nexthop_list, sn) {
+ /* Skip non configured BFD sessions. */
+ if (sn->bsp == NULL)
+ continue;
+
+ static_bfd_show_nexthop_json(vty, jo, sn);
+ }
+ }
+ }
+}
+
+static void static_bfd_show_json(struct vty *vty)
+{
+ struct json_object *jo, *jo_path, *jo_afi_safi;
+ struct vrf *vrf;
+
+ jo = json_object_new_object();
+ jo_path = json_object_new_object();
+
+ json_object_object_add(jo, "path-list", jo_path);
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ const struct static_vrf *svrf = vrf->info;
+ struct route_table *rt;
+
+ jo_afi_safi = json_object_new_array();
+ json_object_object_add(jo_path, "ipv4-unicast", jo_afi_safi);
+ rt = svrf->stable[AFI_IP][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path_json(vty, jo_afi_safi, rt);
+
+ jo_afi_safi = json_object_new_array();
+ json_object_object_add(jo_path, "ipv4-multicast", jo_afi_safi);
+ rt = svrf->stable[AFI_IP][SAFI_MULTICAST];
+ if (rt)
+ static_bfd_show_path_json(vty, jo_afi_safi, rt);
+
+ jo_afi_safi = json_object_new_array();
+ json_object_object_add(jo_path, "ipv6-unicast", jo_afi_safi);
+ rt = svrf->stable[AFI_IP6][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path_json(vty, jo_afi_safi, rt);
+ }
+
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
+ json_object_free(jo);
+}
+
+static void static_bfd_show_nexthop(struct vty *vty,
+ const struct static_nexthop *sn)
+{
+ vty_out(vty, " %pRN", sn->rn);
+
+ if (sn->bsp == NULL) {
+ vty_out(vty, "\n");
+ return;
+ }
+
+ if (sn->type == STATIC_IPV4_GATEWAY ||
+ sn->type == STATIC_IPV4_GATEWAY_IFNAME)
+ vty_out(vty, " peer %pI4", &sn->addr.ipv4);
+ else if (sn->type == STATIC_IPV6_GATEWAY ||
+ sn->type == STATIC_IPV6_GATEWAY_IFNAME)
+ vty_out(vty, " peer %pI6", &sn->addr.ipv6);
+ else
+ vty_out(vty, " peer unknown");
+
+ vty_out(vty, " (status: %s)\n",
+ sn->path_down ? "uninstalled" : "installed");
+}
+
+static void static_bfd_show_path(struct vty *vty, struct route_table *rt)
+{
+ struct route_node *rn;
+
+ for (rn = route_top(rt); rn; rn = srcdest_route_next(rn)) {
+ struct static_route_info *si = static_route_info_from_rnode(rn);
+ struct static_path *sp;
+
+ if (si == NULL)
+ continue;
+
+ frr_each (static_path_list, &si->path_list, sp) {
+ struct static_nexthop *sn;
+
+ frr_each (static_nexthop_list, &sp->nexthop_list, sn) {
+ /* Skip non configured BFD sessions. */
+ if (sn->bsp == NULL)
+ continue;
+
+ static_bfd_show_nexthop(vty, sn);
+ }
+ }
+ }
+}
+
+void static_bfd_show(struct vty *vty, bool json)
+{
+ struct vrf *vrf;
+
+ if (json) {
+ static_bfd_show_json(vty);
+ return;
+ }
+
+ vty_out(vty, "Showing BFD monitored static routes:\n");
+ vty_out(vty, "\n Next hops:\n");
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ const struct static_vrf *svrf = vrf->info;
+ struct route_table *rt;
+
+ vty_out(vty, " VRF %s IPv4 Unicast:\n", vrf->name);
+ rt = svrf->stable[AFI_IP][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path(vty, rt);
+
+ vty_out(vty, "\n VRF %s IPv4 Multicast:\n", vrf->name);
+ rt = svrf->stable[AFI_IP][SAFI_MULTICAST];
+ if (rt)
+ static_bfd_show_path(vty, rt);
+
+ vty_out(vty, "\n VRF %s IPv6 Unicast:\n", vrf->name);
+ rt = svrf->stable[AFI_IP6][SAFI_UNICAST];
+ if (rt)
+ static_bfd_show_path(vty, rt);
+ }
+
+ vty_out(vty, "\n");
+}
diff --git a/staticd/static_debug.c b/staticd/static_debug.c
index 45f845b40b..847e7d61a4 100644
--- a/staticd/static_debug.c
+++ b/staticd/static_debug.c
@@ -24,6 +24,7 @@
#include "lib/command.h"
#include "lib/debug.h"
+#include "lib/bfd.h"
#include "static_debug.h"
@@ -35,15 +36,18 @@
/* clang-format off */
struct debug static_dbg_events = {0, "Staticd events"};
struct debug static_dbg_route = {0, "Staticd route"};
+struct debug static_dbg_bfd = {0, "Staticd bfd"};
struct debug *static_debug_arr[] = {
&static_dbg_events,
- &static_dbg_route
+ &static_dbg_route,
+ &static_dbg_bfd
};
const char *static_debugs_conflines[] = {
"debug static events",
- "debug static route"
+ "debug static route",
+ "debug static bfd"
};
/* clang-format on */
@@ -105,7 +109,8 @@ int static_debug_status_write(struct vty *vty)
* Debug general internal events
*
*/
-void static_debug_set(int vtynode, bool onoff, bool events, bool route)
+void static_debug_set(int vtynode, bool onoff, bool events, bool route,
+ bool bfd)
{
uint32_t mode = DEBUG_NODE2MODE(vtynode);
@@ -113,6 +118,10 @@ void static_debug_set(int vtynode, bool onoff, bool events, bool route)
DEBUG_MODE_SET(&static_dbg_events, mode, onoff);
if (route)
DEBUG_MODE_SET(&static_dbg_route, mode, onoff);
+ if (bfd) {
+ DEBUG_MODE_SET(&static_dbg_bfd, mode, onoff);
+ bfd_protocol_integration_set_debug(onoff);
+ }
}
/*
diff --git a/staticd/static_debug.h b/staticd/static_debug.h
index ee9f7b0537..129c096688 100644
--- a/staticd/static_debug.h
+++ b/staticd/static_debug.h
@@ -34,6 +34,7 @@ extern "C" {
/* staticd debugging records */
extern struct debug static_dbg_events;
extern struct debug static_dbg_route;
+extern struct debug static_dbg_bfd;
/*
* Initialize staticd debugging.
@@ -71,7 +72,8 @@ int static_debug_status_write(struct vty *vty);
* Debug general internal events
*
*/
-void static_debug_set(int vtynode, bool onoff, bool events, bool route);
+void static_debug_set(int vtynode, bool onoff, bool events, bool route,
+ bool bfd);
#ifdef __cplusplus
}
diff --git a/staticd/static_nb.c b/staticd/static_nb.c
index 5935364d5a..68d9ba97b4 100644
--- a/staticd/static_nb.c
+++ b/staticd/static_nb.c
@@ -117,6 +117,33 @@ const struct frr_yang_module_info frr_staticd_info = {
}
},
{
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring",
+ .cbs = {
+ .create = route_next_hop_bfd_create,
+ .destroy = route_next_hop_bfd_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/source",
+ .cbs = {
+ .modify = route_next_hop_bfd_source_modify,
+ .destroy = route_next_hop_bfd_source_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/multi-hop",
+ .cbs = {
+ .modify = route_next_hop_bfd_multi_hop_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/profile",
+ .cbs = {
+ .modify = route_next_hop_bfd_profile_modify,
+ .destroy = route_next_hop_bfd_profile_destroy,
+ }
+ },
+ {
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list",
.cbs = {
.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create,
diff --git a/staticd/static_nb.h b/staticd/static_nb.h
index 5c3030fcfa..96c9f8d9b7 100644
--- a/staticd/static_nb.h
+++ b/staticd/static_nb.h
@@ -63,6 +63,13 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa
struct nb_cb_modify_args *args);
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_traffic_class_destroy(
struct nb_cb_destroy_args *args);
+int route_next_hop_bfd_create(struct nb_cb_create_args *args);
+int route_next_hop_bfd_destroy(struct nb_cb_destroy_args *args);
+int route_next_hop_bfd_source_modify(struct nb_cb_modify_args *args);
+int route_next_hop_bfd_source_destroy(struct nb_cb_destroy_args *args);
+int route_next_hop_bfd_profile_modify(struct nb_cb_modify_args *args);
+int route_next_hop_bfd_profile_destroy(struct nb_cb_destroy_args *args);
+int route_next_hop_bfd_multi_hop_modify(struct nb_cb_modify_args *args);
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create(
struct nb_cb_create_args *args);
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_destroy(
diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c
index 4a3d9e17a4..cbb5b8234f 100644
--- a/staticd/static_nb_config.c
+++ b/staticd/static_nb_config.c
@@ -750,6 +750,113 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa
/*
* XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring
+ */
+int route_next_hop_bfd_create(struct nb_cb_create_args *args)
+{
+ struct static_nexthop *sn;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ sn = nb_running_get_entry(args->dnode, NULL, true);
+ static_next_hop_bfd_monitor_enable(sn, args->dnode);
+ return NB_OK;
+}
+
+int route_next_hop_bfd_destroy(struct nb_cb_destroy_args *args)
+{
+ struct static_nexthop *sn;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ sn = nb_running_get_entry(args->dnode, NULL, true);
+ static_next_hop_bfd_monitor_disable(sn);
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/source
+ */
+int route_next_hop_bfd_source_modify(struct nb_cb_modify_args *args)
+{
+ struct static_nexthop *sn;
+ struct ipaddr source;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ sn = nb_running_get_entry(args->dnode, NULL, true);
+ yang_dnode_get_ip(&source, args->dnode, NULL);
+ static_next_hop_bfd_source(sn, &source);
+ return NB_OK;
+}
+
+int route_next_hop_bfd_source_destroy(struct nb_cb_destroy_args *args)
+{
+ struct static_nexthop *sn;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ sn = nb_running_get_entry(args->dnode, NULL, true);
+ static_next_hop_bfd_auto_source(sn);
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/multi-hop
+ */
+int route_next_hop_bfd_multi_hop_modify(struct nb_cb_modify_args *args)
+{
+ struct static_nexthop *sn;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ sn = nb_running_get_entry(args->dnode, NULL, true);
+ static_next_hop_bfd_multi_hop(sn,
+ yang_dnode_get_bool(args->dnode, NULL));
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/bfd-monitoring/profile
+ */
+int route_next_hop_bfd_profile_modify(struct nb_cb_modify_args *args)
+{
+ struct static_nexthop *sn;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ sn = nb_running_get_entry(args->dnode, NULL, true);
+ static_next_hop_bfd_profile(sn,
+ yang_dnode_get_string(args->dnode, NULL));
+
+ return NB_OK;
+}
+
+int route_next_hop_bfd_profile_destroy(struct nb_cb_destroy_args *args)
+{
+ struct static_nexthop *sn;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ sn = nb_running_get_entry(args->dnode, NULL, true);
+ static_next_hop_bfd_profile(sn, NULL);
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list
*/
int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_create(
diff --git a/staticd/static_routes.c b/staticd/static_routes.c
index ed4cdc51ce..ccbb98bd11 100644
--- a/staticd/static_routes.c
+++ b/staticd/static_routes.c
@@ -276,6 +276,8 @@ struct static_nexthop *static_add_nexthop(struct static_path *pn,
/* Make new static route structure. */
nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
+ /* Copy back pointers. */
+ nh->rn = rn;
nh->pn = pn;
nh->type = type;
@@ -393,6 +395,8 @@ void static_delete_nexthop(struct static_nexthop *nh)
struct route_node *rn = pn->rn;
static_nexthop_list_del(&(pn->nexthop_list), nh);
+ /* Remove BFD session/configuration if any. */
+ bfd_sess_free(&nh->bsp);
if (nh->nh_vrf_id == VRF_UNKNOWN)
goto EXIT;
@@ -432,6 +436,8 @@ static void static_ifindex_update_nh(struct interface *ifp, bool up,
nh->ifindex = IFINDEX_INTERNAL;
}
+ /* Remove previously configured route if any. */
+ static_uninstall_path(pn);
static_install_path(pn);
}
diff --git a/staticd/static_routes.h b/staticd/static_routes.h
index 71c3689be5..2332cfd2bf 100644
--- a/staticd/static_routes.h
+++ b/staticd/static_routes.h
@@ -20,6 +20,7 @@
#ifndef __STATIC_ROUTES_H__
#define __STATIC_ROUTES_H__
+#include "lib/bfd.h"
#include "lib/mpls.h"
#include "table.h"
#include "memory.h"
@@ -30,6 +31,8 @@ extern "C" {
DECLARE_MGROUP(STATIC);
+#include "staticd/static_vrf.h"
+
/* Static route label information */
struct static_nh_label {
uint8_t num_labels;
@@ -148,6 +151,13 @@ struct static_nexthop {
/* SR-TE color */
uint32_t color;
+
+ /** BFD integration data. */
+ struct bfd_session_params *bsp;
+ /** Back pointer for route node. */
+ struct route_node *rn;
+ /** Path connection status. */
+ bool path_down;
};
DECLARE_DLIST(static_nexthop_list, struct static_nexthop, list);
@@ -218,6 +228,24 @@ extern void zebra_stable_node_cleanup(struct route_table *table,
extern void static_get_nh_str(struct static_nexthop *nh, char *nexthop,
size_t size);
+/*
+ * BFD integration.
+ */
+extern void static_next_hop_bfd_source(struct static_nexthop *sn,
+ const struct ipaddr *source);
+extern void static_next_hop_bfd_auto_source(struct static_nexthop *sn);
+extern void static_next_hop_bfd_monitor_enable(struct static_nexthop *sn,
+ const struct lyd_node *dnode);
+extern void static_next_hop_bfd_monitor_disable(struct static_nexthop *sn);
+extern void static_next_hop_bfd_profile(struct static_nexthop *sn,
+ const char *name);
+extern void static_next_hop_bfd_multi_hop(struct static_nexthop *sn, bool mhop);
+
+/** Call this function after zebra client initialization. */
+extern void static_bfd_initialize(struct zclient *zc, struct thread_master *tm);
+
+extern void static_bfd_show(struct vty *vty, bool isjson);
+
#ifdef __cplusplus
}
#endif
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index efae3c53da..ff79622038 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -65,6 +65,11 @@ struct static_route_args {
const char *label;
const char *table;
const char *color;
+
+ bool bfd;
+ bool bfd_multi_hop;
+ const char *bfd_source;
+ const char *bfd_profile;
};
static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
@@ -138,6 +143,11 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
apply_mask(&p);
prefix2str(&p, buf_prefix, sizeof(buf_prefix));
+ if (args->bfd && args->gateway == NULL) {
+ vty_out(vty, "%% Route monitoring requires a gateway\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
if (args->source)
prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix));
if (args->gateway)
@@ -332,6 +342,41 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
NULL);
}
+
+ if (args->bfd) {
+ char xpath_bfd[XPATH_MAXLEN];
+
+ if (args->bfd_source) {
+ strlcpy(xpath_bfd, xpath_nexthop,
+ sizeof(xpath_bfd));
+ strlcat(xpath_bfd,
+ "/frr-staticd:bfd-monitoring/source",
+ sizeof(xpath_bfd));
+ nb_cli_enqueue_change(vty, xpath_bfd,
+ NB_OP_MODIFY,
+ args->bfd_source);
+ }
+
+ strlcpy(xpath_bfd, xpath_nexthop, sizeof(xpath_bfd));
+ strlcat(xpath_bfd,
+ "/frr-staticd:bfd-monitoring/multi-hop",
+ sizeof(xpath_bfd));
+ nb_cli_enqueue_change(vty, xpath_bfd, NB_OP_MODIFY,
+ args->bfd_multi_hop ? "true"
+ : "false");
+
+ if (args->bfd_profile) {
+ strlcpy(xpath_bfd, xpath_nexthop,
+ sizeof(xpath_bfd));
+ strlcat(xpath_bfd,
+ "/frr-staticd:bfd-monitoring/profile",
+ sizeof(xpath_bfd));
+ nb_cli_enqueue_change(vty, xpath_bfd,
+ NB_OP_MODIFY,
+ args->bfd_profile);
+ }
+ }
+
ret = nb_cli_apply_changes(vty, xpath_prefix);
} else {
if (args->source)
@@ -375,14 +420,23 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
/* Static unicast routes for multicast RPF lookup. */
DEFPY_YANG (ip_mroute_dist,
ip_mroute_dist_cmd,
- "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
+ "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [{"
+ "(1-255)$distance"
+ "|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}]"
+ "}]",
NO_STR
IP_STR
"Configure static unicast route into MRIB for multicast RPF lookup\n"
"IP destination prefix (e.g. 10.0.0.0/8)\n"
"Nexthop address\n"
"Nexthop interface name\n"
- "Distance\n")
+ "Distance\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -392,6 +446,10 @@ DEFPY_YANG (ip_mroute_dist,
.gateway = gate_str,
.interface_name = ifname,
.distance = distance_str,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -506,6 +564,7 @@ DEFPY_YANG(ip_route_address_interface,
|nexthop-vrf NAME \
|onlink$onlink \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -525,7 +584,13 @@ DEFPY_YANG(ip_route_address_interface,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n"
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -543,6 +608,10 @@ DEFPY_YANG(ip_route_address_interface,
.onlink = !!onlink,
.vrf = vrf,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -562,6 +631,7 @@ DEFPY_YANG(ip_route_address_interface_vrf,
|nexthop-vrf NAME \
|onlink$onlink \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -580,7 +650,13 @@ DEFPY_YANG(ip_route_address_interface_vrf,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n"
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -598,6 +674,10 @@ DEFPY_YANG(ip_route_address_interface_vrf,
.onlink = !!onlink,
.xpath_vrf = true,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -616,6 +696,7 @@ DEFPY_YANG(ip_route,
|table (1-4294967295) \
|nexthop-vrf NAME \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -634,7 +715,13 @@ DEFPY_YANG(ip_route,
"The table number to configure\n"
VRF_CMD_HELP_STR
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -651,6 +738,10 @@ DEFPY_YANG(ip_route,
.color = color_str,
.vrf = vrf,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -668,6 +759,7 @@ DEFPY_YANG(ip_route_vrf,
|table (1-4294967295) \
|nexthop-vrf NAME \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -685,7 +777,13 @@ DEFPY_YANG(ip_route_vrf,
"The table number to configure\n"
VRF_CMD_HELP_STR
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -702,6 +800,10 @@ DEFPY_YANG(ip_route_vrf,
.color = color_str,
.xpath_vrf = true,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -814,6 +916,7 @@ DEFPY_YANG(ipv6_route_address_interface,
|nexthop-vrf NAME \
|onlink$onlink \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR
IPV6_STR
@@ -834,7 +937,13 @@ DEFPY_YANG(ipv6_route_address_interface,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n"
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -852,6 +961,10 @@ DEFPY_YANG(ipv6_route_address_interface,
.onlink = !!onlink,
.vrf = vrf,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -870,6 +983,7 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,
|nexthop-vrf NAME \
|onlink$onlink \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR
IPV6_STR
@@ -889,7 +1003,13 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,
VRF_CMD_HELP_STR
"Treat the nexthop as directly attached to the interface\n"
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -907,6 +1027,10 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,
.onlink = !!onlink,
.xpath_vrf = true,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -924,6 +1048,7 @@ DEFPY_YANG(ipv6_route,
|table (1-4294967295) \
|nexthop-vrf NAME \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR
IPV6_STR
@@ -943,7 +1068,13 @@ DEFPY_YANG(ipv6_route,
"The table number to configure\n"
VRF_CMD_HELP_STR
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -960,6 +1091,10 @@ DEFPY_YANG(ipv6_route,
.color = color_str,
.vrf = vrf,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -976,6 +1111,7 @@ DEFPY_YANG(ipv6_route_vrf,
|table (1-4294967295) \
|nexthop-vrf NAME \
|color (1-4294967295) \
+ |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
}]",
NO_STR
IPV6_STR
@@ -994,7 +1130,13 @@ DEFPY_YANG(ipv6_route_vrf,
"The table number to configure\n"
VRF_CMD_HELP_STR
"SR-TE color\n"
- "The SR-TE color to configure\n")
+ "The SR-TE color to configure\n"
+ BFD_INTEGRATION_STR
+ BFD_INTEGRATION_MULTI_HOP_STR
+ BFD_INTEGRATION_SOURCE_STR
+ BFD_INTEGRATION_SOURCEV4_STR
+ BFD_PROFILE_STR
+ BFD_PROFILE_NAME_STR)
{
struct static_route_args args = {
.delete = !!no,
@@ -1011,6 +1153,10 @@ DEFPY_YANG(ipv6_route_vrf,
.color = color_str,
.xpath_vrf = true,
.nexthop_vrf = nexthop_vrf,
+ .bfd = !!bfd,
+ .bfd_multi_hop = !!bfd_multi_hop,
+ .bfd_source = bfd_source_str,
+ .bfd_profile = bfd_profile,
};
return static_route_nb_run(vty, &args);
@@ -1165,6 +1311,25 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,
vty_out(vty, " color %s",
yang_dnode_get_string(nexthop, "./srte-color"));
+ if (yang_dnode_exists(nexthop, "./bfd-monitoring")) {
+ const struct lyd_node *bfd_dnode =
+ yang_dnode_get(nexthop, "./bfd-monitoring");
+
+ if (yang_dnode_get_bool(bfd_dnode, "./multi-hop")) {
+ vty_out(vty, " bfd multi-hop");
+
+ if (yang_dnode_exists(bfd_dnode, "./source"))
+ vty_out(vty, " source %s",
+ yang_dnode_get_string(bfd_dnode,
+ "./source"));
+ } else
+ vty_out(vty, " bfd");
+
+ if (yang_dnode_exists(bfd_dnode, "./profile"))
+ vty_out(vty, " profile %s",
+ yang_dnode_get_string(bfd_dnode, "./profile"));
+ }
+
vty_out(vty, "\n");
}
@@ -1292,20 +1457,33 @@ int static_path_list_cli_cmp(const struct lyd_node *dnode1,
}
DEFPY_YANG(debug_staticd, debug_staticd_cmd,
- "[no] debug static [{events$events|route$route}]",
+ "[no] debug static [{events$events|route$route|bfd$bfd}]",
NO_STR DEBUG_STR STATICD_STR
"Debug events\n"
- "Debug route\n")
+ "Debug route\n"
+ "Debug bfd\n")
{
/* If no specific category, change all */
if (strmatch(argv[argc - 1]->text, "static"))
- static_debug_set(vty->node, !no, true, true);
+ static_debug_set(vty->node, !no, true, true, true);
else
- static_debug_set(vty->node, !no, !!events, !!route);
+ static_debug_set(vty->node, !no, !!events, !!route, !!bfd);
return CMD_SUCCESS;
}
+DEFPY(staticd_show_bfd_routes, staticd_show_bfd_routes_cmd,
+ "show bfd static route [json]$isjson",
+ SHOW_STR
+ BFD_INTEGRATION_STR
+ STATICD_STR
+ ROUTE_STR
+ JSON_STR)
+{
+ static_bfd_show(vty, !!isjson);
+ return CMD_SUCCESS;
+}
+
DEFUN_NOSH (show_debugging_static,
show_debugging_static_cmd,
"show debugging [static]",
@@ -1352,4 +1530,6 @@ void static_vty_init(void)
install_element(ENABLE_NODE, &show_debugging_static_cmd);
install_element(ENABLE_NODE, &debug_staticd_cmd);
install_element(CONFIG_NODE, &debug_staticd_cmd);
+
+ install_element(ENABLE_NODE, &staticd_show_bfd_routes_cmd);
}
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index cb36304473..316247adb3 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -441,6 +441,9 @@ extern void static_zebra_route_add(struct static_path *pn, bool install)
api_nh = &api.nexthops[nh_num];
if (nh->nh_vrf_id == VRF_UNKNOWN)
continue;
+ /* Skip next hop which peer is down. */
+ if (nh->path_down)
+ continue;
api_nh->vrf_id = nh->nh_vrf_id;
if (nh->onlink)
@@ -545,6 +548,7 @@ void static_zebra_init(void)
zclient->zebra_connected = zebra_connected;
static_nht_hash_init(static_nht_hash);
+ static_bfd_initialize(zclient, master);
}
/* static_zebra_stop used by tests/lib/test_grpc.cpp */
diff --git a/staticd/subdir.am b/staticd/subdir.am
index bb0fc95bc2..022428281f 100644
--- a/staticd/subdir.am
+++ b/staticd/subdir.am
@@ -10,6 +10,7 @@ man8 += $(MANBUILD)/frr-staticd.8
endif
staticd_libstatic_a_SOURCES = \
+ staticd/static_bfd.c \
staticd/static_debug.c \
staticd/static_nht.c \
staticd/static_routes.c \
@@ -38,5 +39,6 @@ staticd_staticd_SOURCES = staticd/static_main.c
staticd_staticd_LDADD = staticd/libstatic.a lib/libfrr.la $(LIBCAP)
nodist_staticd_staticd_SOURCES = \
+ yang/frr-bfdd.yang.c \
yang/frr-staticd.yang.c \
# end
diff --git a/tests/topotests/bfd_topo3/r3/bfd-static-down.json b/tests/topotests/bfd_topo3/r3/bfd-static-down.json
new file mode 100644
index 0000000000..60752d3aa1
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r3/bfd-static-down.json
@@ -0,0 +1,12 @@
+{
+ "path-list": {
+ "ipv4-multicast": [],
+ "ipv4-unicast": [],
+ "ipv6-unicast": [
+ {
+ "prefix": "2001:db8:5::\/64",
+ "vrf": "default",
+ "installed": false
+ }
+ ]
+ }}
diff --git a/tests/topotests/bfd_topo3/r3/bfd-static.json b/tests/topotests/bfd_topo3/r3/bfd-static.json
new file mode 100644
index 0000000000..c65060c7b0
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r3/bfd-static.json
@@ -0,0 +1,13 @@
+{
+ "path-list": {
+ "ipv4-multicast": [],
+ "ipv4-unicast": [],
+ "ipv6-unicast": [
+ {
+ "prefix": "2001:db8:5::\/64",
+ "vrf": "default",
+ "installed": true
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bfd_topo3/r3/staticd.conf b/tests/topotests/bfd_topo3/r3/staticd.conf
new file mode 100644
index 0000000000..44f91f3f34
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r3/staticd.conf
@@ -0,0 +1 @@
+ipv6 route 2001:db8:5::/64 2001:db8:4::3 bfd multi-hop profile slow-tx
diff --git a/tests/topotests/bfd_topo3/r4/bfd-peers.json b/tests/topotests/bfd_topo3/r4/bfd-peers.json
index 2f41f25c58..4f71d75389 100644
--- a/tests/topotests/bfd_topo3/r4/bfd-peers.json
+++ b/tests/topotests/bfd_topo3/r4/bfd-peers.json
@@ -19,7 +19,8 @@
"remote-transmit-interval": 2000,
"status": "up",
"uptime": "*",
- "transmit-interval": 2000
+ "transmit-interval": 2000,
+ "vrf": "default"
},
{
"detect-multiplier": 3,
@@ -41,6 +42,49 @@
"remote-transmit-interval": 2000,
"status": "up",
"uptime": "*",
- "transmit-interval": 2000
+ "transmit-interval": 2000,
+ "vrf": "default"
+ },
+ {
+ "detect-multiplier": 3,
+ "diagnostic": "ok",
+ "echo-receive-interval": 50,
+ "echo-transmit-interval": 0,
+ "id": "*",
+ "multihop": false,
+ "passive-mode": false,
+ "peer": "192.168.4.3",
+ "receive-interval": 2000,
+ "remote-detect-multiplier": 3,
+ "remote-diagnostic": "ok",
+ "remote-echo-receive-interval": 50,
+ "remote-id": "*",
+ "remote-receive-interval": 2000,
+ "remote-transmit-interval": 2000,
+ "status": "up",
+ "transmit-interval": 2000,
+ "uptime": "*",
+ "vrf": "default"
+ },
+ {
+ "detect-multiplier": 3,
+ "diagnostic": "ok",
+ "echo-receive-interval": 50,
+ "echo-transmit-interval": 0,
+ "id": "*",
+ "multihop": false,
+ "passive-mode": false,
+ "peer": "192.168.4.2",
+ "receive-interval": 2000,
+ "remote-detect-multiplier": 3,
+ "remote-diagnostic": "ok",
+ "remote-echo-receive-interval": 50,
+ "remote-id": "*",
+ "remote-receive-interval": 2000,
+ "remote-transmit-interval": 2000,
+ "status": "up",
+ "transmit-interval": 2000,
+ "uptime": "*",
+ "vrf": "default"
}
]
diff --git a/tests/topotests/bfd_topo3/r4/bgpd.conf b/tests/topotests/bfd_topo3/r4/bgpd.conf
index 0aab6e3017..bfad78a7ad 100644
--- a/tests/topotests/bfd_topo3/r4/bgpd.conf
+++ b/tests/topotests/bfd_topo3/r4/bgpd.conf
@@ -9,6 +9,7 @@ router bgp 400
neighbor 2001:db8:1::1 bfd profile slow-tx-mh
address-family ipv4 unicast
redistribute connected
+ redistribute static
exit-address-family
address-family ipv6 unicast
redistribute connected
diff --git a/tests/topotests/bfd_topo3/r4/staticd.conf b/tests/topotests/bfd_topo3/r4/staticd.conf
new file mode 100644
index 0000000000..3b1c5bfb66
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r4/staticd.conf
@@ -0,0 +1,2 @@
+ip route 10.254.254.5/32 192.168.4.2 bfd profile slow-tx
+ip route 10.254.254.6/32 192.168.4.3 bfd profile slow-tx
diff --git a/tests/topotests/bfd_topo3/r4/zebra.conf b/tests/topotests/bfd_topo3/r4/zebra.conf
index bf0cfcf42c..2574941724 100644
--- a/tests/topotests/bfd_topo3/r4/zebra.conf
+++ b/tests/topotests/bfd_topo3/r4/zebra.conf
@@ -8,3 +8,7 @@ interface r4-eth0
ip address 192.168.3.1/24
ipv6 address 2001:db8:3::1/64
!
+interface r4-eth1
+ ip address 192.168.4.1/24
+ ipv6 address 2001:db8:4::1/64
+!
diff --git a/tests/topotests/bfd_topo3/r5/bfd-peers.json b/tests/topotests/bfd_topo3/r5/bfd-peers.json
new file mode 100644
index 0000000000..777b1dd9cc
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r5/bfd-peers.json
@@ -0,0 +1,23 @@
+[
+ {
+ "detect-multiplier": 3,
+ "diagnostic": "ok",
+ "echo-receive-interval": 50,
+ "echo-transmit-interval": 0,
+ "id": "*",
+ "multihop": false,
+ "passive-mode": false,
+ "peer": "192.168.4.1",
+ "receive-interval": 2000,
+ "remote-detect-multiplier": 3,
+ "remote-diagnostic": "ok",
+ "remote-echo-receive-interval": 50,
+ "remote-id": "*",
+ "remote-receive-interval": 2000,
+ "remote-transmit-interval": 2000,
+ "status": "up",
+ "transmit-interval": 2000,
+ "uptime": "*",
+ "vrf": "default"
+ }
+]
diff --git a/tests/topotests/bfd_topo3/r5/bfdd.conf b/tests/topotests/bfd_topo3/r5/bfdd.conf
new file mode 100644
index 0000000000..6d4483acc4
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r5/bfdd.conf
@@ -0,0 +1,11 @@
+debug bfd network
+debug bfd peer
+debug bfd zebra
+!
+bfd
+ profile slow-tx
+ receive-interval 2000
+ transmit-interval 2000
+ minimum-ttl 250
+ !
+!
diff --git a/tests/topotests/bfd_topo3/r5/staticd.conf b/tests/topotests/bfd_topo3/r5/staticd.conf
new file mode 100644
index 0000000000..9828cffe0c
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r5/staticd.conf
@@ -0,0 +1,2 @@
+ip route 0.0.0.0/0 192.168.4.1
+ip route 10.254.254.4/32 192.168.4.1 bfd profile slow-tx
diff --git a/tests/topotests/bfd_topo3/r5/zebra.conf b/tests/topotests/bfd_topo3/r5/zebra.conf
new file mode 100644
index 0000000000..f84ce7e7f0
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r5/zebra.conf
@@ -0,0 +1,10 @@
+ip forwarding
+ipv6 forwarding
+!
+interface lo
+ ip address 10.254.254.5/32
+!
+interface r5-eth0
+ ip address 192.168.4.2/24
+ ipv6 address 2001:db8:4::2/64
+!
diff --git a/tests/topotests/bfd_topo3/r6/bfd-peers.json b/tests/topotests/bfd_topo3/r6/bfd-peers.json
new file mode 100644
index 0000000000..4de451d15b
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r6/bfd-peers.json
@@ -0,0 +1,46 @@
+[
+ {
+ "detect-multiplier": 3,
+ "diagnostic": "ok",
+ "echo-receive-interval": 50,
+ "echo-transmit-interval": 0,
+ "id": "*",
+ "multihop": false,
+ "passive-mode": false,
+ "peer": "192.168.4.1",
+ "receive-interval": 2000,
+ "remote-detect-multiplier": 3,
+ "remote-diagnostic": "ok",
+ "remote-echo-receive-interval": 50,
+ "remote-id": "*",
+ "remote-receive-interval": 2000,
+ "remote-transmit-interval": 2000,
+ "status": "up",
+ "transmit-interval": 2000,
+ "uptime": "*",
+ "vrf": "default"
+ },
+ {
+ "detect-multiplier": 3,
+ "diagnostic": "ok",
+ "echo-receive-interval": 50,
+ "echo-transmit-interval": 0,
+ "id": "*",
+ "local": "2001:db8:4::3",
+ "minimum-ttl": 2,
+ "multihop": true,
+ "passive-mode": false,
+ "peer": "2001:db8:3::2",
+ "receive-interval": 2000,
+ "remote-detect-multiplier": 3,
+ "remote-diagnostic": "ok",
+ "remote-echo-receive-interval": 50,
+ "remote-id": "*",
+ "remote-receive-interval": 2000,
+ "remote-transmit-interval": 2000,
+ "status": "up",
+ "transmit-interval": 2000,
+ "uptime": "*",
+ "vrf": "default"
+ }
+]
diff --git a/tests/topotests/bfd_topo3/r6/bfd-static-down.json b/tests/topotests/bfd_topo3/r6/bfd-static-down.json
new file mode 100644
index 0000000000..4dadff2251
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r6/bfd-static-down.json
@@ -0,0 +1,19 @@
+{
+ "path-list": {
+ "ipv4-multicast": [],
+ "ipv4-unicast": [
+ {
+ "installed": true,
+ "prefix": "10.254.254.4/32",
+ "vrf": "default"
+ }
+ ],
+ "ipv6-unicast": [
+ {
+ "prefix": "2001:db8:1::\/64",
+ "vrf": "default",
+ "installed": false
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bfd_topo3/r6/bfd-static.json b/tests/topotests/bfd_topo3/r6/bfd-static.json
new file mode 100644
index 0000000000..d042889d50
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r6/bfd-static.json
@@ -0,0 +1,19 @@
+{
+ "path-list": {
+ "ipv4-multicast": [],
+ "ipv4-unicast": [
+ {
+ "installed": true,
+ "prefix": "10.254.254.4/32",
+ "vrf": "default"
+ }
+ ],
+ "ipv6-unicast": [
+ {
+ "prefix": "2001:db8:1::\/64",
+ "vrf": "default",
+ "installed": true
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bfd_topo3/r6/bfdd.conf b/tests/topotests/bfd_topo3/r6/bfdd.conf
new file mode 100644
index 0000000000..6d4483acc4
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r6/bfdd.conf
@@ -0,0 +1,11 @@
+debug bfd network
+debug bfd peer
+debug bfd zebra
+!
+bfd
+ profile slow-tx
+ receive-interval 2000
+ transmit-interval 2000
+ minimum-ttl 250
+ !
+!
diff --git a/tests/topotests/bfd_topo3/r6/staticd.conf b/tests/topotests/bfd_topo3/r6/staticd.conf
new file mode 100644
index 0000000000..28da508fc2
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r6/staticd.conf
@@ -0,0 +1,5 @@
+ip route 0.0.0.0/0 192.168.4.1
+ip route 10.254.254.4/32 192.168.4.1 bfd profile slow-tx
+!
+ipv6 route 2001:db8:3::/64 2001:db8:4::1
+ipv6 route 2001:db8:1::/64 2001:db8:3::2 bfd multi-hop source 2001:db8:4::3 profile slow-tx
diff --git a/tests/topotests/bfd_topo3/r6/zebra.conf b/tests/topotests/bfd_topo3/r6/zebra.conf
new file mode 100644
index 0000000000..b8f2ea4c03
--- /dev/null
+++ b/tests/topotests/bfd_topo3/r6/zebra.conf
@@ -0,0 +1,10 @@
+ip forwarding
+ipv6 forwarding
+!
+interface lo
+ ip address 10.254.254.6/32
+!
+interface r6-eth0
+ ip address 192.168.4.3/24
+ ipv6 address 2001:db8:4::3/64
+!
diff --git a/tests/topotests/bfd_topo3/test_bfd_topo3.dot b/tests/topotests/bfd_topo3/test_bfd_topo3.dot
index 502cea11f2..8d18783d54 100644
--- a/tests/topotests/bfd_topo3/test_bfd_topo3.dot
+++ b/tests/topotests/bfd_topo3/test_bfd_topo3.dot
@@ -40,6 +40,18 @@ graph template {
fillcolor="#f08080",
style=filled,
];
+ r5 [
+ shape=doubleoctagon
+ label="r5",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r6 [
+ shape=doubleoctagon
+ label="r6",
+ fillcolor="#f08080",
+ style=filled,
+ ];
# Switches
sw1 [
@@ -60,6 +72,12 @@ graph template {
fillcolor="#d0e0d0",
style=filled,
];
+ sw4 [
+ shape=oval,
+ label="sw4\n192.168.4.0/24\n2001:db8:4::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
# Connections
r1 -- sw1 [label="eth0\n.1"];
@@ -70,4 +88,8 @@ graph template {
r4 -- sw3 [label="eth0\n.1"];
r3 -- sw3 [label="eth2\n.2"];
+
+ r4 -- sw4 [label="eth1\n.1"];
+ r5 -- sw4 [label="eth0\n.2"];
+ r6 -- sw4 [label="eth0\n.3"];
}
diff --git a/tests/topotests/bfd_topo3/test_bfd_topo3.jpg b/tests/topotests/bfd_topo3/test_bfd_topo3.jpg
index 6b532560bf..f100eae712 100644
--- a/tests/topotests/bfd_topo3/test_bfd_topo3.jpg
+++ b/tests/topotests/bfd_topo3/test_bfd_topo3.jpg
Binary files differ
diff --git a/tests/topotests/bfd_topo3/test_bfd_topo3.py b/tests/topotests/bfd_topo3/test_bfd_topo3.py
index 978593e41a..ea9f981d9b 100644
--- a/tests/topotests/bfd_topo3/test_bfd_topo3.py
+++ b/tests/topotests/bfd_topo3/test_bfd_topo3.py
@@ -51,6 +51,7 @@ def setup_module(mod):
"s1": ("r1", "r2"),
"s2": ("r2", "r3"),
"s3": ("r3", "r4"),
+ "s4": ("r4", "r5", "r6"),
}
tgen = Topogen(topodef, mod.__name__)
tgen.start_topology()
@@ -69,6 +70,10 @@ def setup_module(mod):
if os.path.isfile(daemon_file):
router.load_config(TopoRouter.RD_BGP, daemon_file)
+ daemon_file = "{}/{}/staticd.conf".format(CWD, rname)
+ if os.path.isfile(daemon_file):
+ router.load_config(TopoRouter.RD_STATIC, daemon_file)
+
# Initialize all routers.
tgen.start_router()
@@ -100,6 +105,10 @@ def test_wait_bgp_convergence():
expect_loopback_route("r1", "ip", "10.254.254.3/32", "bgp")
# Wait for R1 <-> R4 convergence.
expect_loopback_route("r1", "ip", "10.254.254.4/32", "bgp")
+ # Wait for R1 <-> R5 convergence.
+ expect_loopback_route("r1", "ip", "10.254.254.5/32", "bgp")
+ # Wait for R1 <-> R6 convergence.
+ expect_loopback_route("r1", "ip", "10.254.254.6/32", "bgp")
# Wait for R2 <-> R1 convergence.
expect_loopback_route("r2", "ip", "10.254.254.1/32", "bgp")
@@ -107,6 +116,10 @@ def test_wait_bgp_convergence():
expect_loopback_route("r2", "ip", "10.254.254.3/32", "bgp")
# Wait for R2 <-> R4 convergence.
expect_loopback_route("r2", "ip", "10.254.254.4/32", "bgp")
+ # Wait for R2 <-> R5 convergence.
+ expect_loopback_route("r2", "ip", "10.254.254.5/32", "bgp")
+ # Wait for R2 <-> R6 convergence.
+ expect_loopback_route("r2", "ip", "10.254.254.6/32", "bgp")
# Wait for R3 <-> R1 convergence.
expect_loopback_route("r3", "ip", "10.254.254.1/32", "bgp")
@@ -114,6 +127,10 @@ def test_wait_bgp_convergence():
expect_loopback_route("r3", "ip", "10.254.254.2/32", "bgp")
# Wait for R3 <-> R4 convergence.
expect_loopback_route("r3", "ip", "10.254.254.4/32", "bgp")
+ # Wait for R3 <-> R5 convergence.
+ expect_loopback_route("r3", "ip", "10.254.254.5/32", "bgp")
+ # Wait for R3 <-> R6 convergence.
+ expect_loopback_route("r3", "ip", "10.254.254.6/32", "bgp")
# Wait for R4 <-> R1 convergence.
expect_loopback_route("r4", "ip", "10.254.254.1/32", "bgp")
@@ -121,6 +138,15 @@ def test_wait_bgp_convergence():
expect_loopback_route("r4", "ip", "10.254.254.2/32", "bgp")
# Wait for R4 <-> R3 convergence.
expect_loopback_route("r4", "ip", "10.254.254.3/32", "bgp")
+ # Wait for R4 <-> R5 convergence.
+ expect_loopback_route("r4", "ip", "10.254.254.5/32", "static")
+ # Wait for R4 <-> R6 convergence.
+ expect_loopback_route("r4", "ip", "10.254.254.6/32", "static")
+
+ # Wait for R5 <-> R6 convergence.
+ expect_loopback_route("r3", "ipv6", "2001:db8:5::/64", "static")
+ # Wait for R6 <-> R5 convergence.
+ expect_loopback_route("r6", "ipv6", "2001:db8:1::/64", "static")
def test_wait_bfd_convergence():
@@ -149,6 +175,70 @@ def test_wait_bfd_convergence():
expect_bfd_configuration("r2")
expect_bfd_configuration("r3")
expect_bfd_configuration("r4")
+ expect_bfd_configuration("r5")
+ expect_bfd_configuration("r6")
+
+
+def test_static_route_monitoring():
+ "Test static route monitoring output."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("test BFD static route status")
+
+ def expect_static_bfd_output(router, filename):
+ "Load JSON file and compare with 'show bfd peer json'"
+ logger.info("waiting BFD configuration on router {}".format(router))
+ bfd_config = json.loads(
+ open("{}/{}/{}.json".format(CWD, router, filename)).read()
+ )
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show bfd static route json",
+ bfd_config,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assertmsg = '"{}" BFD static route status failure'.format(router)
+ assert result is None, assertmsg
+
+ expect_static_bfd_output("r3", "bfd-static")
+ expect_static_bfd_output("r6", "bfd-static")
+
+ logger.info("Setting r4 link down ...")
+
+ tgen.gears["r4"].link_enable("r4-eth0", False)
+
+ expect_static_bfd_output("r3", "bfd-static-down")
+ expect_static_bfd_output("r6", "bfd-static-down")
+
+
+def test_expect_static_rib_removal():
+ "Test that route got removed from RIB (staticd and bgpd)."
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def expect_route_missing(router, iptype, route):
+ "Wait until route is present on RIB for protocol."
+ logger.info("waiting route {} to disapear in {}".format(route, router))
+ test_func = partial(
+ topotest.router_json_cmp,
+ tgen.gears[router],
+ "show {} route json".format(iptype),
+ {route: None},
+ )
+ rv, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assertmsg = '"{}" convergence failure'.format(router)
+ assert result is None, assertmsg
+
+ expect_route_missing("r1", "ip", "10.254.254.5/32")
+ expect_route_missing("r2", "ip", "10.254.254.5/32")
+ expect_route_missing("r3", "ip", "10.254.254.5/32")
+ expect_route_missing("r3", "ipv6", "2001:db8:5::/64")
+ expect_route_missing("r6", "ipv6", "2001:db8:1::/64")
def teardown_module(_mod):
diff --git a/tests/topotests/bgp_accept_own/pe1/bgpd.conf b/tests/topotests/bgp_accept_own/pe1/bgpd.conf
index 8631293730..109e0eadbb 100644
--- a/tests/topotests/bgp_accept_own/pe1/bgpd.conf
+++ b/tests/topotests/bgp_accept_own/pe1/bgpd.conf
@@ -24,6 +24,7 @@ router bgp 65001 vrf Customer
neighbor 192.168.1.1 timers 1 3
neighbor 192.168.1.1 timers connect 1
address-family ipv4 unicast
+ redistribute connected
label vpn export 10
rd vpn export 192.168.1.2:2
rt vpn import 192.168.1.2:2
diff --git a/tests/topotests/bgp_accept_own/pe1/zebra.conf b/tests/topotests/bgp_accept_own/pe1/zebra.conf
index 71476d2aef..2b7aefadf2 100644
--- a/tests/topotests/bgp_accept_own/pe1/zebra.conf
+++ b/tests/topotests/bgp_accept_own/pe1/zebra.conf
@@ -11,5 +11,8 @@ interface pe1-eth1 vrf Service
interface pe1-eth2
ip address 10.0.1.1/24
!
+interface pe1-eth3 vrf Customer
+ ip address 192.0.2.1/24
+!
ip forwarding
!
diff --git a/tests/topotests/bgp_accept_own/test_bgp_accept_own.py b/tests/topotests/bgp_accept_own/test_bgp_accept_own.py
index 161530b483..daef6dcd52 100644
--- a/tests/topotests/bgp_accept_own/test_bgp_accept_own.py
+++ b/tests/topotests/bgp_accept_own/test_bgp_accept_own.py
@@ -58,6 +58,9 @@ def build_topo(tgen):
switch.add_link(tgen.gears["pe1"])
switch.add_link(tgen.gears["rr1"])
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["pe1"])
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
@@ -72,6 +75,7 @@ def setup_module(mod):
pe1.run("ip link add Service type vrf table 1002")
pe1.run("ip link set up dev Service")
pe1.run("ip link set pe1-eth1 master Service")
+ pe1.run("ip link set pe1-eth3 master Customer")
pe1.run("sysctl -w net.mpls.conf.pe1-eth2.input=1")
rr1.run("sysctl -w net.mpls.conf.rr1-eth0.input=1")
@@ -112,7 +116,7 @@ def test_bgp_accept_own():
def _bgp_check_received_routes_due_originator_id():
output = json.loads(pe1.vtysh_cmd("show bgp ipv4 vpn summary json"))
- expected = {"peers": {"10.10.10.101": {"pfxRcd": 0, "pfxSnt": 4}}}
+ expected = {"peers": {"10.10.10.101": {"pfxRcd": 0, "pfxSnt": 5}}}
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_check_received_routes_due_originator_id)
@@ -134,7 +138,7 @@ def test_bgp_accept_own():
def _bgp_check_received_routes_with_modified_rts():
output = json.loads(pe1.vtysh_cmd("show bgp ipv4 vpn summary json"))
- expected = {"peers": {"10.10.10.101": {"pfxRcd": 4, "pfxSnt": 4}}}
+ expected = {"peers": {"10.10.10.101": {"pfxRcd": 5, "pfxSnt": 5}}}
return topotest.json_cmp(output, expected)
test_func = functools.partial(_bgp_check_received_routes_with_modified_rts)
@@ -154,9 +158,7 @@ def test_bgp_accept_own():
expected = {
"paths": [
{
- "community": {
- "string": "65001:111"
- },
+ "community": {"string": "65001:111"},
"extendedCommunity": {
"string": "RT:192.168.1.2:2 RT:192.168.2.2:2"
},
@@ -171,6 +173,37 @@ def test_bgp_accept_own():
result is None
), "Failed, routes are not imported from RR1 with modified RT list"
+ step("Check if 192.0.2.0/24 is imported to vrf Service from vrf Customer")
+
+ def _bgp_check_imported_local_routes_from_vrf_service():
+ output = json.loads(
+ pe1.vtysh_cmd("show ip route vrf Service 192.0.2.0/24 json")
+ )
+ expected = {
+ "192.0.2.0/24": [
+ {
+ "vrfName": "Service",
+ "table": 1002,
+ "installed": True,
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "vrf": "Customer",
+ "active": True,
+ }
+ ],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_check_imported_local_routes_from_vrf_service)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert (
+ result is None
+ ), "Failed, didn't import local route 192.0.2.0/24 from vrf Customer to vrf Service"
+
step("Check if 172.16.255.1/32 is announced to CE2")
def _bgp_check_received_routes_from_pe():
@@ -188,9 +221,7 @@ def test_bgp_accept_own():
test_func = functools.partial(_bgp_check_received_routes_from_pe)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
- assert (
- result is None
- ), "Failed, didn't receive 172.16.255.1/32 from PE1"
+ assert result is None, "Failed, didn't receive 172.16.255.1/32 from PE1"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/zebra.conf
index 375bbea9ff..46831bb711 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/zebra.conf
@@ -4,8 +4,6 @@ hostname ce1
!
interface lo
ip address 99.0.0.1/32
- ip address 5.1.0.1/24
- ip address 6.0.2.1/24
!
interface ce1-eth0
description to r1
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/zebra.conf
index 90dd3c55b4..fb4d8cc9c4 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/zebra.conf
@@ -4,8 +4,6 @@ hostname ce2
!
interface lo
ip address 99.0.0.2/32
- ip address 5.1.0.1/24
- ip address 6.0.2.1/24
!
interface ce2-eth0
description to r3
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf
index cf7396eb12..e316de5690 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/bgpd.conf
@@ -19,7 +19,6 @@ router bgp 5227
network 5.1.3.0/24 route-map rm-nh
network 6.0.1.0/24 route-map rm-nh
network 6.0.2.0/24 route-map rm-nh-same
- network 6.0.3.0/24 route-map rm-nh-same
neighbor 192.168.1.1 activate
exit-address-family
!
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/zebra.conf
index df6ac47b08..77a1163a4b 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce3/zebra.conf
@@ -4,7 +4,6 @@ hostname ce3
!
interface lo
ip address 99.0.0.3/32
- ip address 6.0.3.1/24
!
interface ce3-eth0
description to r4
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf
index 9a6ca08a0b..60d9e93108 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/bgpd.conf
@@ -19,7 +19,6 @@ router bgp 5228 vrf ce4-cust2
network 5.4.3.0/24 route-map rm-nh
network 6.0.1.0/24 route-map rm-nh
network 6.0.2.0/24 route-map rm-nh-same
- network 6.0.3.0/24 route-map rm-nh-same
neighbor 192.168.2.1 activate
exit-address-family
!
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/zebra.conf
index 0e3a736292..e55c9e779a 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce4/zebra.conf
@@ -4,7 +4,6 @@ hostname ce4
!
interface ce4-cust2
ip address 99.0.0.4/32
- ip address 6.0.3.1/24
!
interface ce4-eth0
description to r4
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
index b2bf5f5f63..5161d8471f 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
@@ -175,20 +175,6 @@ def ltemplatePreRouterStartHook():
"setup {0} vrf {0}-cust1, {0}-eth4. enabled mpls input.".format(rtr)
)
# configure cust2 VRFs & MPLS
- rtrs = ["r1"]
- cmds = [
- "ip link add {0}-cust3 type vrf table 20",
- "ip link set dev {0}-cust3 up",
- "ip link add {0}-cust4 type vrf table 30",
- "ip link set dev {0}-cust4 up",
- "ip link add {0}-cust5 type vrf table 40",
- "ip link set dev {0}-cust5 up",
- ]
- for rtr in rtrs:
- for cmd in cmds:
- cc.doCmd(tgen, rtr, cmd.format(rtr))
- logger.info("setup {0} vrf {0}-cust3 and{0}-cust4.".format(rtr))
- # configure cust2 VRFs & MPLS
rtrs = ["r4"]
cmds = [
"ip link add {0}-cust2 type vrf table 20",
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
index 24e9f95372..8d42cfc0d8 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/bgpd.conf
@@ -11,7 +11,6 @@ log file bgpd.log debugging
#debug bgp vpn leak-from-vrf
#debug bgp vpn label
#debug bgp updates out
-#debug bgp nht
router bgp 5226
bgp router-id 1.1.1.1
@@ -40,11 +39,6 @@ router bgp 5227 vrf r1-cust1
neighbor 192.168.1.2 timers 3 10
address-family ipv4 unicast
- network 10.2.3.4/32
- network 192.0.0.0/24
-
- redistribute connected
-
neighbor 192.168.1.2 activate
neighbor 192.168.1.2 next-hop-self
@@ -57,47 +51,5 @@ router bgp 5227 vrf r1-cust1
exit-address-family
-router bgp 5228 vrf r1-cust3
- bgp router-id 192.168.1.1
-
- address-family ipv4 unicast
- rd vpn export 10:13
- rt vpn import 52:100
-
- import vpn
- export vpn
- exit-address-family
-
-
-router bgp 5227 vrf r1-cust4
- no bgp network import-check
-
- bgp router-id 192.168.1.1
-
- address-family ipv4 unicast
- network 28.0.0.0/24
-
- rd vpn export 10:14
- rt vpn export 52:100
-
- import vpn
- export vpn
- exit-address-family
-
-
-router bgp 5227 vrf r1-cust5
- bgp router-id 192.168.1.1
-
- address-family ipv4 unicast
- redistribute connected
-
- label vpn export 105
- rd vpn export 10:15
- rt vpn both 52:100
-
- import vpn
- export vpn
- exit-address-family
-
!
end
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/staticd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/staticd.conf
deleted file mode 100644
index 59430fdf99..0000000000
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/staticd.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-hostname r1
-log file staticd.log
-!
-vrf r1-cust1
- ip route 192.0.0.0/24 192.168.1.2
-exit-vrf
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/zebra.conf
index e81bc6b2ab..221bc7a839 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r1/zebra.conf
@@ -4,9 +4,6 @@ hostname r1
password zebra
#debug zebra packet
-#debug zebra rib detailed
-#debug zebra dplane detailed
-#debug zebra nexthop detail
interface lo
ip address 1.1.1.1/32
@@ -21,14 +18,6 @@ interface r1-eth4
ip address 192.168.1.1/24
no link-detect
-interface r1-cust1
- ip address 10.4.5.6/24
- no link-detect
-
-interface r1-cust5
- ip address 29.0.0.1/32
- no link-detect
-
ip forwarding
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py
index 89369241a8..91a7adf997 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_mpls.py
@@ -81,24 +81,3 @@ if ret != False and found != None:
"wait",
"CE3->CE4 (loopback) ping",
)
- luCommand(
- "r1",
- "ip vrf exec r1-cust1 ping 6.0.3.1 -I 10.4.5.6 -c 1",
- " 0. packet loss",
- "wait",
- "R1(r1-cust1)->CE3/4 (loopback) ping",
- )
- luCommand(
- "r1",
- "ip vrf exec r1-cust1 ping 6.0.3.1 -I 10.4.5.6 -c 1",
- " 0. packet loss",
- "pass",
- "R1(r1-cust1)->CE3/4 (loopback) ping",
- )
- luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 6.0.3.1 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "pass",
- "R1(r1-cust5)->CE3/4 ( (loopback) ping",
- )
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
index e9647898ab..75158b127e 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
@@ -72,53 +72,3 @@ luCommand(
"wait",
"CE4->PE4 ping",
)
-ret = luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 29.0.0.1 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "pass",
- "Ping its own IP. Check https://bugzilla.kernel.org/show_bug.cgi?id=203483 if it fails",
-)
-luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 192.168.1.1 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "pass",
- "R1(r1-cust5)->R1(r1-cust1 - r1-eth4) ping",
-)
-luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 192.168.1.2 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "wait",
- "R1(r1-cust5)->CE1 ping",
-)
-luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 192.168.1.2 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "pass",
- "R1(r1-cust5)->CE1 ping",
-)
-luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 99.0.0.1 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "pass",
- "R1(r1-cust5)->CE1 (loopback) ping",
-)
-luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 5.1.0.1 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "wait",
- "R1(r1-cust5)->CE1 (loopback) ping",
- time=30,
-)
-luCommand(
- "r1",
- "ip vrf exec r1-cust5 ping 5.1.0.1 -I 29.0.0.1 -c 1",
- " 0. packet loss",
- "pass",
- "R1(r1-cust5)->CE1 (loopback) ping",
-)
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
index 3242e3bd3a..1e2758c1c9 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
@@ -54,44 +54,15 @@ bgpribRequireUnicastRoutes("ce4", "ipv4", "ce4-cust2", "Cust 4 routes in ce1", w
#
# r1 vtysh -c "show bgp vrf r1-cust1 ipv4"
#
-want_r1_cust1_3_5_routes = [
+want_r1_cust1_routes = [
{"p": "5.1.0.0/24", "n": "99.0.0.1"},
{"p": "5.1.1.0/24", "n": "99.0.0.1"},
{"p": "6.0.1.0/24", "n": "99.0.0.1"},
{"p": "6.0.2.0/24", "n": "99.0.0.1"},
- {"p": "10.2.3.4/32", "n": "0.0.0.0", "bp": False},
- {"p": "10.4.5.0/24", "n": "0.0.0.0", "bp": True},
- {"p": "28.0.0.0/24", "n": "0.0.0.0", "bp": True},
- {"p": "29.0.0.1/32", "n": "0.0.0.0", "bp": True},
{"p": "99.0.0.1/32", "n": "192.168.1.2"},
- {"p": "192.0.0.0/24", "n": "0.0.0.0", "bp": True},
- {"p": "192.168.1.0/24", "n": "0.0.0.0", "bp": True},
]
bgpribRequireUnicastRoutes(
- "r1", "ipv4", "r1-cust1", "Customer 1 routes in r1 vrf", want_r1_cust1_3_5_routes
-)
-bgpribRequireUnicastRoutes(
- "r1", "ipv4", "r1-cust3", "Customer 3 routes in r1 vrf", want_r1_cust1_3_5_routes
-)
-bgpribRequireUnicastRoutes(
- "r1", "ipv4", "r1-cust5", "Customer 5 routes in r1 vrf", want_r1_cust1_3_5_routes
-)
-
-want_r1_cust4_routes = [
- {"p": "5.1.0.0/24", "n": "99.0.0.1", "exist": False},
- {"p": "5.1.1.0/24", "n": "99.0.0.1", "exist": False},
- {"p": "6.0.1.0/24", "n": "99.0.0.1", "exist": False},
- {"p": "6.0.2.0/24", "n": "99.0.0.1", "exist": False},
- {"p": "10.2.3.4/32", "n": "0.0.0.0", "exist": False},
- {"p": "10.4.5.0/24", "n": "0.0.0.0", "exist": False},
- {"p": "28.0.0.0/24", "n": "0.0.0.0", "bp": True},
- {"p": "29.0.0.1/32", "n": "0.0.0.0", "exist": False},
- {"p": "99.0.0.1/32", "n": "192.168.1.2", "exist": False},
- {"p": "192.0.0.0/24", "n": "0.0.0.0", "exist": False},
- {"p": "192.168.1.0/24", "n": "0.0.0.0", "exist": False},
-]
-bgpribRequireUnicastRoutes(
- "r1", "ipv4", "r1-cust4", "Customer 4 routes in r1 vrf", want_r1_cust4_routes
+ "r1", "ipv4", "r1-cust1", "Customer 1 routes in r1 vrf", want_r1_cust1_routes
)
want_r3_cust1_routes = [
@@ -99,20 +70,10 @@ want_r3_cust1_routes = [
{"p": "5.1.1.0/24", "n": "99.0.0.2"},
{"p": "6.0.1.0/24", "n": "99.0.0.2"},
{"p": "6.0.2.0/24", "n": "99.0.0.2"},
- {"p": "10.2.3.4/32", "n": "0.0.0.0", "exist": False},
- {"p": "28.0.0.0/24", "n": "1.1.1.1", "bp": True},
- {"p": "29.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.2/32", "n": "192.168.1.2"},
- {"p": "192.0.0.0/24", "n": "1.1.1.1", "bp": True},
- {"p": "192.168.1.0/24", "n": "1.1.1.1", "bp": True},
]
bgpribRequireUnicastRoutes(
- "r3",
- "ipv4",
- "r3-cust1",
- "Customer 1 routes in r3 vrf",
- want_r3_cust1_routes,
- retry=30,
+ "r3", "ipv4", "r3-cust1", "Customer 1 routes in r3 vrf", want_r3_cust1_routes
)
want_r4_cust1_routes = [
@@ -120,20 +81,10 @@ want_r4_cust1_routes = [
{"p": "5.1.3.0/24", "n": "99.0.0.3"},
{"p": "6.0.1.0/24", "n": "99.0.0.3"},
{"p": "6.0.2.0/24", "n": "99.0.0.3"},
- {"p": "10.2.3.4/32", "n": "0.0.0.0", "exist": False},
- {"p": "28.0.0.0/24", "n": "1.1.1.1", "bp": True},
- {"p": "29.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.3/32", "n": "192.168.1.2"},
- {"p": "192.0.0.0/24", "n": "1.1.1.1", "bp": True},
- {"p": "192.168.1.0/24", "n": "1.1.1.1", "bp": True},
]
bgpribRequireUnicastRoutes(
- "r4",
- "ipv4",
- "r4-cust1",
- "Customer 1 routes in r4 vrf",
- want_r4_cust1_routes,
- retry=30,
+ "r4", "ipv4", "r4-cust1", "Customer 1 routes in r4 vrf", want_r4_cust1_routes
)
want_r4_cust2_routes = [
@@ -141,20 +92,10 @@ want_r4_cust2_routes = [
{"p": "5.4.3.0/24", "n": "99.0.0.4"},
{"p": "6.0.1.0/24", "n": "99.0.0.4"},
{"p": "6.0.2.0/24", "n": "99.0.0.4"},
- {"p": "10.2.3.4/32", "n": "0.0.0.0", "exist": False},
- {"p": "28.0.0.0/24", "n": "1.1.1.1", "bp": True},
- {"p": "29.0.0.1/32", "n": "1.1.1.1", "bp": True},
{"p": "99.0.0.4/32", "n": "192.168.2.2"},
- {"p": "192.0.0.0/24", "n": "1.1.1.1", "bp": True},
- {"p": "192.168.1.0/24", "n": "1.1.1.1", "bp": True},
]
bgpribRequireUnicastRoutes(
- "r4",
- "ipv4",
- "r4-cust2",
- "Customer 2 routes in r4 vrf",
- want_r4_cust2_routes,
- retry=30,
+ "r4", "ipv4", "r4-cust2", "Customer 2 routes in r4 vrf", want_r4_cust2_routes
)
########################################################################
@@ -726,7 +667,7 @@ bgpribRequireUnicastRoutes(
luCommand(
"ce1",
'vtysh -c "show bgp ipv4 uni"',
- "18 routes and 19",
+ "12 routes and 12",
"wait",
"Local and remote routes",
10,
@@ -748,7 +689,7 @@ bgpribRequireUnicastRoutes(
luCommand(
"ce2",
'vtysh -c "show bgp ipv4 uni"',
- "18 routes and 22",
+ "12 routes and 15",
"wait",
"Local and remote routes",
10,
@@ -780,7 +721,7 @@ luCommand("r4", 'vtysh -c "show ip route vrf r4-cust2"')
luCommand(
"ce3",
'vtysh -c "show bgp ipv4 uni"',
- "18 routes and 19",
+ "12 routes and 13",
"wait",
"Local and remote routes",
10,
@@ -802,7 +743,7 @@ bgpribRequireUnicastRoutes(
luCommand(
"ce4",
'vtysh -c "show bgp vrf ce4-cust2 ipv4 uni"',
- "18 routes and 21",
+ "12 routes and 14",
"wait",
"Local and remote routes",
10,
diff --git a/tests/topotests/bgp_path_attribute_discard/__init__.py b/tests/topotests/bgp_path_attribute_discard/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_path_attribute_discard/__init__.py
diff --git a/tests/topotests/bgp_path_attribute_discard/exabgp.env b/tests/topotests/bgp_path_attribute_discard/exabgp.env
new file mode 100644
index 0000000000..28e642360a
--- /dev/null
+++ b/tests/topotests/bgp_path_attribute_discard/exabgp.env
@@ -0,0 +1,53 @@
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+##daemonize = false
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg
new file mode 100644
index 0000000000..7fb9210ecf
--- /dev/null
+++ b/tests/topotests/bgp_path_attribute_discard/peer1/exabgp.cfg
@@ -0,0 +1,24 @@
+neighbor 10.0.0.1 {
+ router-id 10.0.0.2;
+ local-address 10.0.0.2;
+ local-as 65001;
+ peer-as 65002;
+
+ capability {
+ route-refresh;
+ }
+
+ static {
+ route 192.168.100.101/32 {
+ atomic-aggregate;
+ community 65001:101;
+ next-hop 10.0.0.2;
+ }
+
+ route 192.168.100.102/32 {
+ originator-id 10.0.0.2;
+ community 65001:102;
+ next-hop 10.0.0.2;
+ }
+ }
+}
diff --git a/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf b/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf
new file mode 100644
index 0000000000..c96f354cc5
--- /dev/null
+++ b/tests/topotests/bgp_path_attribute_discard/r1/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 10.0.0.2 remote-as external
+ neighbor 10.0.0.2 timers 3 10
+!
diff --git a/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf b/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf
new file mode 100644
index 0000000000..51a1b2657c
--- /dev/null
+++ b/tests/topotests/bgp_path_attribute_discard/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r1-eth0
+ ip address 10.0.0.1/24
+!
diff --git a/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py
new file mode 100644
index 0000000000..4badf64c37
--- /dev/null
+++ b/tests/topotests/bgp_path_attribute_discard/test_bgp_path_attribute_discard.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if `neighbor path-attribute discard` command works correctly,
+can discard unwanted attributes from UPDATE messages, and ignore them
+by continuing to process UPDATE messages.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ r1 = tgen.add_router("r1")
+ peer1 = tgen.add_exabgp_peer("peer1", ip="10.0.0.2", defaultRoute="via 10.0.0.1")
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(r1)
+ switch.add_link(peer1)
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router = tgen.gears["r1"]
+ router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf"))
+ router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "r1/bgpd.conf"))
+ router.start()
+
+ peer = tgen.gears["peer1"]
+ peer.start(os.path.join(CWD, "peer1"), os.path.join(CWD, "exabgp.env"))
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_path_attribute_discard():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json detail"))
+ expected = {
+ "routes": {
+ "192.168.100.101/32": [
+ {
+ "valid": True,
+ "atomicAggregate": True,
+ "community": {
+ "string": "65001:101",
+ },
+ }
+ ],
+ "192.168.100.102/32": [
+ {
+ "valid": True,
+ "originatorId": "10.0.0.2",
+ "community": {
+ "string": "65001:102",
+ },
+ }
+ ],
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed bgp convergence"
+
+ step("Discard atomic-aggregate, community, and originator-id attributes from peer1")
+ r1.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ neighbor 10.0.0.2 path-attribute discard 6 8 9
+ """
+ )
+
+ def _bgp_check_if_attributes_discarded():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json detail"))
+ expected = {
+ "routes": {
+ "192.168.100.101/32": [
+ {
+ "valid": True,
+ "atomicAggregate": None,
+ "community": None,
+ }
+ ],
+ "192.168.100.102/32": [
+ {
+ "valid": True,
+ "originatorId": None,
+ "community": None,
+ }
+ ],
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_check_if_attributes_discarded)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert (
+ result is None
+ ), "Failed to discard path attributes (atomic-aggregate, community, and originator-id)"
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_sender_as_path_loop_detection/r1/bgpd.conf b/tests/topotests/bgp_sender_as_path_loop_detection/r1/bgpd.conf
index 719d76392d..409be74740 100644
--- a/tests/topotests/bgp_sender_as_path_loop_detection/r1/bgpd.conf
+++ b/tests/topotests/bgp_sender_as_path_loop_detection/r1/bgpd.conf
@@ -1,14 +1,19 @@
! exit1
router bgp 65001
- no bgp ebgp-requires-policy
- neighbor 192.168.255.1 remote-as 65002
- neighbor 192.168.255.1 timers 3 10
- address-family ipv4 unicast
- neighbor 192.168.255.1 route-map prepend out
- redistribute connected
- exit-address-family
- !
+ no bgp ebgp-requires-policy
+ neighbor 192.168.255.1 remote-as 65002
+ neighbor 192.168.255.1 timers 3 10
+ address-family ipv4 unicast
+ neighbor 192.168.255.1 route-map prepend out
+ redistribute connected
+ exit-address-family
+ !
+!
+ip prefix-list p1 seq 5 permit 172.16.255.253/32
!
route-map prepend permit 10
- set as-path prepend 65003
+ match ip address prefix-list p1
+ set as-path prepend 65003
+!
+route-map prepend permit 20
!
diff --git a/tests/topotests/bgp_sender_as_path_loop_detection/r1/zebra.conf b/tests/topotests/bgp_sender_as_path_loop_detection/r1/zebra.conf
index 9904bb4e16..74489a0571 100644
--- a/tests/topotests/bgp_sender_as_path_loop_detection/r1/zebra.conf
+++ b/tests/topotests/bgp_sender_as_path_loop_detection/r1/zebra.conf
@@ -1,5 +1,6 @@
! exit1
interface lo
+ ip address 172.16.255.253/32
ip address 172.16.255.254/32
!
interface r1-eth0
diff --git a/tests/topotests/bgp_sender_as_path_loop_detection/r2/bgpd.conf b/tests/topotests/bgp_sender_as_path_loop_detection/r2/bgpd.conf
index a4a654d7b5..dcb52a2e7d 100644
--- a/tests/topotests/bgp_sender_as_path_loop_detection/r2/bgpd.conf
+++ b/tests/topotests/bgp_sender_as_path_loop_detection/r2/bgpd.conf
@@ -1,11 +1,10 @@
! spine
router bgp 65002
- no bgp ebgp-requires-policy
- neighbor 192.168.255.2 remote-as 65001
- neighbor 192.168.255.2 timers 3 10
- neighbor 192.168.255.2 solo
- neighbor 192.168.254.2 remote-as 65003
- neighbor 192.168.254.2 timers 3 10
- neighbor 192.168.254.2 solo
- neighbor 192.168.254.2 sender-as-path-loop-detection
+ no bgp ebgp-requires-policy
+ neighbor 192.168.255.2 remote-as 65001
+ neighbor 192.168.255.2 timers 3 10
+ neighbor 192.168.255.2 sender-as-path-loop-detection
+ neighbor 192.168.254.2 remote-as 65003
+ neighbor 192.168.254.2 timers 3 10
+ neighbor 192.168.254.2 sender-as-path-loop-detection
!
diff --git a/tests/topotests/bgp_sender_as_path_loop_detection/r3/bgpd.conf b/tests/topotests/bgp_sender_as_path_loop_detection/r3/bgpd.conf
index 2e24de0b2d..519273d30d 100644
--- a/tests/topotests/bgp_sender_as_path_loop_detection/r3/bgpd.conf
+++ b/tests/topotests/bgp_sender_as_path_loop_detection/r3/bgpd.conf
@@ -1,6 +1,6 @@
! exit2
router bgp 65003
- no bgp ebgp-requires-policy
- neighbor 192.168.254.1 remote-as 65002
- neighbor 192.168.254.1 timers 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.254.1 remote-as 65002
+ neighbor 192.168.254.1 timers 3 10
!
diff --git a/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py b/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py
index b5c33f359b..ebeab05648 100644
--- a/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py
+++ b/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py
@@ -85,20 +85,20 @@ def test_bgp_sender_as_path_loop_detection():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- router = tgen.gears["r2"]
+ r2 = tgen.gears["r2"]
- def _bgp_converge(router):
- output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json"))
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json"))
expected = {
"192.168.255.2": {
"bgpState": "Established",
- "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 3}},
}
}
return topotest.json_cmp(output, expected)
- def _bgp_has_route_from_r1(router):
- output = json.loads(router.vtysh_cmd("show ip bgp 172.16.255.254/32 json"))
+ def _bgp_has_route_from_r1():
+ output = json.loads(r2.vtysh_cmd("show ip bgp 172.16.255.253/32 json"))
expected = {
"paths": [
{
@@ -111,31 +111,35 @@ def test_bgp_sender_as_path_loop_detection():
}
return topotest.json_cmp(output, expected)
- def _bgp_suppress_route_to_r3(router):
+ def _bgp_suppress_route_to_r1():
output = json.loads(
- router.vtysh_cmd(
- "show ip bgp neighbor 192.168.254.2 advertised-routes json"
- )
+ r2.vtysh_cmd("show ip bgp neighbor 192.168.255.2 advertised-routes json")
)
expected = {"totalPrefixCounter": 0}
return topotest.json_cmp(output, expected)
- test_func = functools.partial(_bgp_converge, router)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
-
- assert result is None, 'Failed bgp convergence in "{}"'.format(router)
+ def _bgp_suppress_route_to_r3():
+ output = json.loads(
+ r2.vtysh_cmd("show ip bgp neighbor 192.168.254.2 advertised-routes json")
+ )
+ expected = {"totalPrefixCounter": 2}
+ return topotest.json_cmp(output, expected)
- test_func = functools.partial(_bgp_has_route_from_r1, router)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed bgp to convergence"
- assert result is None, 'Failed to see a route from r1 in "{}"'.format(router)
+ test_func = functools.partial(_bgp_has_route_from_r1)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed to see a route from r1"
- test_func = functools.partial(_bgp_suppress_route_to_r3, router)
- success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ test_func = functools.partial(_bgp_suppress_route_to_r3)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Route 172.16.255.253/32 should not be sent to r3 from r2"
- assert (
- result is None
- ), 'Route 172.16.255.254/32 should not be sent to r3 "{}"'.format(router)
+ test_func = functools.partial(_bgp_suppress_route_to_r1)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Routes should not be sent to r1 from r2"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/bgpd.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/bgpd.conf
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/staticd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/staticd.conf
new file mode 100644
index 0000000000..0c88575abd
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/staticd.conf
@@ -0,0 +1,4 @@
+!
+ip route 0.0.0.0/0 192.168.3.254
+ipv6 route ::/0 2001:3::ffff
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/zebra.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/zebra.conf
new file mode 100644
index 0000000000..3f75641ea7
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c31/zebra.conf
@@ -0,0 +1,6 @@
+hostname c31
+!
+interface eth0
+ ip address 192.168.3.1/24
+ ipv6 address 2001:3::1/64
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/bgpd.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/bgpd.conf
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/staticd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/staticd.conf
new file mode 100644
index 0000000000..0c88575abd
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/staticd.conf
@@ -0,0 +1,4 @@
+!
+ip route 0.0.0.0/0 192.168.3.254
+ipv6 route ::/0 2001:3::ffff
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/zebra.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/zebra.conf
new file mode 100644
index 0000000000..c06a7d19f5
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/c32/zebra.conf
@@ -0,0 +1,6 @@
+hostname c32
+!
+interface eth0
+ ip address 192.168.3.1/24
+ ipv6 address 2001:3::1/64
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/bgpd.conf
index 048702f918..22b9014291 100644
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/bgpd.conf
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/bgpd.conf
@@ -11,16 +11,21 @@ router bgp 65001
bgp router-id 192.0.2.1
no bgp ebgp-requires-policy
no bgp default ipv4-unicast
- neighbor 2001:db8::2 remote-as 65002
- neighbor 2001:db8::2 timers 3 10
- neighbor 2001:db8::2 timers connect 1
- neighbor 2001:db8::2 capability extended-nexthop
+ neighbor 2001:db8:12::2 remote-as 65002
+ neighbor 2001:db8:12::2 timers 3 10
+ neighbor 2001:db8:12::2 timers connect 1
+ neighbor 2001:db8:12::2 capability extended-nexthop
+ neighbor 2001:db8:13::3 remote-as 65001
+ neighbor 2001:db8:13::3 timers 3 10
+ neighbor 2001:db8:13::3 timers connect 1
+ neighbor 2001:db8:13::3 capability extended-nexthop
!
segment-routing srv6
locator default
!
address-family ipv4 vpn
- neighbor 2001:db8::2 activate
+ neighbor 2001:db8:12::2 activate
+ neighbor 2001:db8:13::3 activate
exit-address-family
!
!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/staticd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/staticd.conf
index 662856f476..49b64fd7af 100644
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/staticd.conf
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/staticd.conf
@@ -1,3 +1,4 @@
!
-ipv6 route 2001:db8:2:2::/64 2001:db8::2
+ipv6 route 2001:db8:2:2::/64 2001:db8:12::2
+ipv6 route 2001:db8:3:3::/64 2001:db8:13::3
!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/zebra.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/zebra.conf
index 066748bec5..79dbf95593 100644
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/zebra.conf
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r1/zebra.conf
@@ -6,12 +6,15 @@ interface lo
ipv6 address 2001:db8:1:1::1/128
!
interface eth0
- ipv6 address 2001:db8::1/64
+ ipv6 address 2001:db8:12::1/64
!
-interface eth1 vrf vrf10
+interface eth1
+ ipv6 address 2001:db8:13::1/64
+!
+interface eth2 vrf vrf10
ip address 192.168.1.254/24
!
-interface eth2 vrf vrf20
+interface eth3 vrf vrf20
ip address 192.168.1.254/24
!
segment-routing
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/bgpd.conf
index 33b9103aaf..42b9d511d9 100644
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/bgpd.conf
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/bgpd.conf
@@ -11,16 +11,16 @@ router bgp 65002
bgp router-id 192.0.2.2
no bgp ebgp-requires-policy
no bgp default ipv4-unicast
- neighbor 2001:db8::1 remote-as 65001
- neighbor 2001:db8::1 timers 3 10
- neighbor 2001:db8::1 timers connect 1
- neighbor 2001:db8::1 capability extended-nexthop
+ neighbor 2001:db8:12::1 remote-as 65001
+ neighbor 2001:db8:12::1 timers 3 10
+ neighbor 2001:db8:12::1 timers connect 1
+ neighbor 2001:db8:12::1 capability extended-nexthop
!
segment-routing srv6
locator default
!
address-family ipv4 vpn
- neighbor 2001:db8::1 activate
+ neighbor 2001:db8:12::1 activate
exit-address-family
!
!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/staticd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/staticd.conf
index a2f54b7333..8d80c1ead2 100644
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/staticd.conf
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/staticd.conf
@@ -1,3 +1,4 @@
!
-ipv6 route 2001:db8:1:1::/64 2001:db8::1
+ipv6 route 2001:db8:1:1::/64 2001:db8:12::1
+ipv6 route 2001:db8:3:3::/64 2001:db8:12::1
!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/zebra.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/zebra.conf
index dc03389fcb..09a65b989c 100644
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/zebra.conf
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r2/zebra.conf
@@ -6,7 +6,7 @@ interface lo
ipv6 address 2001:db8:2:2::1/128
!
interface eth0
- ipv6 address 2001:db8::2/64
+ ipv6 address 2001:db8:12::2/64
!
interface eth1 vrf vrf10
ip address 192.168.2.254/24
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/bgpd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/bgpd.conf
new file mode 100644
index 0000000000..339b4eb089
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/bgpd.conf
@@ -0,0 +1,52 @@
+frr defaults traditional
+!
+hostname r2
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+router bgp 65001
+ bgp router-id 192.0.2.3
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001:db8:13::1 remote-as 65001
+ neighbor 2001:db8:13::1 timers 3 10
+ neighbor 2001:db8:13::1 timers connect 1
+ neighbor 2001:db8:13::1 capability extended-nexthop
+ !
+ segment-routing srv6
+ locator default
+ !
+ address-family ipv4 vpn
+ neighbor 2001:db8:13::1 activate
+ exit-address-family
+ !
+!
+router bgp 65001 vrf vrf10
+ bgp router-id 192.0.2.3
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 1
+ rd vpn export 65001:10
+ rt vpn both 0:10
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
+router bgp 65001 vrf vrf20
+ bgp router-id 192.0.2.2
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 2
+ rd vpn export 65001:20
+ rt vpn both 0:20
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/staticd.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/staticd.conf
new file mode 100644
index 0000000000..9d672d51ba
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/staticd.conf
@@ -0,0 +1,6 @@
+!
+ipv6 route 2001:db8:12::/64 2001:db8:13::1
+!
+ipv6 route 2001:db8:1:1::/64 2001:db8:13::1
+ipv6 route 2001:db8:2:2::/64 2001:db8:13::1
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/zebra.conf b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/zebra.conf
new file mode 100644
index 0000000000..a20cb76a74
--- /dev/null
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/r3/zebra.conf
@@ -0,0 +1,29 @@
+log file zebra.log
+!
+hostname r2
+!
+interface lo
+ ipv6 address 2001:db8:3:3::1/128
+!
+interface eth0
+ ipv6 address 2001:db8:13::3/64
+!
+interface eth1 vrf vrf10
+ ip address 192.168.3.254/24
+!
+interface eth2 vrf vrf20
+ ip address 192.168.3.254/24
+!
+segment-routing
+ srv6
+ locators
+ locator default
+ prefix 2001:db8:3:3::/64
+ !
+ !
+!
+ip forwarding
+ipv6 forwarding
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py b/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py
index 6a75fb82f4..0b8870cdca 100755
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py
@@ -44,17 +44,23 @@ pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
tgen.add_router("r1")
tgen.add_router("r2")
+ tgen.add_router("r3")
tgen.add_router("c11")
tgen.add_router("c12")
tgen.add_router("c21")
tgen.add_router("c22")
+ tgen.add_router("c31")
+ tgen.add_router("c32")
tgen.add_link(tgen.gears["r1"], tgen.gears["r2"], "eth0", "eth0")
- tgen.add_link(tgen.gears["r1"], tgen.gears["c11"], "eth1", "eth0")
- tgen.add_link(tgen.gears["r1"], tgen.gears["c12"], "eth2", "eth0")
+ tgen.add_link(tgen.gears["r1"], tgen.gears["r3"], "eth1", "eth0")
+ tgen.add_link(tgen.gears["r1"], tgen.gears["c11"], "eth2", "eth0")
+ tgen.add_link(tgen.gears["r1"], tgen.gears["c12"], "eth3", "eth0")
tgen.add_link(tgen.gears["r2"], tgen.gears["c21"], "eth1", "eth0")
tgen.add_link(tgen.gears["r2"], tgen.gears["c22"], "eth2", "eth0")
+ tgen.add_link(tgen.gears["r3"], tgen.gears["c31"], "eth1", "eth0")
+ tgen.add_link(tgen.gears["r3"], tgen.gears["c32"], "eth2", "eth0")
def setup_module(mod):
@@ -66,20 +72,23 @@ def setup_module(mod):
tgen.start_topology()
for rname, router in tgen.routers().items():
- router.load_config(TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname)))
- router.load_config(TopoRouter.RD_STATIC,
- os.path.join(CWD, '{}/staticd.conf'.format(rname)))
- router.load_config(TopoRouter.RD_BGP,
- os.path.join(CWD, '{}/bgpd.conf'.format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_STATIC, os.path.join(CWD, "{}/staticd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
tgen.gears["r1"].run("sysctl net.vrf.strict_mode=1")
tgen.gears["r1"].run("ip link add vrf10 type vrf table 10")
tgen.gears["r1"].run("ip link set vrf10 up")
tgen.gears["r1"].run("ip link add vrf20 type vrf table 20")
tgen.gears["r1"].run("ip link set vrf20 up")
- tgen.gears["r1"].run("ip link set eth1 master vrf10")
- tgen.gears["r1"].run("ip link set eth2 master vrf20")
+ tgen.gears["r1"].run("ip link set eth2 master vrf10")
+ tgen.gears["r1"].run("ip link set eth3 master vrf20")
tgen.gears["r2"].run("sysctl net.vrf.strict_mode=1")
tgen.gears["r2"].run("ip link add vrf10 type vrf table 10")
@@ -89,6 +98,14 @@ def setup_module(mod):
tgen.gears["r2"].run("ip link set eth1 master vrf10")
tgen.gears["r2"].run("ip link set eth2 master vrf20")
+ tgen.gears["r3"].run("sysctl net.vrf.strict_mode=1")
+ tgen.gears["r3"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["r3"].run("ip link set vrf10 up")
+ tgen.gears["r3"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["r3"].run("ip link set vrf20 up")
+ tgen.gears["r3"].run("ip link set eth1 master vrf10")
+ tgen.gears["r3"].run("ip link set eth2 master vrf20")
+
tgen.start_router()
@@ -115,12 +132,13 @@ def check_ping4(name, dest_addr, expected):
def test_ping():
tgen = get_topogen()
- logger.info(tgen.gears["c11"].run("ip route show"))
- # tests for ipv4-vpn
+
check_ping4("c11", "192.168.2.1", True)
+ check_ping4("c11", "192.168.3.1", True)
check_ping4("c12", "192.168.2.1", True)
- check_ping4("c21", "192.168.1.1", True)
- check_ping4("c22", "192.168.1.1", True)
+ check_ping4("c12", "192.168.3.1", True)
+ check_ping4("c21", "192.168.3.1", True)
+ check_ping4("c22", "192.168.3.1", True)
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json
index 2ce936b291..9f78447255 100644
--- a/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json
+++ b/tests/topotests/bgp_srv6l3vpn_route_leak/pe1/results/vrf20_ipv4.json
@@ -12,7 +12,7 @@
{
"fib": true,
"directlyConnected": true,
- "interfaceName": "vrf10",
+ "interfaceName": "eth0",
"vrf": "vrf10",
"active": true
}
diff --git a/tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf b/tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf
index 0e2d3a8248..295811bfd0 100644
--- a/tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf
+++ b/tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf
@@ -14,6 +14,7 @@ router bgp 65500 vrf vrf1
bgp router-id 192.0.2.1
address-family ipv4 unicast
redistribute connected
+ distance bgp 21 201 41
label vpn export 101
rd vpn export 444:1
rt vpn both 52:100
diff --git a/tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json b/tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json
index 5f2732aab0..e57e21bb12 100644
--- a/tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json
+++ b/tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json
@@ -7,7 +7,7 @@
"vrfName": "vrf1",
"selected": true,
"destSelected": true,
- "distance": 20,
+ "distance": 201,
"metric": 0,
"nexthops": [
{
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
new file mode 100644
index 0000000000..c51beca72a
--- /dev/null
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
@@ -0,0 +1,407 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test BGP Multi-VRF Dynamic Route Leaking:
+1. Verify recursive import among Tenant VRFs.
+2. Verify that dynamic import works fine between two different Tenant VRFs.
+ When next-hop IPs are same across all VRFs.
+ When next-hop IPs are different across all VRFs.
+3. Verify that with multiple tenant VRFs, dynamic import works fine between
+ Tenant VRFs to default VRF.
+ When next-hop IPs and prefixes are same across all VRFs.
+ When next-hop IPs and prefixes are different across all VRFs.
+"""
+
+import os
+import sys
+import time
+import pytest
+import platform
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topotest import version_cmp
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ check_address_types,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ step,
+ create_route_maps,
+ create_static_routes,
+ create_prefix_lists,
+ create_bgp_community_lists,
+ get_frr_ipv6_linklocal,
+)
+
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_bgp_community,
+ verify_bgp_rib,
+)
+from lib.topojson import build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Global variables
+NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
+NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
+NETWORK1_3 = {"ipv4": "10.10.10.1/32", "ipv6": "10:10::1/128"}
+NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
+NETWORK1_5 = {"ipv4": "110.110.110.1/32", "ipv6": "110:110::1/128"}
+NETWORK1_6 = {"ipv4": "110.110.110.100/32", "ipv6": "110:110::100/128"}
+
+NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
+NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
+NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
+NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
+NETWORK2_5 = {"ipv4": "220.220.220.20/32", "ipv6": "220:220::20/128"}
+NETWORK2_6 = {"ipv4": "220.220.220.200/32", "ipv6": "220:220::200/128"}
+
+NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
+NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
+
+PREFIX_LIST = {
+ "ipv4": ["11.11.11.1", "22.22.22.2", "22.22.22.22"],
+ "ipv6": ["11:11::1", "22:22::2", "22:22::22"],
+}
+PREFERRED_NEXT_HOP = "global"
+VRF_LIST = ["RED", "BLUE", "GREEN"]
+COMM_VAL_1 = "100:100"
+COMM_VAL_2 = "500:500"
+COMM_VAL_3 = "600:600"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_vrf_dynamic_route_leak_topo4.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start daemons and then start routers
+ start_topology(tgen)
+
+ # Run these tests for kernel version 4.19 or above
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ "BGP vrf dynamic route leak tests will not run "
+ '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
+ )
+ pytest.skip(error_msg)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def test_dynamic_import_recursive_import_tenant_vrf_p1(request):
+ """
+ Verify recursive import among Tenant VRFs.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step(
+ "Configure static routes on R2 for vrf RED and redistribute in "
+ "respective BGP instance"
+ )
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r2": {
+ "static_routes": [
+ {
+ "network": [NETWORK2_1[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Redistribute static route on BGP VRF RED")
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
+ )
+
+ redist_dict = {
+ "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that R2 has installed redistributed routes in vrf RED only")
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r2": {
+ "static_routes": [{"network": [NETWORK2_1[addr_type]], "vrf": "RED"}]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r2", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r2", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Import vrf RED's routes into vrf GREEN on R2")
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": "RED"}}}})
+
+ import_dict = {
+ "r2": {"bgp": [{"vrf": "GREEN", "local_as": 2, "address_family": temp}]}
+ }
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify on R2, that it installs imported routes from vrf RED to vrf "
+ "GREEN's RIB/FIB pointing next-hop to vrf RED"
+ )
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r2": {
+ "static_routes": [{"network": [NETWORK2_1[addr_type]], "vrf": "GREEN"}]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r2", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r2", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("On R3 import routes from vrf GREEN to vrf default")
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": "GREEN"}}}})
+
+ import_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify on R3, that it installs imported routes from vrf GREEN to "
+ "vrf default RIB/FIB pointing next-hop to vrf GREEN. "
+ )
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r2": {"static_routes": [{"network": [NETWORK2_1[addr_type]]}]}
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("On R4 import routes from vrf default to vrf BLUE")
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": "default"}}}})
+
+ import_dict = {
+ "r4": {"bgp": [{"vrf": "BLUE", "local_as": 4, "address_family": temp}]}
+ }
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify on R4, that it installs imported routes from vrf default to "
+ "vrf BLUE RIB/FIB pointing next-hop to vrf default."
+ )
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r4": {
+ "static_routes": [{"network": [NETWORK2_1[addr_type]], "vrf": "BLUE"}]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r4", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r4", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for dut, vrf_name, vrf_import, as_num in zip(
+ ["r2", "r4"], ["GREEN", "BLUE"], ["RED", "default"], [2, 4]
+ ):
+
+ for action, value in zip(["Delete", "Re-add"], [True, False]):
+ step("{} the import command on {} router".format(action, dut))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {"import": {"vrf": vrf_import, "delete": value}}
+ }
+ }
+ )
+
+ import_dict = {
+ dut: {
+ "bgp": [
+ {"vrf": vrf_name, "local_as": as_num, "address_family": temp}
+ ]
+ }
+ }
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r4": {
+ "static_routes": [
+ {"network": [NETWORK2_1[addr_type]], "vrf": "BLUE"}
+ ]
+ }
+ }
+ if value:
+ result = verify_bgp_rib(
+ tgen, addr_type, "r4", static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r4"]["static_routes"][0]["network"],
+ )
+
+ result = verify_rib(
+ tgen, addr_type, "r4", static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes["r4"]["static_routes"][0]["network"],
+ )
+ else:
+ result = verify_bgp_rib(tgen, addr_type, "r4", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r4", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
new file mode 100644
index 0000000000..bfeaaa17df
--- /dev/null
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
@@ -0,0 +1,932 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test BGP Multi-VRF Dynamic Route Leaking:
+1. Verify recursive import among Tenant VRFs.
+2. Verify that dynamic import works fine between two different Tenant VRFs.
+ When next-hop IPs are same across all VRFs.
+ When next-hop IPs are different across all VRFs.
+3. Verify that with multiple tenant VRFs, dynamic import works fine between
+ Tenant VRFs to default VRF.
+ When next-hop IPs and prefixes are same across all VRFs.
+ When next-hop IPs and prefixes are different across all VRFs.
+"""
+
+import os
+import sys
+import time
+import pytest
+import platform
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topotest import version_cmp
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ check_address_types,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ step,
+ create_route_maps,
+ create_static_routes,
+ create_prefix_lists,
+ create_bgp_community_lists,
+ get_frr_ipv6_linklocal,
+)
+
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_bgp_community,
+ verify_bgp_rib,
+)
+from lib.topojson import build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Global variables
+NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
+NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
+NETWORK1_3 = {"ipv4": "10.10.10.1/32", "ipv6": "10:10::1/128"}
+NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
+NETWORK1_5 = {"ipv4": "110.110.110.1/32", "ipv6": "110:110::1/128"}
+NETWORK1_6 = {"ipv4": "110.110.110.100/32", "ipv6": "110:110::100/128"}
+
+NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
+NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
+NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
+NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
+NETWORK2_5 = {"ipv4": "220.220.220.20/32", "ipv6": "220:220::20/128"}
+NETWORK2_6 = {"ipv4": "220.220.220.200/32", "ipv6": "220:220::200/128"}
+
+NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
+NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
+
+PREFIX_LIST = {
+ "ipv4": ["11.11.11.1", "22.22.22.2", "22.22.22.22"],
+ "ipv6": ["11:11::1", "22:22::2", "22:22::22"],
+}
+PREFERRED_NEXT_HOP = "global"
+VRF_LIST = ["RED", "BLUE", "GREEN"]
+COMM_VAL_1 = "100:100"
+COMM_VAL_2 = "500:500"
+COMM_VAL_3 = "600:600"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_vrf_dynamic_route_leak_topo4.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start daemons and then start routers
+ start_topology(tgen)
+
+ # Run these tests for kernel version 4.19 or above
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ "BGP vrf dynamic route leak tests will not run "
+ '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
+ )
+ pytest.skip(error_msg)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def test_dynamic_import_routes_between_two_tenant_vrf_p0(request):
+ """
+ Verify that dynamic import works fine between two different Tenant VRFs.
+
+ When next-hop IPs are same across all VRFs.
+ When next-hop IPs are different across all VRFs.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step(
+ "Configure static routes on R3 for each vrf and redistribute in "
+ "respective BGP instance"
+ )
+
+ for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
+ step("Configure static route for VRF : {}".format(vrf_name))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [network[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
+ )
+
+ redist_dict = {
+ "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
+ step(
+ "Verify that R3 has installed redistributed routes in respective "
+ "vrfs: {}".format(vrf_name)
+ )
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [network[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name,
+ }
+ ]
+ }
+ }
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Import from vrf GREEN+BLUE into vrf RED on R3")
+
+ for vrf_name in ["BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
+
+ import_dict = {
+ "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify on R1, that it installs all the routes(local+imported) in "
+ "vrf RED's RIB/FIB and doesn't get confuse with next-hop attribute, "
+ "as all vrfs on R1 are using same IP address for next-hop"
+ )
+
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ next_hop_1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[0]
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", static_routes, next_hop=next_hop_1
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", static_routes, next_hop=next_hop_1)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Remove import vrf GREEN/BLUE/Both command from vrf RED's instance on" " R3")
+ for vrf_name in ["BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
+ )
+
+ import_dict = {
+ "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that R1,R2 & R3 withdraw imported routes from vrf RED's RIB")
+ for dut in ["r1", "r2", "r3"]:
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in Route table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+ )
+
+ step("Add import vrf GREEN/BLUE/Both command from vrf RED's instance on " "R3")
+ for vrf_name in ["BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
+
+ import_dict = {
+ "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify that {} reinstall imported routes from vrf RED's RIB".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value in zip(["Shut", "No shut"], [True, False]):
+ step(
+ "{} the neighborship between R1-R3 and R1-R2 for vrf GREEN, BLUE "
+ "and default".format(action)
+ )
+ bgp_disable = {"r3": {"bgp": []}}
+ for vrf_name in ["GREEN", "BLUE", "default"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {"r3-link1": {"shutdown": value}}
+ },
+ "r2": {
+ "dest_link": {"r3-link1": {"shutdown": value}}
+ },
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable["r3"]["bgp"].append(
+ {"vrf": vrf_name, "local_as": 3, "address_family": temp}
+ )
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify RIB/FIB of vrf RED will be unchanged on all 3 routers")
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value, status in zip(
+ ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
+ ):
+ step("{} the neighborship between R1-R3 and R1-R2 for vrf RED".format(action))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r3-link1": {"shutdown": value}}},
+ "r2": {"dest_link": {"r3-link1": {"shutdown": value}}},
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable = {
+ "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
+ }
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that R1 and R2 {} all the routes from RED vrf's RIB and"
+ " FIB".format(status)
+ )
+ for dut in ["r1", "r2"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ if value:
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+
+ result = verify_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+ else:
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Remove import command from router R3 and configure the same on R2")
+ for vrf_name in ["BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
+ )
+
+ import_dict = {
+ "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that once import commands are removed from R3, all imported "
+ "routes are withdrawn from RIB/FIB of vrf RED on R1/R2/R3"
+ )
+
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+
+ step(
+ "Configure static routes on R2 for each vrf and redistribute in "
+ "respective BGP instance"
+ )
+ for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
+ step("Configure static route for VRF : {}".format(vrf_name))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r2": {
+ "static_routes": [
+ {
+ "network": [network[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
+ )
+
+ redist_dict = {
+ "r2": {"bgp": [{"vrf": vrf_name, "local_as": 2, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Remove redistribute static route on BGP VRF : {} on r3".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "redistribute": [{"redist_type": "static", "delete": True}]
+ }
+ }
+ }
+ )
+
+ redist_dict = {
+ "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for vrf_name in ["BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
+
+ import_dict = {
+ "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify after import commands are re-configured on R2's vrf RED, all "
+ "those routes are installed again in vrf RED of R1,R2,R3"
+ )
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Remove/add import vrf GREEN/BLUE/both command from vrf RED's " "instance on R2"
+ )
+ for vrf_name in ["BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
+ )
+
+ redist_dict = {
+ "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that R1,R2 & R3 withdraw imported routes from vrf RED's RIB")
+ for dut in ["r1", "r2", "r3"]:
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+
+ step("Add import vrf GREEN/BLUE/Both command from vrf RED's instance on " "R2")
+ for vrf_name in ["BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
+
+ redist_dict = {
+ "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify that {} reinstall imported routes from vrf RED's RIB".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value in zip(["Shut", "No shut"], [True, False]):
+ step(
+ "{} the neighborship between R2-R3 for vrf GREEN, BLUE and default".format(
+ action
+ )
+ )
+ bgp_disable = {"r2": {"bgp": []}}
+ for vrf_name in ["GREEN", "BLUE", "default"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {"r2-link1": {"shutdown": value}}
+ }
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable["r2"]["bgp"].append(
+ {"vrf": vrf_name, "local_as": 2, "address_family": temp}
+ )
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify RIB/FIB of vrf RED will be unchanged on all 3 routers")
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value, status in zip(
+ ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
+ ):
+ step("{} the neighborship between R2-R3 for vrf RED".format(action))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r3-link1": {"shutdown": value}}}
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable = {
+ "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
+ }
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that R1 and R2 {} all the routes from RED vrf's RIB and"
+ " FIB".format(status)
+ )
+ for dut in ["r1", "r3"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ if value:
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+
+ result = verify_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+ else:
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
new file mode 100644
index 0000000000..1d80a2a64a
--- /dev/null
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
@@ -0,0 +1,932 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test BGP Multi-VRF Dynamic Route Leaking:
+1. Verify recursive import among Tenant VRFs.
+2. Verify that dynamic import works fine between two different Tenant VRFs.
+ When next-hop IPs are same across all VRFs.
+ When next-hop IPs are different across all VRFs.
+3. Verify that with multiple tenant VRFs, dynamic import works fine between
+ Tenant VRFs to default VRF.
+ When next-hop IPs and prefixes are same across all VRFs.
+ When next-hop IPs and prefixes are different across all VRFs.
+"""
+
+import os
+import sys
+import time
+import pytest
+import platform
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topotest import version_cmp
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ check_address_types,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ step,
+ create_route_maps,
+ create_static_routes,
+ create_prefix_lists,
+ create_bgp_community_lists,
+ get_frr_ipv6_linklocal,
+)
+
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_bgp_community,
+ verify_bgp_rib,
+)
+from lib.topojson import build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Global variables
+NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
+NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
+NETWORK1_3 = {"ipv4": "10.10.10.1/32", "ipv6": "10:10::1/128"}
+NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
+NETWORK1_5 = {"ipv4": "110.110.110.1/32", "ipv6": "110:110::1/128"}
+NETWORK1_6 = {"ipv4": "110.110.110.100/32", "ipv6": "110:110::100/128"}
+
+NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
+NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
+NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
+NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
+NETWORK2_5 = {"ipv4": "220.220.220.20/32", "ipv6": "220:220::20/128"}
+NETWORK2_6 = {"ipv4": "220.220.220.200/32", "ipv6": "220:220::200/128"}
+
+NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
+NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
+
+PREFIX_LIST = {
+ "ipv4": ["11.11.11.1", "22.22.22.2", "22.22.22.22"],
+ "ipv6": ["11:11::1", "22:22::2", "22:22::22"],
+}
+PREFERRED_NEXT_HOP = "global"
+VRF_LIST = ["RED", "BLUE", "GREEN"]
+COMM_VAL_1 = "100:100"
+COMM_VAL_2 = "500:500"
+COMM_VAL_3 = "600:600"
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_vrf_dynamic_route_leak_topo4.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start daemons and then start routers
+ start_topology(tgen)
+
+ # Run these tests for kernel version 4.19 or above
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ "BGP vrf dynamic route leak tests will not run "
+ '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
+ )
+ pytest.skip(error_msg)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global BGP_CONVERGENCE
+ global ADDR_TYPES
+ ADDR_TYPES = check_address_types()
+
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format(
+ BGP_CONVERGENCE
+ )
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
+ """
+ Verify that with multiple tenant VRFs, dynamic import works fine between
+ Tenant VRFs to default VRF.
+
+ When next-hop IPs and prefixes are same across all VRFs.
+ When next-hop IPs and prefixes are different across all VRFs.
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step(
+ "Configure static routes on R3 for each vrf and redistribute in "
+ "respective BGP instance"
+ )
+
+ for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
+ step("Configure static route for VRF : {}".format(vrf_name))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [network[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
+ )
+
+ redist_dict = {
+ "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
+ step(
+ "Verify that R3 has installed redistributed routes in respective "
+ "vrfs: {}".format(vrf_name)
+ )
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [network[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name,
+ }
+ ]
+ }
+ }
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Import all tenant vrfs(GREEN+BLUE+RED) in default vrf on R3")
+
+ for vrf_name in ["RED", "BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
+
+ redist_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify on R3 that it installs all the routes(imported from tenant "
+ "VRFs) in default vrf. Additionally, verify that R1 & R2 also "
+ "receive these routes from R3 and install in default vrf, next-hop "
+ "pointing to R3"
+ )
+
+ for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [network[addr_type]],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+
+ for dut in ["r2", "r1"]:
+ next_hop_val = topo["routers"]["r3"]["links"]["{}-link4".format(dut)][
+ addr_type
+ ].split("/")[0]
+
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, static_routes, next_hop=next_hop_val
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(
+ tgen, addr_type, dut, static_routes, next_hop=next_hop_val
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r3", static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value, status in zip(
+ ["Remove", "Add"], [True, False], ["withdraw", "re-install"]
+ ):
+ step(
+ "{} import vrf GREEN/BLUE/RED/all command from default vrf "
+ "instance on R3".format(action)
+ )
+ for vrf_name in ["RED", "BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {"import": {"vrf": vrf_name, "delete": value}}
+ }
+ }
+ )
+
+ import_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that R1,R2 & R3 {} imported routes from GREEN/BLUE/RED/all"
+ " in default vrf's RIB".format(status)
+ )
+ for dut in ["r1", "r2", "r3"]:
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+
+ if value:
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+
+ result = verify_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+ else:
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value in zip(["Shut", "No shut"], [True, False]):
+ step(
+ "{} the neighborship between R1-R3 and R1-R2 for vrf RED, GREEN "
+ "and BLUE".format(action)
+ )
+ bgp_disable = {"r3": {"bgp": []}}
+ for vrf_name in ["RED", "GREEN", "BLUE"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {"r3-link4": {"shutdown": value}}
+ },
+ "r2": {
+ "dest_link": {"r3-link4": {"shutdown": value}}
+ },
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable["r3"]["bgp"].append(
+ {"vrf": vrf_name, "local_as": 3, "address_family": temp}
+ )
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that when peering is shutdown for tenant vrfs, it "
+ "doesn't impact the RIB/FIB of default vrf on router R1 and R2"
+ )
+ for dut in ["r1", "r2"]:
+ step("Verify RIB/FIB for default vrf on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value, status in zip(
+ ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
+ ):
+ step(
+ "{} the neighborship between R1-R3 and R2-R3 for default vrf".format(action)
+ )
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r3-link4": {"shutdown": value}}},
+ "r2": {"dest_link": {"r3-link4": {"shutdown": value}}},
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that R1 and R2 {} all the routes from default vrf's RIB"
+ " and FIB".format(status)
+ )
+ for dut in ["r1", "r2"]:
+ step("Verify RIB/FIB for default vrf on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+
+ if value:
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+
+ result = verify_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+ else:
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Remove import command from router R3 and configure the same on R2")
+ temp = {}
+ for vrf_name in VRF_LIST:
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
+ )
+
+ import_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that once import commands are removed from R3, all imported "
+ "routes are withdrawn from RIB/FIB of default vrf on R1/R2/R3"
+ )
+
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify RIB/FIB for default vrf on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
+ step("Configure static route for VRF : {} on r2".format(vrf_name))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ "r2": {
+ "static_routes": [
+ {
+ "network": [network[addr_type]],
+ "next_hop": "blackhole",
+ "vrf": vrf_name,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, static_routes)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Redistribute static route on BGP VRF : {}".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
+ )
+
+ redist_dict = {
+ "r2": {"bgp": [{"vrf": vrf_name, "local_as": 2, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Remove redistribute static route on BGP VRF : {} on r3".format(vrf_name))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "redistribute": [{"redist_type": "static", "delete": True}]
+ }
+ }
+ }
+ )
+
+ redist_dict = {
+ "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
+ }
+
+ result = create_router_bgp(tgen, topo, redist_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for vrf_name in ["RED", "BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
+
+ import_dict = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify after import commands are re-configured on R2's vrf RED, all "
+ "those routes are installed again in default vrf of R1,R2,R3"
+ )
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Remove import vrf RED/GREEN/BLUE/all one by one from default vrf" " on R2")
+ for vrf_name in ["RED", "BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
+ )
+
+ import_dict = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that R1, R2 and R3 withdraws imported routes from default "
+ "vrf's RIB and FIB "
+ )
+ for dut in ["r1", "r2", "r3"]:
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name, result, static_routes[dut]["static_routes"][0]["network"]
+ )
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
+ assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ step("Add import vrf RED/GREEN/BLUE/all one by one from default vrf on R2")
+ for vrf_name in ["RED", "BLUE", "GREEN"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
+
+ import_dict = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
+
+ result = create_router_bgp(tgen, topo, import_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify that {} reinstall imported routes from vrf RED's RIB".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value in zip(["Shut", "No shut"], [True, False]):
+ step(
+ "{} the neighborship between R2-R3 for vrf GREEN, BLUE and RED".format(
+ action
+ )
+ )
+ bgp_disable = {"r2": {"bgp": []}}
+ for vrf_name in ["GREEN", "BLUE", "RED"]:
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {"r2-link4": {"shutdown": value}}
+ }
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable["r2"]["bgp"].append(
+ {"vrf": vrf_name, "local_as": 2, "address_family": temp}
+ )
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify RIB/FIB of vrf RED will be unchanged on all 3 routers")
+ for dut in ["r1", "r2", "r3"]:
+ step("Verify RIB/FIB for vrf RED on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ for action, value, status in zip(
+ ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
+ ):
+ step("{} the neighborship between R2-R3 for default vrf".format(action))
+ temp = {}
+ for addr_type in ADDR_TYPES:
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {"dest_link": {"r2-link4": {"shutdown": value}}}
+ }
+ }
+ }
+ }
+ )
+
+ bgp_disable = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
+ result = create_router_bgp(tgen, topo, bgp_disable)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that R1 and R2 {} all the routes from default vrfs RIB and"
+ " FIB".format(status)
+ )
+ for dut in ["r1", "r3"]:
+ step("Verify RIB/FIB for default vrf on {}".format(dut))
+ for addr_type in ADDR_TYPES:
+ static_routes = {
+ dut: {
+ "static_routes": [
+ {
+ "network": [
+ NETWORK1_1[addr_type],
+ NETWORK2_1[addr_type],
+ NETWORK3_1[addr_type],
+ ],
+ "next_hop": "blackhole",
+ }
+ ]
+ }
+ }
+
+ if value:
+ result = verify_bgp_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+
+ result = verify_rib(
+ tgen, addr_type, dut, static_routes, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
+ else:
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, dut, static_routes)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4.py
deleted file mode 100644
index 97016caa75..0000000000
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4.py
+++ /dev/null
@@ -1,1909 +0,0 @@
-#!/usr/bin/env python
-
-#
-# Copyright (c) 2021 by VMware, Inc. ("VMware")
-# Used Copyright (c) 2018 by Network Device Education Foundation,
-# Inc. ("NetDEF") in this file.
-#
-# Permission to use, copy, modify, and/or distribute this software
-# for any purpose with or without fee is hereby granted, provided
-# that the above copyright notice and this permission notice appear
-# in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
-# OF THIS SOFTWARE.
-#
-
-"""
-Following tests are covered to test BGP Multi-VRF Dynamic Route Leaking:
-1. Verify recursive import among Tenant VRFs.
-2. Verify that dynamic import works fine between two different Tenant VRFs.
- When next-hop IPs are same across all VRFs.
- When next-hop IPs are different across all VRFs.
-3. Verify that with multiple tenant VRFs, dynamic import works fine between
- Tenant VRFs to default VRF.
- When next-hop IPs and prefixes are same across all VRFs.
- When next-hop IPs and prefixes are different across all VRFs.
-"""
-
-import os
-import sys
-import time
-import pytest
-import platform
-from time import sleep
-
-# Save the Current Working Directory to find configuration files.
-CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(CWD, "../"))
-sys.path.append(os.path.join(CWD, "../lib/"))
-
-# Required to instantiate the topology builder class.
-
-# pylint: disable=C0413
-# Import topogen and topotest helpers
-from lib.topogen import Topogen, get_topogen
-from lib.topotest import version_cmp
-
-from lib.common_config import (
- start_topology,
- write_test_header,
- check_address_types,
- write_test_footer,
- reset_config_on_routers,
- verify_rib,
- step,
- create_route_maps,
- create_static_routes,
- create_prefix_lists,
- create_bgp_community_lists,
- get_frr_ipv6_linklocal,
-)
-
-from lib.topolog import logger
-from lib.bgp import (
- verify_bgp_convergence,
- create_router_bgp,
- verify_bgp_community,
- verify_bgp_rib,
-)
-from lib.topojson import build_config_from_json
-
-pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
-
-# Global variables
-NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
-NETWORK1_2 = {"ipv4": "11.11.11.11/32", "ipv6": "11:11::11/128"}
-NETWORK1_3 = {"ipv4": "10.10.10.1/32", "ipv6": "10:10::1/128"}
-NETWORK1_4 = {"ipv4": "10.10.10.100/32", "ipv6": "10:10::100/128"}
-NETWORK1_5 = {"ipv4": "110.110.110.1/32", "ipv6": "110:110::1/128"}
-NETWORK1_6 = {"ipv4": "110.110.110.100/32", "ipv6": "110:110::100/128"}
-
-NETWORK2_1 = {"ipv4": "22.22.22.2/32", "ipv6": "22:22::2/128"}
-NETWORK2_2 = {"ipv4": "22.22.22.22/32", "ipv6": "22:22::22/128"}
-NETWORK2_3 = {"ipv4": "20.20.20.20/32", "ipv6": "20:20::20/128"}
-NETWORK2_4 = {"ipv4": "20.20.20.200/32", "ipv6": "20:20::200/128"}
-NETWORK2_5 = {"ipv4": "220.220.220.20/32", "ipv6": "220:220::20/128"}
-NETWORK2_6 = {"ipv4": "220.220.220.200/32", "ipv6": "220:220::200/128"}
-
-NETWORK3_1 = {"ipv4": "30.30.30.3/32", "ipv6": "30:30::3/128"}
-NETWORK3_2 = {"ipv4": "30.30.30.30/32", "ipv6": "30:30::30/128"}
-
-PREFIX_LIST = {
- "ipv4": ["11.11.11.1", "22.22.22.2", "22.22.22.22"],
- "ipv6": ["11:11::1", "22:22::2", "22:22::22"],
-}
-PREFERRED_NEXT_HOP = "global"
-VRF_LIST = ["RED", "BLUE", "GREEN"]
-COMM_VAL_1 = "100:100"
-COMM_VAL_2 = "500:500"
-COMM_VAL_3 = "600:600"
-
-
-def setup_module(mod):
- """
- Sets up the pytest environment
-
- * `mod`: module name
- """
-
- testsuite_run_time = time.asctime(time.localtime(time.time()))
- logger.info("Testsuite start time: {}".format(testsuite_run_time))
- logger.info("=" * 40)
-
- logger.info("Running setup_module to create topology")
-
- # This function initiates the topology build with Topogen...
- json_file = "{}/bgp_vrf_dynamic_route_leak_topo4.json".format(CWD)
- tgen = Topogen(json_file, mod.__name__)
- global topo
- topo = tgen.json_topo
- # ... and here it calls Mininet initialization functions.
-
- # Starting topology, create tmp files which are loaded to routers
- # to start daemons and then start routers
- start_topology(tgen)
-
- # Run these tests for kernel version 4.19 or above
- if version_cmp(platform.release(), "4.19") < 0:
- error_msg = (
- "BGP vrf dynamic route leak tests will not run "
- '(have kernel "{}", but it requires >= 4.19)'.format(platform.release())
- )
- pytest.skip(error_msg)
-
- # Creating configuration from JSON
- build_config_from_json(tgen, topo)
-
- global BGP_CONVERGENCE
- global ADDR_TYPES
- ADDR_TYPES = check_address_types()
-
- BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format(
- BGP_CONVERGENCE
- )
-
- logger.info("Running setup_module() done")
-
-
-def teardown_module():
- """Teardown the pytest environment"""
-
- logger.info("Running teardown_module to delete topology")
-
- tgen = get_topogen()
-
- # Stop toplogy and Remove tmp files
- tgen.stop_topology()
-
- logger.info(
- "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
- )
- logger.info("=" * 40)
-
-
-#####################################################
-#
-# Testcases
-#
-#####################################################
-
-
-def test_dynamic_import_recursive_import_tenant_vrf_p1(request):
- """
- Verify recursive import among Tenant VRFs.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
- reset_config_on_routers(tgen)
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step(
- "Configure static routes on R2 for vrf RED and redistribute in "
- "respective BGP instance"
- )
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r2": {
- "static_routes": [
- {
- "network": [NETWORK2_1[addr_type]],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
-
- result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Redistribute static route on BGP VRF RED")
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
- )
-
- redist_dict = {
- "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("Verify that R2 has installed redistributed routes in vrf RED only")
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r2": {
- "static_routes": [{"network": [NETWORK2_1[addr_type]], "vrf": "RED"}]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, "r2", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r2", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Import vrf RED's routes into vrf GREEN on R2")
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": "RED"}}}})
-
- import_dict = {
- "r2": {"bgp": [{"vrf": "GREEN", "local_as": 2, "address_family": temp}]}
- }
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step(
- "Verify on R2, that it installs imported routes from vrf RED to vrf "
- "GREEN's RIB/FIB pointing next-hop to vrf RED"
- )
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r2": {
- "static_routes": [{"network": [NETWORK2_1[addr_type]], "vrf": "GREEN"}]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, "r2", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r2", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("On R3 import routes from vrf GREEN to vrf default")
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": "GREEN"}}}})
-
- import_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step(
- "Verify on R3, that it installs imported routes from vrf GREEN to "
- "vrf default RIB/FIB pointing next-hop to vrf GREEN. "
- )
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r2": {"static_routes": [{"network": [NETWORK2_1[addr_type]]}]}
- }
- result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r3", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("On R4 import routes from vrf default to vrf BLUE")
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": "default"}}}})
-
- import_dict = {
- "r4": {"bgp": [{"vrf": "BLUE", "local_as": 4, "address_family": temp}]}
- }
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step(
- "Verify on R4, that it installs imported routes from vrf default to "
- "vrf BLUE RIB/FIB pointing next-hop to vrf default."
- )
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r4": {
- "static_routes": [{"network": [NETWORK2_1[addr_type]], "vrf": "BLUE"}]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, "r4", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r4", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for dut, vrf_name, vrf_import, as_num in zip(
- ["r2", "r4"], ["GREEN", "BLUE"], ["RED", "default"], [2, 4]
- ):
-
- for action, value in zip(["Delete", "Re-add"], [True, False]):
- step("{} the import command on {} router".format(action, dut))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {"import": {"vrf": vrf_import, "delete": value}}
- }
- }
- )
-
- import_dict = {
- dut: {
- "bgp": [
- {"vrf": vrf_name, "local_as": as_num, "address_family": temp}
- ]
- }
- }
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r4": {
- "static_routes": [
- {"network": [NETWORK2_1[addr_type]], "vrf": "BLUE"}
- ]
- }
- }
- if value:
- result = verify_bgp_rib(
- tgen, addr_type, "r4", static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r4"]["static_routes"][0]["network"],
- )
-
- result = verify_rib(
- tgen, addr_type, "r4", static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes["r4"]["static_routes"][0]["network"],
- )
- else:
- result = verify_bgp_rib(tgen, addr_type, "r4", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r4", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_dynamic_import_routes_between_two_tenant_vrf_p0(request):
- """
- Verify that dynamic import works fine between two different Tenant VRFs.
-
- When next-hop IPs are same across all VRFs.
- When next-hop IPs are different across all VRFs.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
- reset_config_on_routers(tgen)
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step(
- "Configure static routes on R3 for each vrf and redistribute in "
- "respective BGP instance"
- )
-
- for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
- step("Configure static route for VRF : {}".format(vrf_name))
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r3": {
- "static_routes": [
- {
- "network": [network[addr_type]],
- "next_hop": "blackhole",
- "vrf": vrf_name,
- }
- ]
- }
- }
-
- result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Redistribute static route on BGP VRF : {}".format(vrf_name))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
- )
-
- redist_dict = {
- "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
- step(
- "Verify that R3 has installed redistributed routes in respective "
- "vrfs: {}".format(vrf_name)
- )
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r3": {
- "static_routes": [
- {
- "network": [network[addr_type]],
- "next_hop": "blackhole",
- "vrf": vrf_name,
- }
- ]
- }
- }
-
- result = verify_rib(tgen, addr_type, "r3", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Import from vrf GREEN+BLUE into vrf RED on R3")
-
- for vrf_name in ["BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
-
- import_dict = {
- "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify on R1, that it installs all the routes(local+imported) in "
- "vrf RED's RIB/FIB and doesn't get confuse with next-hop attribute, "
- "as all vrfs on R1 are using same IP address for next-hop"
- )
-
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r3": {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
-
- next_hop_1 = topo["routers"]["r3"]["links"]["r1-link1"][addr_type].split("/")[0]
- result = verify_bgp_rib(
- tgen, addr_type, "r1", static_routes, next_hop=next_hop_1
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r1", static_routes, next_hop=next_hop_1)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Remove import vrf GREEN/BLUE/Both command from vrf RED's instance on" " R3")
- for vrf_name in ["BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
- )
-
- import_dict = {
- "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Verify that R1,R2 & R3 withdraw imported routes from vrf RED's RIB")
- for dut in ["r1", "r2", "r3"]:
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \nError {}\n"
- "Routes {} still in BGP table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \nError {}\n"
- "Routes {} still in Route table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
- )
-
- step("Add import vrf GREEN/BLUE/Both command from vrf RED's instance on " "R3")
- for vrf_name in ["BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
-
- import_dict = {
- "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for dut in ["r1", "r2", "r3"]:
- step("Verify that {} reinstall imported routes from vrf RED's RIB".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value in zip(["Shut", "No shut"], [True, False]):
- step(
- "{} the neighborship between R1-R3 and R1-R2 for vrf GREEN, BLUE "
- "and default".format(action)
- )
- bgp_disable = {"r3": {"bgp": []}}
- for vrf_name in ["GREEN", "BLUE", "default"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {"r3-link1": {"shutdown": value}}
- },
- "r2": {
- "dest_link": {"r3-link1": {"shutdown": value}}
- },
- }
- }
- }
- }
- )
-
- bgp_disable["r3"]["bgp"].append(
- {"vrf": vrf_name, "local_as": 3, "address_family": temp}
- )
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Verify RIB/FIB of vrf RED will be unchanged on all 3 routers")
- for dut in ["r1", "r2", "r3"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value, status in zip(
- ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
- ):
- step("{} the neighborship between R1-R3 and R1-R2 for vrf RED".format(action))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r3-link1": {"shutdown": value}}},
- "r2": {"dest_link": {"r3-link1": {"shutdown": value}}},
- }
- }
- }
- }
- )
-
- bgp_disable = {
- "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
- }
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that R1 and R2 {} all the routes from RED vrf's RIB and"
- " FIB".format(status)
- )
- for dut in ["r1", "r2"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
-
- if value:
- result = verify_bgp_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
-
- result = verify_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
- else:
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Remove import command from router R3 and configure the same on R2")
- for vrf_name in ["BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
- )
-
- import_dict = {
- "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that once import commands are removed from R3, all imported "
- "routes are withdrawn from RIB/FIB of vrf RED on R1/R2/R3"
- )
-
- for dut in ["r1", "r2", "r3"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \nError {}\n"
- "Routes {} still in BGP table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
-
- step(
- "Configure static routes on R2 for each vrf and redistribute in "
- "respective BGP instance"
- )
- for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
- step("Configure static route for VRF : {}".format(vrf_name))
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r2": {
- "static_routes": [
- {
- "network": [network[addr_type]],
- "next_hop": "blackhole",
- "vrf": vrf_name,
- }
- ]
- }
- }
-
- result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Redistribute static route on BGP VRF : {}".format(vrf_name))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
- )
-
- redist_dict = {
- "r2": {"bgp": [{"vrf": vrf_name, "local_as": 2, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Remove redistribute static route on BGP VRF : {} on r3".format(vrf_name))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "redistribute": [{"redist_type": "static", "delete": True}]
- }
- }
- }
- )
-
- redist_dict = {
- "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for vrf_name in ["BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
-
- import_dict = {
- "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify after import commands are re-configured on R2's vrf RED, all "
- "those routes are installed again in vrf RED of R1,R2,R3"
- )
- for dut in ["r1", "r2", "r3"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step(
- "Remove/add import vrf GREEN/BLUE/both command from vrf RED's " "instance on R2"
- )
- for vrf_name in ["BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
- )
-
- redist_dict = {
- "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Verify that R1,R2 & R3 withdraw imported routes from vrf RED's RIB")
- for dut in ["r1", "r2", "r3"]:
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \nError {}\n"
- "Routes {} still in BGP table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
-
- step("Add import vrf GREEN/BLUE/Both command from vrf RED's instance on " "R2")
- for vrf_name in ["BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
-
- redist_dict = {
- "r2": {"bgp": [{"vrf": "RED", "local_as": 2, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for dut in ["r1", "r2", "r3"]:
- step("Verify that {} reinstall imported routes from vrf RED's RIB".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [NETWORK2_1[addr_type], NETWORK3_1[addr_type]],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value in zip(["Shut", "No shut"], [True, False]):
- step(
- "{} the neighborship between R2-R3 for vrf GREEN, BLUE and default".format(
- action
- )
- )
- bgp_disable = {"r2": {"bgp": []}}
- for vrf_name in ["GREEN", "BLUE", "default"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {"r2-link1": {"shutdown": value}}
- }
- }
- }
- }
- }
- )
-
- bgp_disable["r2"]["bgp"].append(
- {"vrf": vrf_name, "local_as": 2, "address_family": temp}
- )
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Verify RIB/FIB of vrf RED will be unchanged on all 3 routers")
- for dut in ["r1", "r2", "r3"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value, status in zip(
- ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
- ):
- step("{} the neighborship between R2-R3 for vrf RED".format(action))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r2": {"dest_link": {"r3-link1": {"shutdown": value}}}
- }
- }
- }
- }
- )
-
- bgp_disable = {
- "r3": {"bgp": [{"vrf": "RED", "local_as": 3, "address_family": temp}]}
- }
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that R1 and R2 {} all the routes from RED vrf's RIB and"
- " FIB".format(status)
- )
- for dut in ["r1", "r3"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- "vrf": "RED",
- }
- ]
- }
- }
-
- if value:
- result = verify_bgp_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
-
- result = verify_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
- else:
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
- """
- Verify that with multiple tenant VRFs, dynamic import works fine between
- Tenant VRFs to default VRF.
-
- When next-hop IPs and prefixes are same across all VRFs.
- When next-hop IPs and prefixes are different across all VRFs.
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
- reset_config_on_routers(tgen)
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step(
- "Configure static routes on R3 for each vrf and redistribute in "
- "respective BGP instance"
- )
-
- for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
- step("Configure static route for VRF : {}".format(vrf_name))
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r3": {
- "static_routes": [
- {
- "network": [network[addr_type]],
- "next_hop": "blackhole",
- "vrf": vrf_name,
- }
- ]
- }
- }
-
- result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Redistribute static route on BGP VRF : {}".format(vrf_name))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
- )
-
- redist_dict = {
- "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
- step(
- "Verify that R3 has installed redistributed routes in respective "
- "vrfs: {}".format(vrf_name)
- )
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r3": {
- "static_routes": [
- {
- "network": [network[addr_type]],
- "next_hop": "blackhole",
- "vrf": vrf_name,
- }
- ]
- }
- }
-
- result = verify_rib(tgen, addr_type, "r3", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Import all tenant vrfs(GREEN+BLUE+RED) in default vrf on R3")
-
- for vrf_name in ["RED", "BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
-
- redist_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify on R3 that it installs all the routes(imported from tenant "
- "VRFs) in default vrf. Additionally, verify that R1 & R2 also "
- "receive these routes from R3 and install in default vrf, next-hop "
- "pointing to R3"
- )
-
- for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r3": {
- "static_routes": [
- {
- "network": [network[addr_type]],
- "next_hop": "blackhole",
- }
- ]
- }
- }
-
- for dut in ["r2", "r1"]:
- next_hop_val = topo["routers"]["r3"]["links"]["{}-link4".format(dut)][
- addr_type
- ].split("/")[0]
-
- result = verify_bgp_rib(
- tgen, addr_type, dut, static_routes, next_hop=next_hop_val
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(
- tgen, addr_type, dut, static_routes, next_hop=next_hop_val
- )
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, "r3", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value, status in zip(
- ["Remove", "Add"], [True, False], ["withdraw", "re-install"]
- ):
- step(
- "{} import vrf GREEN/BLUE/RED/all command from default vrf "
- "instance on R3".format(action)
- )
- for vrf_name in ["RED", "BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {"import": {"vrf": vrf_name, "delete": value}}
- }
- }
- )
-
- import_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that R1,R2 & R3 {} imported routes from GREEN/BLUE/RED/all"
- " in default vrf's RIB".format(status)
- )
- for dut in ["r1", "r2", "r3"]:
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
-
- if value:
- result = verify_bgp_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
-
- result = verify_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
- else:
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value in zip(["Shut", "No shut"], [True, False]):
- step(
- "{} the neighborship between R1-R3 and R1-R2 for vrf RED, GREEN "
- "and BLUE".format(action)
- )
- bgp_disable = {"r3": {"bgp": []}}
- for vrf_name in ["RED", "GREEN", "BLUE"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r1": {
- "dest_link": {"r3-link4": {"shutdown": value}}
- },
- "r2": {
- "dest_link": {"r3-link4": {"shutdown": value}}
- },
- }
- }
- }
- }
- )
-
- bgp_disable["r3"]["bgp"].append(
- {"vrf": vrf_name, "local_as": 3, "address_family": temp}
- )
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that when peering is shutdown for tenant vrfs, it "
- "doesn't impact the RIB/FIB of default vrf on router R1 and R2"
- )
- for dut in ["r1", "r2"]:
- step("Verify RIB/FIB for default vrf on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value, status in zip(
- ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
- ):
- step(
- "{} the neighborship between R1-R3 and R2-R3 for default vrf".format(action)
- )
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r1": {"dest_link": {"r3-link4": {"shutdown": value}}},
- "r2": {"dest_link": {"r3-link4": {"shutdown": value}}},
- }
- }
- }
- }
- )
-
- bgp_disable = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that R1 and R2 {} all the routes from default vrf's RIB"
- " and FIB".format(status)
- )
- for dut in ["r1", "r2"]:
- step("Verify RIB/FIB for default vrf on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
-
- if value:
- result = verify_bgp_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
-
- result = verify_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
- else:
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Remove import command from router R3 and configure the same on R2")
- temp = {}
- for vrf_name in VRF_LIST:
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
- )
-
- import_dict = {"r3": {"bgp": [{"local_as": 3, "address_family": temp}]}}
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that once import commands are removed from R3, all imported "
- "routes are withdrawn from RIB/FIB of default vrf on R1/R2/R3"
- )
-
- for dut in ["r1", "r2", "r3"]:
- step("Verify RIB/FIB for default vrf on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \nError {}\n"
- "Routes {} still in BGP table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for vrf_name, network in zip(VRF_LIST, [NETWORK1_1, NETWORK2_1, NETWORK3_1]):
- step("Configure static route for VRF : {} on r2".format(vrf_name))
- for addr_type in ADDR_TYPES:
- static_routes = {
- "r2": {
- "static_routes": [
- {
- "network": [network[addr_type]],
- "next_hop": "blackhole",
- "vrf": vrf_name,
- }
- ]
- }
- }
-
- result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Redistribute static route on BGP VRF : {}".format(vrf_name))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
- )
-
- redist_dict = {
- "r2": {"bgp": [{"vrf": vrf_name, "local_as": 2, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Remove redistribute static route on BGP VRF : {} on r3".format(vrf_name))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "redistribute": [{"redist_type": "static", "delete": True}]
- }
- }
- }
- )
-
- redist_dict = {
- "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
- }
-
- result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for vrf_name in ["RED", "BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
-
- import_dict = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify after import commands are re-configured on R2's vrf RED, all "
- "those routes are installed again in default vrf of R1,R2,R3"
- )
- for dut in ["r1", "r2", "r3"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Remove import vrf RED/GREEN/BLUE/all one by one from default vrf" " on R2")
- for vrf_name in ["RED", "BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {addr_type: {"unicast": {"import": {"vrf": vrf_name, "delete": True}}}}
- )
-
- import_dict = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that R1, R2 and R3 withdraws imported routes from default "
- "vrf's RIB and FIB "
- )
- for dut in ["r1", "r2", "r3"]:
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \nError {}\n"
- "Routes {} still in BGP table".format(
- tc_name, result, static_routes[dut]["static_routes"][0]["network"]
- )
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- step("Add import vrf RED/GREEN/BLUE/all one by one from default vrf on R2")
- for vrf_name in ["RED", "BLUE", "GREEN"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update({addr_type: {"unicast": {"import": {"vrf": vrf_name}}}})
-
- import_dict = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
-
- result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- for dut in ["r1", "r2", "r3"]:
- step("Verify that {} reinstall imported routes from vrf RED's RIB".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value in zip(["Shut", "No shut"], [True, False]):
- step(
- "{} the neighborship between R2-R3 for vrf GREEN, BLUE and RED".format(
- action
- )
- )
- bgp_disable = {"r2": {"bgp": []}}
- for vrf_name in ["GREEN", "BLUE", "RED"]:
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r3": {
- "dest_link": {"r2-link4": {"shutdown": value}}
- }
- }
- }
- }
- }
- )
-
- bgp_disable["r2"]["bgp"].append(
- {"vrf": vrf_name, "local_as": 2, "address_family": temp}
- )
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("Verify RIB/FIB of vrf RED will be unchanged on all 3 routers")
- for dut in ["r1", "r2", "r3"]:
- step("Verify RIB/FIB for vrf RED on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
-
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- for action, value, status in zip(
- ["Shut", "No shut"], [True, False], ["Withdraw", "Reinstall"]
- ):
- step("{} the neighborship between R2-R3 for default vrf".format(action))
- temp = {}
- for addr_type in ADDR_TYPES:
- temp.update(
- {
- addr_type: {
- "unicast": {
- "neighbor": {
- "r3": {"dest_link": {"r2-link4": {"shutdown": value}}}
- }
- }
- }
- }
- )
-
- bgp_disable = {"r2": {"bgp": [{"local_as": 2, "address_family": temp}]}}
- result = create_router_bgp(tgen, topo, bgp_disable)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step(
- "Verify that R1 and R2 {} all the routes from default vrfs RIB and"
- " FIB".format(status)
- )
- for dut in ["r1", "r3"]:
- step("Verify RIB/FIB for default vrf on {}".format(dut))
- for addr_type in ADDR_TYPES:
- static_routes = {
- dut: {
- "static_routes": [
- {
- "network": [
- NETWORK1_1[addr_type],
- NETWORK2_1[addr_type],
- NETWORK3_1[addr_type],
- ],
- "next_hop": "blackhole",
- }
- ]
- }
- }
-
- if value:
- result = verify_bgp_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
-
- result = verify_rib(
- tgen, addr_type, dut, static_routes, expected=False
- )
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
- )
- else:
- result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- result = verify_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}".format(
- tc_name, result
- )
-
- write_test_footer(tc_name)
-
-
-if __name__ == "__main__":
- args = ["-s"] + sys.argv[1:]
- sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf b/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
index 0540a62096..03dfbf9322 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
+++ b/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
@@ -1,11 +1,5 @@
hostname r1
-
-#debug bgp vpn leak-to-vrf
-#debug bgp vpn leak-from-vrf
-#debug bgp nht
-
-
router bgp 99 vrf DONNA
no bgp ebgp-requires-policy
address-family ipv4 unicast
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf b/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf
index 731a00829d..35038557df 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf
+++ b/tests/topotests/bgp_vrf_route_leak_basic/r1/zebra.conf
@@ -16,9 +16,3 @@ int dummy4
ip address 10.0.3.1/24
no shut
!
-int EVA
- no shut
-!
-int DONNA
- no shut
-!
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
index be07c85997..191a0b53ec 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
+++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
@@ -29,7 +29,6 @@ import os
import sys
from functools import partial
import pytest
-import time
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -78,117 +77,7 @@ def teardown_module(mod):
tgen.stop_topology()
-def check_bgp_rib(router, vrf, in_fib):
- if in_fib:
- attr = [{"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}]
- else:
- attr = [{"protocol": "bgp", "nexthops": []}]
-
- if vrf == "DONNA":
- expect = {
- "10.0.0.0/24": [
- {
- "protocol": "connected",
- }
- ],
- "10.0.1.0/24": attr,
- "10.0.2.0/24": [{"protocol": "connected"}],
- "10.0.3.0/24": attr,
- }
- else:
- expect = {
- "10.0.0.0/24": attr,
- "10.0.1.0/24": [
- {
- "protocol": "connected",
- }
- ],
- "10.0.2.0/24": attr,
- "10.0.3.0/24": [
- {
- "protocol": "connected",
- }
- ],
- }
-
- test_func = partial(
- topotest.router_json_cmp, router, "show ip route vrf %s json" % vrf, expect
- )
- return topotest.run_and_expect(test_func, None, count=10, wait=0.5)
-
-
-def check_bgp_fib(router, vrf, in_rib):
- # Check FIB
- # DONNA
- # 10.0.1.0/24 dev EVA proto bgp metric 20
- # 10.0.3.0/24 dev EVA proto bgp metric 20
- # EVA
- # 10.0.0.0/24 dev DONNA proto bgp metric 20
- # 10.0.2.0/24 dev DONNA proto bgp metric 20
-
- if vrf == "DONNA":
- table = 1001
- nh_vrf = "EVA"
- else:
- table = 1002
- nh_vrf = "DONNA"
-
- negate = "" if in_rib else "! "
-
- cmd = "%sip route show table %s | grep %s" % (negate, table, nh_vrf)
- result = False
- retry = 5
- output = ""
- while retry:
- retry -= 1
- try:
- output = router.cmd_raises(cmd)
- result = True
- break
- except:
- time.sleep(0.1)
-
- logger.info("VRF %s leaked FIB content %s: %s", vrf, cmd, output)
-
- return result, output
-
-
-def check_bgp_ping(router, vrf):
- if vrf == "DONNA":
- cmd = "ip vrf exec DONNA ping -c1 10.0.1.1 -I 10.0.0.1"
- else:
- cmd = "ip vrf exec EVA ping -c1 10.0.0.1 -I 10.0.1.1"
-
- result = False
- retry = 5
- output = ""
- while retry:
- retry -= 1
- try:
- output = router.cmd_raises(cmd)
- result = True
- break
- except:
- time.sleep(0.1)
-
- return result, output
-
-
-def check_bgp_ping_own_ip(router):
- cmd = "ip vrf exec DONNA ping -c1 10.0.0.1 -I 10.0.0.1"
-
- output = ""
- try:
- output = router.cmd_raises(cmd)
- result = True
- except:
- result = False
- pass
-
- return result, output
-
-
-def test_vrf_route_leak_test1():
+def test_vrf_route_leak():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
# Don't run this test if we have any failure.
@@ -197,86 +86,53 @@ def test_vrf_route_leak_test1():
r1 = tgen.gears["r1"]
- result, output = check_bgp_ping_own_ip(r1)
- assert (
- result
- ), "Ping from VRF fails - check https://bugzilla.kernel.org/show_bug.cgi?id=203483\n:{}".format(
- output
- )
-
- for vrf in ["EVA", "DONNA"]:
- result, diff = check_bgp_rib(r1, vrf, True)
- assert result, "BGP RIB VRF {} check failed:\n{}".format(vrf, diff)
- result, output = check_bgp_fib(r1, vrf, True)
- assert result, "BGP FIB VRF {} check failed:\n{}".format(vrf, output)
- result, output = check_bgp_ping(r1, vrf)
- assert result, "Ping from VRF {} failed:\n{}".format(vrf, output)
-
+ # Test DONNA VRF.
+ expect = {
+ "10.0.0.0/24": [
+ {
+ "protocol": "connected",
+ }
+ ],
+ "10.0.1.0/24": [
+ {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ ],
+ "10.0.2.0/24": [{"protocol": "connected"}],
+ "10.0.3.0/24": [
+ {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ ],
+ }
-def test_vrf_route_leak_test2():
- logger.info(
- "Ensure that leaked are still present after VRF iface IP address deletion"
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
)
- tgen = get_topogen()
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- r1 = tgen.gears["r1"]
-
- logger.info("Adding and removing an IPv4 address to EVA and DONNA VRF ifaces")
- r1.cmd("ip address add 1.1.1.1/32 dev EVA && ip address del 1.1.1.1/32 dev EVA")
- r1.cmd("ip address add 2.2.2.2/32 dev DONNA && ip address del 2.2.2.2/32 dev DONNA")
-
- for vrf in ["EVA", "DONNA"]:
- result, diff = check_bgp_rib(r1, vrf, True)
- assert result, "BGP RIB VRF {} check failed:\n{}".format(vrf, diff)
- result, output = check_bgp_fib(r1, vrf, True)
- assert result, "BGP FIB VRF {} check failed:\n{}".format(vrf, output)
- result, output = check_bgp_ping(r1, vrf)
- assert result, "Ping from VRF {} failed:\n{}".format(vrf, output)
-
-
-def test_vrf_route_leak_test3():
- logger.info("Ensure that setting down the VRF ifaces invalidates leaked routes")
- tgen = get_topogen()
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- r1 = tgen.gears["r1"]
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+ # Test EVA VRF.
+ expect = {
+ "10.0.0.0/24": [
+ {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ ],
+ "10.0.1.0/24": [
+ {
+ "protocol": "connected",
+ }
+ ],
+ "10.0.2.0/24": [
+ {"protocol": "bgp", "selected": True, "nexthops": [{"fib": True}]}
+ ],
+ "10.0.3.0/24": [
+ {
+ "protocol": "connected",
+ }
+ ],
+ }
- logger.info("Setting down EVA and DONNA VRF ifaces")
- r1.cmd("ip link set EVA down")
- r1.cmd("ip link set DONNA down")
-
- for vrf in ["EVA", "DONNA"]:
- result, diff = check_bgp_rib(r1, vrf, False)
- assert result, "BGP RIB VRF {} check failed:\n{}".format(vrf, diff)
- result, output = check_bgp_fib(r1, vrf, False)
- assert result, "BGP FIB VRF {} check failed:\n{}".format(vrf, output)
-
-
-def test_vrf_route_leak_test4():
- logger.info("Ensure that setting up the VRF ifaces validates leaked routes")
- tgen = get_topogen()
- # Don't run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- r1 = tgen.gears["r1"]
-
- logger.info("Setting up EVA and DONNA VRF ifaces")
- r1.cmd("ip link set EVA up")
- r1.cmd("ip link set DONNA up")
-
- for vrf in ["EVA", "DONNA"]:
- result, diff = check_bgp_rib(r1, vrf, True)
- assert result, "BGP RIB VRF {} check failed:\n{}".format(vrf, diff)
- result, output = check_bgp_fib(r1, vrf, True)
- assert result, "BGP FIB VRF {} check failed:\n{}".format(vrf, output)
- result, output = check_bgp_ping(r1, vrf)
- assert result, "Ping from VRF {} failed:\n{}".format(vrf, output)
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf EVA json", expect
+ )
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF EVA check failed:\n{}".format(diff)
def test_memory_leak():
diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py
index 332ffdf6d5..e92c1c30d1 100644
--- a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py
+++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py
@@ -829,10 +829,11 @@ def test_RT_verification_auto_p0(request):
}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
step(
"Revert back to original VNI number for all 3 VRFs on Edge-1 "
@@ -965,12 +966,11 @@ def test_RT_verification_auto_p0(request):
result = verify_attributes_for_evpn_routes(
tgen, topo, "d2", input_routes_1, rt="auto", rt_peer="e1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Malfaromed Auto-RT value accepted: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Malformed Auto-RT value should not be accepted in {} \n "
+ "Found: {}".format(tc_name, "d2", result)
)
- logger.info("Expected Behavior: {}".format(result))
step("Configure VNI number more than boundary limit (16777215)")
@@ -1000,12 +1000,11 @@ def test_RT_verification_auto_p0(request):
result = verify_attributes_for_evpn_routes(
tgen, topo, "d2", input_routes_1, rt="auto", rt_peer="e1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Malfaromed Auto-RT value accepted: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Malformed Auto-RT value should not be accepted in {} \n "
+ "Found: {}".format(tc_name, "d2", result)
)
- logger.info("Expected Behavior: {}".format(result))
step("Un-configure VNI number more than boundary limit (16777215)")
diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py
index b6a6037128..3ce6c6cb5c 100644
--- a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py
+++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py
@@ -848,17 +848,17 @@ def test_RT_verification_manual_p0(request):
}
result = verify_rib(tgen, addr_type, "d1", input_routes, expected=False)
assert result is not True, (
- "Testcase {} :Failed \n Expected Behavior: Routes are still "
- "present \n Error: {}".format(tc_name, result)
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d1", result)
)
- logger.info("Expected Behavior: {}".format(result))
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
assert result is not True, (
- "Testcase {} :Failed \n Expected Behavior: Routes are still "
- "present \n Error: {}".format(tc_name, result)
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"Configure RT value as 100:100000010000010000101010 to check "
@@ -900,10 +900,10 @@ def test_RT_verification_manual_p0(request):
tgen, topo, dut, input_routes, rt="100:100000010000010000101010", expected=False
)
assert result is not True, (
- "Testcase {} :Failed \n Expected Behavior: RT value of out"
- " of boundary \n Error: {}".format(tc_name, result)
+ "Testcase {} : Failed \n "
+ "Expected: RT value out of boundary error in {} \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
@@ -1316,18 +1316,20 @@ def test_evpn_routes_from_VNFs_p1(request):
for addr_type in ADDR_TYPES:
input_routes = {key: topo["routers"][key] for key in ["r1"]}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase :Failed \n Routes are still present: {}".format(result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
for addr_type in ADDR_TYPES:
input_routes = {key: topo["routers"][key] for key in ["r1"]}
result = verify_rib(tgen, addr_type, "r3", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "r3", result)
+ )
step("Re-advertise IP prefixes from VFN(R1).")
step(
@@ -1401,16 +1403,18 @@ def test_evpn_routes_from_VNFs_p1(request):
}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "r4", result)
+ )
step("Add vrf BLUE on router Edge-1 again.")
interface = topo["routers"]["e1"]["links"]["r2-link1"]["interface"]
@@ -1504,16 +1508,18 @@ def test_evpn_routes_from_VNFs_p1(request):
}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "r4", result)
+ )
step("Advertise IPv6 address-family in EVPN advertisements " "for VRF GREEN.")
addr_type = "ipv6"
diff --git a/tests/topotests/lib/bgprib.py b/tests/topotests/lib/bgprib.py
index 01439373c5..35a57d0a99 100644
--- a/tests/topotests/lib/bgprib.py
+++ b/tests/topotests/lib/bgprib.py
@@ -37,7 +37,6 @@
from lib.lutil import luCommand, luResult, LUtil
import json
import re
-import time
# gpz: get rib in json form and compare against desired routes
class BgpRib:
@@ -49,15 +48,7 @@ class BgpRib:
for pfx in pfxtbl.keys():
if debug:
self.log("trying pfx %s" % pfx)
- if "exist" in want and want["exist"] == False:
- if pfx == want["p"]:
- if debug:
- self.log("unexpected route: pfx=" + want["p"])
- return 0
- if debug:
- self.log("unwant pfx=" + want["p"] + ", not " + pfx)
- continue
- elif pfx != want["p"]:
+ if pfx != want["p"]:
if debug:
self.log("want pfx=" + want["p"] + ", not " + pfx)
continue
@@ -84,67 +75,53 @@ class BgpRib:
if debug:
self.log("missing route: pfx=" + want["p"] + ", nh=" + want["n"])
return 0
- if "exist" in want and want["exist"] == False:
- return 1
- return 0
- def RequireVpnRoutes(self, target, title, wantroutes, retry=0, wait=1, debug=0):
+ def RequireVpnRoutes(self, target, title, wantroutes, debug=0):
import json
logstr = "RequireVpnRoutes " + str(wantroutes)
- retry += 1
- while retry:
- retry -= 1
- # non json form for humans
- luCommand(
- target,
- 'vtysh -c "show bgp ipv4 vpn"',
- ".",
- "None",
- "Get VPN RIB (non-json)",
- )
- ret = luCommand(
- target,
- 'vtysh -c "show bgp ipv4 vpn json"',
- ".*",
- "None",
- "Get VPN RIB (json)",
- )
- if re.search(r"^\s*$", ret):
- # degenerate case: empty json means no routes
- if len(wantroutes) > 0:
- luResult(target, False, title, logstr)
- return
- luResult(target, True, title, logstr)
- rib = json.loads(ret)
- rds = rib["routes"]["routeDistinguishers"]
- for want in wantroutes:
- found = 0
- if debug:
- self.log("want rd %s" % want["rd"])
- for rd in rds.keys():
- if rd != want["rd"]:
- continue
- if debug:
- self.log("found rd %s" % rd)
- table = rds[rd]
- if self.routes_include_wanted(table, want, debug):
- found = 1
- break
- if not found:
- if retry:
- break
- luResult(target, False, title, logstr)
- return
- if not found and retry:
- time.sleep(wait)
- continue
+ # non json form for humans
+ luCommand(
+ target,
+ 'vtysh -c "show bgp ipv4 vpn"',
+ ".",
+ "None",
+ "Get VPN RIB (non-json)",
+ )
+ ret = luCommand(
+ target,
+ 'vtysh -c "show bgp ipv4 vpn json"',
+ ".*",
+ "None",
+ "Get VPN RIB (json)",
+ )
+ if re.search(r"^\s*$", ret):
+ # degenerate case: empty json means no routes
+ if len(wantroutes) > 0:
+ luResult(target, False, title, logstr)
+ return
luResult(target, True, title, logstr)
- break
+ rib = json.loads(ret)
+ rds = rib["routes"]["routeDistinguishers"]
+ for want in wantroutes:
+ found = 0
+ if debug:
+ self.log("want rd %s" % want["rd"])
+ for rd in rds.keys():
+ if rd != want["rd"]:
+ continue
+ if debug:
+ self.log("found rd %s" % rd)
+ table = rds[rd]
+ if self.routes_include_wanted(table, want, debug):
+ found = 1
+ break
+ if not found:
+ luResult(target, False, title, logstr)
+ return
+ luResult(target, True, title, logstr)
- def RequireUnicastRoutes(
- self, target, afi, vrf, title, wantroutes, retry=0, wait=1, debug=0
- ):
+ def RequireUnicastRoutes(self, target, afi, vrf, title, wantroutes, debug=0):
logstr = "RequireUnicastRoutes %s" % str(wantroutes)
vrfstr = ""
if vrf != "":
@@ -153,62 +130,48 @@ class BgpRib:
if (afi != "ipv4") and (afi != "ipv6"):
self.log("ERROR invalid afi")
- retry += 1
- while retry:
- retry -= 1
- cmdstr = "show bgp %s %s unicast" % (vrfstr, afi)
- # non json form for humans
- cmd = 'vtysh -c "%s"' % cmdstr
- luCommand(
- target, cmd, ".", "None", "Get %s %s RIB (non-json)" % (vrfstr, afi)
- )
- cmd = 'vtysh -c "%s json"' % cmdstr
- ret = luCommand(
- target, cmd, ".*", "None", "Get %s %s RIB (json)" % (vrfstr, afi)
- )
- if re.search(r"^\s*$", ret):
- # degenerate case: empty json means no routes
- if len(wantroutes) > 0:
- luResult(target, False, title, logstr)
- return
- luResult(target, True, title, logstr)
- rib = json.loads(ret)
- try:
- table = rib["routes"]
- # KeyError: 'routes' probably means missing/bad VRF
- except KeyError as err:
- if vrf != "":
- errstr = "-script ERROR: check if wrong vrf (%s)" % (vrf)
- else:
- errstr = "-script ERROR: check if vrf missing"
- if retry:
- time.sleep(wait)
- continue
- luResult(target, False, title + errstr, logstr)
+ cmdstr = "show bgp %s %s unicast" % (vrfstr, afi)
+ # non json form for humans
+ cmd = 'vtysh -c "%s"' % cmdstr
+ luCommand(target, cmd, ".", "None", "Get %s %s RIB (non-json)" % (vrfstr, afi))
+ cmd = 'vtysh -c "%s json"' % cmdstr
+ ret = luCommand(
+ target, cmd, ".*", "None", "Get %s %s RIB (json)" % (vrfstr, afi)
+ )
+ if re.search(r"^\s*$", ret):
+ # degenerate case: empty json means no routes
+ if len(wantroutes) > 0:
+ luResult(target, False, title, logstr)
return
- # if debug:
- # self.log("table=%s" % table)
- for want in wantroutes:
- if debug:
- self.log("want=%s" % want)
- if not self.routes_include_wanted(table, want, debug):
- if retry:
- time.sleep(wait)
- continue
- luResult(target, False, title, logstr)
- return
luResult(target, True, title, logstr)
- break
+ rib = json.loads(ret)
+ try:
+ table = rib["routes"]
+ # KeyError: 'routes' probably means missing/bad VRF
+ except KeyError as err:
+ if vrf != "":
+ errstr = "-script ERROR: check if wrong vrf (%s)" % (vrf)
+ else:
+ errstr = "-script ERROR: check if vrf missing"
+ luResult(target, False, title + errstr, logstr)
+ return
+ # if debug:
+ # self.log("table=%s" % table)
+ for want in wantroutes:
+ if debug:
+ self.log("want=%s" % want)
+ if not self.routes_include_wanted(table, want, debug):
+ luResult(target, False, title, logstr)
+ return
+ luResult(target, True, title, logstr)
BgpRib = BgpRib()
-def bgpribRequireVpnRoutes(target, title, wantroutes, retry=0, wait=1, debug=0):
- BgpRib.RequireVpnRoutes(target, title, wantroutes, retry, wait, debug)
+def bgpribRequireVpnRoutes(target, title, wantroutes, debug=0):
+ BgpRib.RequireVpnRoutes(target, title, wantroutes, debug)
-def bgpribRequireUnicastRoutes(
- target, afi, vrf, title, wantroutes, retry=0, wait=1, debug=0
-):
- BgpRib.RequireUnicastRoutes(target, afi, vrf, title, wantroutes, retry, wait, debug)
+def bgpribRequireUnicastRoutes(target, afi, vrf, title, wantroutes, debug=0):
+ BgpRib.RequireUnicastRoutes(target, afi, vrf, title, wantroutes, debug)
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 676a5704e5..8ed37d1a82 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -81,6 +81,26 @@ DEBUG_LOGS = {
"debug pim packets register",
"debug pim nht",
],
+ "pim6d": [
+ "debug pimv6 events",
+ "debug pimv6 packets",
+ "debug pimv6 packet-dump send",
+ "debug pimv6 packet-dump receive",
+ "debug pimv6 trace",
+ "debug pimv6 trace detail",
+ "debug pimv6 zebra",
+ "debug pimv6 bsm",
+ "debug pimv6 packets hello",
+ "debug pimv6 packets joins",
+ "debug pimv6 packets register",
+ "debug pimv6 nht",
+ "debug pimv6 nht detail",
+ "debug mroute6",
+ "debug mroute6 detail",
+ "debug mld events",
+ "debug mld packets",
+ "debug mld trace",
+ ],
"bgpd": [
"debug bgp neighbor-events",
"debug bgp updates",
diff --git a/tests/topotests/lib/lutil.py b/tests/topotests/lib/lutil.py
index 5c1fa24a7b..62c21e9ce4 100644
--- a/tests/topotests/lib/lutil.py
+++ b/tests/topotests/lib/lutil.py
@@ -50,6 +50,7 @@ class lUtil:
l_line = 0
l_dotall_experiment = False
l_last_nl = None
+ l_wait_strict = 1
fout = ""
fsum = ""
@@ -189,7 +190,7 @@ Total %-4d %-4d %d\n\
self.log("unable to read: " + tstFile)
sys.exit(1)
- def command(self, target, command, regexp, op, result, returnJson, startt=None):
+ def command(self, target, command, regexp, op, result, returnJson, startt=None, force_result=False):
global net
if op == "jsoncmp_pass" or op == "jsoncmp_fail":
returnJson = True
@@ -292,7 +293,7 @@ Total %-4d %-4d %d\n\
9,
)
if startt != None:
- if js != None or ret is not False:
+ if js != None or ret is not False or force_result is not False:
delta = time.time() - startt
self.result(target, success, "%s +%4.2f secs" % (result, delta))
elif op == "pass" or op == "fail":
@@ -322,12 +323,23 @@ Total %-4d %-4d %d\n\
n = 0
startt = time.time()
+ if (op == "wait-strict") or ((op == "wait") and self.l_wait_strict):
+ strict = True
+ else:
+ strict = False
+
# Calculate the amount of `sleep`s we are going to peform.
wait_count = int(math.ceil(wait / wait_time)) + 1
+ force_result = False
while wait_count > 0:
n += 1
- found = self.command(target, command, regexp, op, result, returnJson, startt)
+
+ # log a failure on last iteration if we don't get desired regexp
+ if strict and (wait_count == 1):
+ force_result = True
+
+ found = self.command(target, command, regexp, op, result, returnJson, startt, force_result)
if found is not False:
break
@@ -378,12 +390,14 @@ def luCommand(
returnJson=False,
wait_time=0.5,
):
- if op != "wait":
- return LUtil.command(target, command, regexp, op, result, returnJson)
- else:
+ waitops = ["wait", "wait-strict", "wait-nostrict"]
+
+ if op in waitops:
return LUtil.wait(
target, command, regexp, op, result, time, returnJson, wait_time
)
+ else:
+ return LUtil.command(target, command, regexp, op, result, returnJson)
def luLast(usenl=False):
@@ -454,6 +468,25 @@ def luShowFail():
if printed > 0:
logger.error("See %s for details of errors" % LUtil.fout_name)
+#
+# Sets default wait type for luCommand(op="wait) (may be overridden by
+# specifying luCommand(op="wait-strict") or luCommand(op="wait-nostrict")).
+#
+# "nostrict" is the historical default behavior, which is to ignore
+# failures to match the specified regexp in the specified time.
+#
+# "strict" means that failure to match the specified regexp in the
+# specified time yields an explicit, logged failure result
+#
+def luSetWaitType(waittype):
+ if waittype == "strict":
+ LUtil.l_wait_strict = 1
+ else:
+ if waittype == "nostrict":
+ LUtil.l_wait_strict = 0
+ else:
+ raise ValueError('waittype must be one of "strict" or "nostrict"')
+
# for testing
if __name__ == "__main__":
diff --git a/tests/topotests/lib/micronet.py b/tests/topotests/lib/micronet.py
index dfa10ccb2f..ba3d59823c 100644
--- a/tests/topotests/lib/micronet.py
+++ b/tests/topotests/lib/micronet.py
@@ -470,7 +470,8 @@ class LinuxNamespace(Commander):
nslist = []
cmd = ["/usr/bin/unshare"]
- flags = "-"
+ flags = ""
+ self.a_flags = []
self.ifnetns = {}
if cgroup:
@@ -487,6 +488,7 @@ class LinuxNamespace(Commander):
flags += "n"
if pid:
nslist.append("pid")
+ flags += "f"
flags += "p"
cmd.append("--mount-proc")
if time:
@@ -499,9 +501,17 @@ class LinuxNamespace(Commander):
cmd.append("--keep-caps")
if uts:
nslist.append("uts")
- cmd.append("--uts")
+ flags += "u"
- cmd.append(flags)
+ if flags:
+ aflags = flags.replace("f", "")
+ if aflags:
+ self.a_flags = ["-" + x for x in aflags]
+ cmd.extend(["-" + x for x in flags])
+
+ if pid:
+ cmd.append(commander.get_exec_path("tini"))
+ cmd.append("-vvv")
cmd.append("/bin/cat")
# Using cat and a stdin PIPE is nice as it will exit when we do. However, we
@@ -516,7 +526,8 @@ class LinuxNamespace(Commander):
stdin=subprocess.PIPE,
stdout=open("/dev/null", "w"),
stderr=open("/dev/null", "w"),
- preexec_fn=os.setsid, # detach from pgid so signals don't propogate
+ text=True,
+ start_new_session=True, # detach from pgid so signals don't propagate
shell=False,
)
self.p = p
@@ -550,7 +561,7 @@ class LinuxNamespace(Commander):
assert not nslist, "unshare never unshared!"
# Set pre-command based on our namespace proc
- self.base_pre_cmd = ["/usr/bin/nsenter", "-a", "-t", str(self.pid)]
+ self.base_pre_cmd = ["/usr/bin/nsenter", *self.a_flags, "-t", str(self.pid)]
if not pid:
self.base_pre_cmd.append("-F")
self.set_pre_cmd(self.base_pre_cmd + ["--wd=" + self.cwd])
@@ -743,7 +754,7 @@ class SharedNamespace(Commander):
An object that executes commands in an existing pid's linux namespace
"""
- def __init__(self, name, pid, logger=None):
+ def __init__(self, name, pid, aflags=("-a",), logger=None):
"""
Share a linux namespace.
@@ -757,10 +768,11 @@ class SharedNamespace(Commander):
self.pid = pid
self.intfs = []
+ self.a_flags = aflags
# Set pre-command based on our namespace proc
self.set_pre_cmd(
- ["/usr/bin/nsenter", "-a", "-t", str(self.pid), "--wd=" + self.cwd]
+ ["/usr/bin/nsenter", *self.a_flags, "-t", str(self.pid), "--wd=" + self.cwd]
)
def __str__(self):
@@ -769,7 +781,9 @@ class SharedNamespace(Commander):
def set_cwd(self, cwd):
# Set pre-command based on our namespace proc
self.logger.debug("%s: new CWD %s", self, cwd)
- self.set_pre_cmd(["/usr/bin/nsenter", "-a", "-t", str(self.pid), "--wd=" + cwd])
+ self.set_pre_cmd(
+ ["/usr/bin/nsenter", *self.a_flags, "-t", str(self.pid), "--wd=" + cwd]
+ )
def register_interface(self, ifname):
if ifname not in self.intfs:
@@ -800,7 +814,7 @@ class Bridge(SharedNamespace):
self.brid = "br{}".format(self.brid_ord)
name = self.brid
- super(Bridge, self).__init__(name, unet.pid, logger)
+ super(Bridge, self).__init__(name, unet.pid, aflags=unet.a_flags, logger=logger)
self.logger.debug("Bridge: Creating")
diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py
index 7a57af7dbf..32dda82712 100644
--- a/tests/topotests/lib/pim.py
+++ b/tests/topotests/lib/pim.py
@@ -1136,16 +1136,18 @@ def verify_upstream_iif(
if group_addr_json[src_address]["joinState"] != "Joined":
errormsg = (
"[DUT %s]: Verifying iif "
- "(Inbound Interface) for (%s,%s) and"
- " joinState :%s [FAILED]!! "
- " Expected: %s, Found: %s"
+ "(Inbound Interface) and joinState "
+ "for (%s, %s), Expected iif: %s, "
+ "Found iif : %s, and Expected "
+ "joinState :%s , Found joinState: %s"
% (
dut,
src_address,
grp_addr,
- group_addr_json[src_address]["joinState"],
in_interface,
group_addr_json[src_address]["inboundInterface"],
+ joinState,
+ group_addr_json[src_address]["joinState"],
)
)
return errormsg
@@ -1153,16 +1155,18 @@ def verify_upstream_iif(
elif group_addr_json[src_address]["joinState"] != joinState:
errormsg = (
"[DUT %s]: Verifying iif "
- "(Inbound Interface) for (%s,%s) and"
- " joinState :%s [FAILED]!! "
- " Expected: %s, Found: %s"
+ "(Inbound Interface) and joinState "
+ "for (%s, %s), Expected iif: %s, "
+ "Found iif : %s, and Expected "
+ "joinState :%s , Found joinState: %s"
% (
dut,
src_address,
grp_addr,
- group_addr_json[src_address]["joinState"],
in_interface,
group_addr_json[src_address]["inboundInterface"],
+ joinState,
+ group_addr_json[src_address]["joinState"],
)
)
return errormsg
@@ -1171,16 +1175,18 @@ def verify_upstream_iif(
if group_addr_json[src_address]["regState"] != regState:
errormsg = (
"[DUT %s]: Verifying iif "
- "(Inbound Interface) for (%s,%s) and"
- " rejstate :%s [FAILED]!! "
- " Expected: %s, Found: %s"
+ "(Inbound Interface) and regState "
+ "for (%s, %s), Expected iif: %s, "
+ "Found iif : %s, and Expected "
+ "regState :%s , Found regState: %s"
% (
dut,
src_address,
grp_addr,
- group_addr_json[src_address]["regState"],
in_interface,
group_addr_json[src_address]["inboundInterface"],
+ regState,
+ group_addr_json[src_address]["regState"],
)
)
return errormsg
@@ -1212,8 +1218,8 @@ def verify_upstream_iif(
)
return errormsg
- logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
- return True
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return True
@retry(retry_timeout=12)
diff --git a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py
index 285f0dcebc..a6f876f066 100755
--- a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py
+++ b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp1.py
@@ -268,9 +268,6 @@ def test_pim6_add_delete_static_RP_p0(request):
check_router_status(tgen)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Shut link b/w R1 and R3 and R1 and R4 as per testcase topology")
@@ -468,9 +465,6 @@ def test_pim6_SPT_RPT_path_same_p1(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Shut link b/w R1->R3, R1->R4 and R3->R1, R3->R4 as per " "testcase topology")
@@ -644,9 +638,6 @@ def test_pim6_RP_configured_as_LHR_p1(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
@@ -779,9 +770,6 @@ def test_pim6_RP_configured_as_FHR_p1(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
@@ -910,9 +898,6 @@ def test_pim6_SPT_RPT_path_different_p1(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
@@ -1083,9 +1068,6 @@ def test_pim6_send_join_on_higher_preffered_rp_p1(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
diff --git a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py
index 6113635783..b615b9b824 100755
--- a/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py
+++ b/tests/topotests/multicast_pim6_static_rp_topo1/test_multicast_pim6_static_rp2.py
@@ -75,6 +75,7 @@ from lib.common_config import (
socat_send_mld_join,
socat_send_pim6_traffic,
kill_socat,
+ create_debug_log_config,
)
from lib.pim import (
create_pim_config,
@@ -272,11 +273,17 @@ def test_pim6_multiple_groups_same_RP_address_p2(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
+ input_dict = {
+ "r1": {"debug": {"log_file": "r1_debug.log", "enable": ["pim6d"]}},
+ "r2": {"debug": {"log_file": "r2_debug.log", "enable": ["pim6d"]}},
+ "r3": {"debug": {"log_file": "r3_debug.log", "enable": ["pim6d"]}},
+ "r4": {"debug": {"log_file": "r4_debug.log", "enable": ["pim6d"]}},
+ }
+
+ result = create_debug_log_config(tgen, input_dict)
+
step("Enable MLD on r1 interface")
step("Enable the PIM6 on all the interfaces of r1, r2, r3 and r4 routers")
step("r2: Configure r2 as RP")
@@ -594,9 +601,6 @@ def test_pim6_multiple_groups_different_RP_address_p2(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
@@ -673,17 +677,21 @@ def test_pim6_multiple_groups_different_RP_address_p2(request):
step("r1: Verify (*, G) upstream IIF interface")
dut = "r1"
- iif = TOPO["routers"]["r1"]["links"]["r2"]["interface"]
- result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
- assert result is True, ASSERT_MSG.format(tc_name, result)
+ iif1 = TOPO["routers"]["r1"]["links"]["r2"]["interface"]
+ iif2 = TOPO["routers"]["r1"]["links"]["r4"]["interface"]
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, STAR, group_address_list, addr_type="ipv6"
- )
- assert result is True, ASSERT_MSG.format(tc_name, result)
+ for _iif, _group in zip([iif1, iif2], [GROUP_ADDRESS_LIST_1, GROUP_ADDRESS_LIST_2]):
+ result = verify_upstream_iif(tgen, dut, _iif, STAR, _group)
+ assert result is True, ASSERT_MSG.format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, _iif, STAR, _group, addr_type="ipv6"
+ )
+ assert result is True, ASSERT_MSG.format(tc_name, result)
step("r1: Verify (*, G) ip mroutes")
+ iif = TOPO["routers"]["r1"]["links"]["r2"]["interface"]
oif = TOPO["routers"]["r1"]["links"]["r0"]["interface"]
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
assert result is True, ASSERT_MSG.format(tc_name, result)
@@ -1189,9 +1197,6 @@ def test_pim6_delete_RP_shut_noshut_upstream_interface_p1(request):
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
index 83ed8a6360..1f62cb24c9 100644
--- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
+++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
@@ -151,7 +151,7 @@ def setup_module(mod):
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.15")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.15")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
@@ -691,10 +691,10 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
result = verify_rib(
tgen, "ipv4", "f1", input_routes, protocol="static", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "Route is still present \n Error {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "f1", result)
)
# Use scapy to send pre-defined packet from senser to receiver
@@ -740,10 +740,10 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
step("Verify if b1 chosen as BSR in l1")
result = verify_pim_bsr(tgen, topo, "l1", BSR_IP_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "b1 is not chosen as BSR in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: b1 should be chosen as BSR in {} \n "
+ "Found: {}".format(tc_name, "l1", result)
)
state_after = get_pim_interface_traffic(tgen, state_dict)
@@ -788,9 +788,8 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "Routes:[{}, {}] are still present \n Error {}".format(
- tc_name, BSR1_ADDR, CRP, result
- )
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "f1", result)
)
step("Sending BSR after removing black-hole address for BSR and candidate RP")
@@ -915,9 +914,8 @@ def test_new_router_fwd_p0(request):
result = verify_pim_bsr(tgen, topo, "l1", bsr_ip, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "BSR data is present after no-forward bsm also \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: BSR data should not be present after no-forward bsm \n "
+ "Found: {}".format(tc_name, "l1", result)
)
# unconfigure unicast bsm on f1-i1-eth2
@@ -1042,10 +1040,10 @@ def test_int_bsm_config_p1(request):
result = verify_mroutes(
tgen, "i1", src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "Mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should be cleared from mroute table\n "
+ "Found: {}".format(tc_name, "i1", result)
)
# unconfigure bsm processing on f1 on f1-i1-eth2
@@ -1066,10 +1064,10 @@ def test_int_bsm_config_p1(request):
# Verify bsr state in i1
step("Verify if b1 is not chosen as BSR in i1")
result = verify_pim_bsr(tgen, topo, "i1", bsr_ip, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "b1 is chosen as BSR in i1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: b1 should not be chosen as BSR \n "
+ "Found: {}".format(tc_name, "i1", result)
)
# check if mroute still not installed because of rp not available
@@ -1079,7 +1077,8 @@ def test_int_bsm_config_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "mroute installed but rp not available \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: mroute (S, G) should not be installed as RP is not available\n "
+ "Found: {}".format(tc_name, "i1", result)
)
# configure bsm processing on i1 on f1-i1-eth2
@@ -1536,11 +1535,10 @@ def test_BSM_timeout_p0(request):
result = verify_pim_grp_rp_source(
tgen, topo, "f1", group, rp_source="BSR", expected=False
)
-
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "bsr has not aged out in f1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: bsr should be aged out \n "
+ "Found: {}".format(tc_name, "f1", result)
)
# Verify RP mapping removed after hold timer expires
@@ -1567,9 +1565,8 @@ def test_BSM_timeout_p0(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "join state is up and join timer is running in l1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
# Verify ip mroute is not installed
@@ -1577,10 +1574,10 @@ def test_BSM_timeout_p0(request):
result = verify_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be installed \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("clear BSM database before moving to next case")
@@ -1717,10 +1714,10 @@ def test_iif_join_state_p0(request):
result = verify_rib(
tgen, "ipv4", "l1", input_dict, protocol="static", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "Routes:{} are still present \n Error {}".format(
- tc_name, rp_ip, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, "l1", result)
)
# Check RP unreachable
@@ -1742,10 +1739,10 @@ def test_iif_join_state_p0(request):
result = verify_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be installed \n "
+ "Found: {}".format(tc_name, dut, result)
)
# Add back route for RP to make it reachable
diff --git a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
index 3da311a08f..9ad9f0021c 100644
--- a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
+++ b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
@@ -131,7 +131,7 @@ def setup_module(mod):
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.15")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.15")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
@@ -455,10 +455,10 @@ def test_starg_mroute_p0(request):
result = verify_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, retry_timeout=20, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be installed \n "
+ "Found: {}".format(tc_name, dut, result)
)
# Send BSM again to configure rp
@@ -802,10 +802,10 @@ def test_BSR_election_p0(request):
# Verify bsr state in FHR
step("Verify if b2 is not chosen as bsr in f1")
result = verify_pim_bsr(tgen, topo, "f1", bsr_ip2, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "b2 is chosen as bsr in f1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: b2 should not be chosen as bsr \n "
+ "Found: {}".format(tc_name, "f1", result)
)
# Verify if b1 is still chosen as bsr
diff --git a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
index eb841d6504..531fea95b4 100755
--- a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
+++ b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
@@ -159,7 +159,7 @@ def setup_module(mod):
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
@@ -880,12 +880,11 @@ def test_verify_mroute_when_same_receiver_joining_5_diff_sources_p0(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"Source which is stopped got removed , other source"
@@ -1100,12 +1099,11 @@ def test_verify_mroute_when_frr_is_transit_router_p2(request):
result = verify_mroutes(
tgen, "c1", "*", IGMP_JOIN, "c1-c2-eth1", "c1-l1-eth0", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, "c1", result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
@@ -1209,12 +1207,11 @@ def test_verify_mroute_when_RP_unreachable_p1(request):
result = verify_mroutes(
tgen, "f1", "*", IGMP_JOIN, "f1-r2-eth3", "f1-i8-eth2", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, "f1", result)
)
- logger.info("Expected Behavior: {}".format(result))
step("IGMP groups are present verify using 'show ip igmp group'")
dut = "l1"
diff --git a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
index 2775464a54..044f378fb0 100755
--- a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
+++ b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
@@ -157,7 +157,7 @@ def setup_module(mod):
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
@@ -454,12 +454,11 @@ def test_verify_mroute_and_traffic_when_pimd_restarted_p2(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
@@ -663,12 +662,11 @@ def test_verify_mroute_and_traffic_when_frr_restarted_p2(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
@@ -1053,8 +1051,9 @@ def test_verify_mroute_after_shut_noshut_of_upstream_interface_p1(request):
tgen, "l1", "Unknown", source, IGMP_JOIN_RANGE_2, expected=False
)
assert result is not True, (
- "Testcase {} : Failed Error: \n "
- "mroutes are still present, after waiting for 10 mins".format(tc_name)
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF should be unknown \n "
+ "Found: {}".format(tc_name, "l1", result)
)
step("No shut the Source interface just after the upstream is expired" " from FRR1")
@@ -1085,12 +1084,11 @@ def test_verify_mroute_after_shut_noshut_of_upstream_interface_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
@@ -1410,9 +1408,11 @@ def test_verify_mroute_when_FRR_is_FHR_and_LHR_p0(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error: \nmroutes are still present".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
+ )
write_test_footer(tc_name)
@@ -1607,12 +1607,11 @@ def test_verify_mroute_when_5_different_receiver_joining_same_sources_p0(request
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"No traffic impact observed on other receivers verify using"
@@ -1820,12 +1819,11 @@ def test_verify_oil_iif_for_mroute_after_shut_noshut_source_interface_p1(request
"f1-i8-eth2",
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
result = verify_upstream_iif(
tgen, "f1", "Unknown", "10.0.5.2", _IGMP_JOIN_RANGE, joinState="NotJoined"
diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
index 721b30140b..16603ae2d5 100755
--- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
+++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
@@ -171,7 +171,7 @@ def setup_module(mod):
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
@@ -549,12 +549,11 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
input_traffic = {"l1": {"traffic_sent": [intf_l1_i1]}}
result = verify_multicast_traffic(tgen, input_traffic, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " " Traffic is not stopped yet \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Multicast traffic should be stopped \n "
+ "Found: {}".format(tc_name, "l1", result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"IGMP groups are remove from FRR1 node 'show ip igmp groups'"
@@ -565,12 +564,11 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
result = verify_igmp_groups(
tgen, dut, intf_l1_i1, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "IGMP groups are not deleted \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should be deleted \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
dut = "f1"
result = verify_igmp_groups(tgen, dut, intf_f1_i8, IGMP_JOIN_RANGE_1)
@@ -609,12 +607,11 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_l1:
result = verify_upstream_iif(
@@ -627,9 +624,9 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream entries are still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF {} should not be present \n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
input_dict_f1 = [
{
@@ -677,12 +674,11 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
input_traffic = {"f1": {"traffic_sent": [intf_f1_i8]}}
result = verify_multicast_traffic(tgen, input_traffic, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " " Traffic is not stopped yet \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Multicast traffic should be stopped \n "
+ "Found: {}".format(tc_name, "f1", result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"IGMP groups are remove from FRR1 node 'show ip igmp groups'"
@@ -693,12 +689,11 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
result = verify_igmp_groups(
tgen, dut, intf_f1_i8, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "IGMP groups are not deleted \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should be deleted \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"(*,G) and (S,G) OIL got prune state (none) from all the nodes"
@@ -732,12 +727,11 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_l1:
result = verify_upstream_iif(
@@ -750,9 +744,9 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream entries are still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF {} should not be present \n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "f1", intf_f1_i8, True)
shutdown_bringup_interface(tgen, "l1", intf_l1_i1, True)
@@ -920,12 +914,11 @@ def test_verify_oil_when_join_prune_sent_scenario_2_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
input_dict_l1_r2 = [
{
@@ -984,12 +977,11 @@ def test_verify_oil_when_join_prune_sent_scenario_2_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("After prune is sent verify upstream got removed in FRR1 node")
@@ -1004,9 +996,9 @@ def test_verify_oil_when_join_prune_sent_scenario_2_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream entries are still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF {} should not be present \n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
write_test_footer(tc_name)
@@ -1143,12 +1135,11 @@ def test_shut_noshut_source_interface_when_upstream_cleared_from_LHR_p1(request)
result = verify_mroutes(
tgen, "f1", source_i2, IGMP_JOIN_RANGE_1, intf_f1_i2, intf_f1_r2, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, "f1", result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"After waiting for (S,G) timeout from FRR1 for same"
@@ -1159,9 +1150,11 @@ def test_shut_noshut_source_interface_when_upstream_cleared_from_LHR_p1(request)
result = verify_upstream_iif(
tgen, "l1", "Unknown", source_i2, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error: \n mroutes are still present".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF should be Unknown \n "
+ "Found: {}".format(tc_name, "l1", result)
+ )
step("No shut the Source interface just after the upstream is expired" " from FRR1")
shutdown_bringup_interface(tgen, "f1", intf_f1_i2, True)
@@ -1352,9 +1345,11 @@ def test_shut_noshut_receiver_interface_when_upstream_cleared_from_LHR_p1(reques
result = verify_upstream_iif(
tgen, "l1", "Unknown", source_i2, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error: \nmroutes are still present".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF should be Unknown \n "
+ "Found: {}".format(tc_name, "l1", result)
+ )
step("No shut the Source interface just after the upstream is expired" " from FRR1")
shutdown_bringup_interface(tgen, "l1", intf_l1_i1, True)
@@ -1556,12 +1551,11 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
dut = "l1"
interface = topo["routers"]["l1"]["links"]["i1"]["interface"]
result = verify_igmp_groups(tgen, dut, interface, IGMP_JOIN_RANGE_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Groups are not" " present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
intf_l1_r2 = topo["routers"]["l1"]["links"]["r2"]["interface"]
intf_l1_i1 = topo["routers"]["l1"]["links"]["i1"]["interface"]
@@ -1655,12 +1649,11 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
dut = "l1"
interface = topo["routers"]["l1"]["links"]["i1"]["interface"]
result = verify_igmp_groups(tgen, dut, interface, IGMP_JOIN_RANGE_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Groups are not" " present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
result = verify_multicast_traffic(tgen, input_traffic)
assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
@@ -1777,12 +1770,11 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
result = verify_mroutes(
tgen, dut, source, IGMP_JOIN_RANGE_1, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n routes are still" " present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
write_test_footer(tc_name)
@@ -1962,12 +1954,11 @@ def test_verify_remove_add_igmp_commands_when_pim_configured_p0(request):
)
result = verify_igmp_config(tgen, input_dict_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "IGMP interface is not removed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP interface should be removed \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify that no core is observed")
if tgen.routers_have_failure():
@@ -2849,12 +2840,11 @@ def test_mroute_after_removing_RP_sending_IGMP_prune_p2(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_sg:
result = verify_mroutes(
@@ -2886,9 +2876,9 @@ def test_mroute_after_removing_RP_sending_IGMP_prune_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "IGMP groups still present still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: IGMP groups should not present \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"After receiving the IGMP prune from FRR1 , verify traffic "
@@ -3180,12 +3170,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_sg_i1:
result = verify_mroutes(
@@ -3209,12 +3198,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "upstream still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n"
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_sg_i1:
result = verify_upstream_iif(
@@ -3234,12 +3222,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP IIF should be updated as Unknown \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify mroute after No shut the link from LHR to RP from RP node")
@@ -3366,8 +3353,9 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is still present after shut the link from "
- "FHR to RP from RP node \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present"
+ " after shutting link from RP to FHR \n"
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step(" No shut the link from FHR to RP from RP node")
@@ -3383,12 +3371,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP IIF should be updated as Unknown \n"
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify mroute after Noshut the link from FHR to RP from RP node")
@@ -3515,8 +3502,9 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is still present after shut the link from "
- "FHR to RP from FHR node \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present"
+ " after shutting link from FHR to RP \n"
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step(" No shut the link from FHR to RP from FHR node")
@@ -3531,12 +3519,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP IIF should be updated as Unknown \n"
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify mroute after No Shut the link from FHR to RP from FHR node")
@@ -3966,12 +3953,10 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
expected=False,
)
assert result is not True, (
- "Testcase {} : Failed \n"
- " Expected Behaviour: mroutes are cleared \n Error: {}".format(
- tc_name, result
- )
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "r2", intf_r2_i3, True)
@@ -4035,12 +4020,11 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" "mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "l1", intf_l1_i1, True)
@@ -4110,12 +4094,11 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "r2", intf_r2_f1, True)
@@ -4178,12 +4161,11 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
result = verify_mroutes(
tgen, dut, src_address, _IGMP_JOIN_RANGE, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "l1", intf_l1_r2, True)
@@ -4380,12 +4362,11 @@ def test_verify_multicast_traffic_when_FHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("No shut the receiver(l1) port in 1 min interval")
@@ -4446,12 +4427,11 @@ def test_verify_multicast_traffic_when_FHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("No shut the source(r2) port in 1 min interval")
@@ -4518,12 +4498,11 @@ def test_verify_multicast_traffic_when_FHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
write_test_footer(tc_name)
diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
index d209e42a81..91ee026022 100755
--- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
+++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo4.py
@@ -136,7 +136,7 @@ def setup_module(mod):
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
@@ -424,9 +424,8 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "mroutes(S,G) are present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
result = verify_upstream_iif(
@@ -439,9 +438,8 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
for data in input_dict_starg:
@@ -456,9 +454,8 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "mroutes(*,G) are present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
result = verify_upstream_iif(
@@ -471,9 +468,8 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step("Configure default routes on c2")
@@ -499,9 +495,9 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "RP info is unknown after removing static route from c2 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: RP Info should not be Unknown after removing static"
+ " route from c2 \n"
+ "Found: {}".format(tc_name, data["dut"], result)
)
step("Verify (s,g) populated after adding default route ")
@@ -720,10 +716,10 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
result = verify_upstream_iif(
@@ -734,10 +730,10 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "upstream is still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step("Configure default routes on all the nodes")
@@ -777,9 +773,9 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "RP info is unknown after removing static route from c2 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: RP Info should not be Unknown after removing static"
+ " route from c2 \n"
+ "Found: {}".format(tc_name, data["dut"], result)
)
step("Verify (s,g) populated after adding default route ")
diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
index e5182fbecf..772f0751ef 100755
--- a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
+++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
@@ -375,9 +375,8 @@ def test_add_delete_static_RP_p0(request):
result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: igmp group present without any IGMP join \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: IGMP groups should not be present without any IGMP join\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify show ip pim interface traffic without any IGMP join")
@@ -445,17 +444,18 @@ def test_add_delete_static_RP_p0(request):
result = verify_pim_rp_info(
tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: RP info present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP info should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify upstream IIF interface")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IIF interface present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step("r1: Verify upstream join state and join timer")
@@ -464,24 +464,25 @@ def test_add_delete_static_RP_p0(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream join state is up and join timer is running \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
# 20
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: PIM state should not be up \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify show ip pim interface traffic without any IGMP join")
@@ -638,9 +639,8 @@ def test_SPT_RPT_path_same_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S, G) upstream join state is up and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -767,16 +767,16 @@ def test_not_reachable_static_RP_p0(request):
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "OIL is not same and IIF is not cleared on R1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: OIL should be same and IIF should be cleared\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: upstream IIF should be unknown , verify using show ip pim" "upstream")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IIF is not unknown \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should be unknown \n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step(
@@ -788,9 +788,8 @@ def test_not_reachable_static_RP_p0(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: join state is joined and timer is not stopped \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step(
@@ -811,11 +810,9 @@ def test_not_reachable_static_RP_p0(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*, G) are not cleared from mroute table \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared from mroute table\n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behavior: %s", result)
# Uncomment next line for debugging
# tgen.mininet_cli()
@@ -877,10 +874,10 @@ def test_add_RP_after_join_received_p1(request):
result = verify_pim_rp_info(
tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: rp-info is present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP-info should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("joinTx value before join sent")
@@ -905,7 +902,8 @@ def test_add_RP_after_join_received_p1(request):
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IFF interface is present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present \n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step("r1: Verify upstream join state and join timer")
@@ -915,25 +913,24 @@ def test_add_RP_after_join_received_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream join state is joined and timer is running \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: PIM state should not be up\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Configure static RP")
@@ -1058,7 +1055,8 @@ def test_reachable_static_RP_after_join_p0(request):
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IIF interface is present\n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present \n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step("r1 : Verify upstream join state and join timer")
@@ -1067,25 +1065,24 @@ def test_reachable_static_RP_after_join_p0(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream join state is joined and timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1 : Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: PIM state should not be up \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1 : Verify ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Make RP reachable")
@@ -1329,9 +1326,8 @@ def test_send_join_on_higher_preffered_rp_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: rp-info is present for group 225.1.1.1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: RP-info should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step(
diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py
index dbeaa9b8f9..06f3c4110b 100755
--- a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py
+++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py
@@ -536,8 +536,9 @@ def test_RP_configured_as_LHR_1_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S, G) upstream join state is joined and join"
- " timer is running \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -741,9 +742,9 @@ def test_RP_configured_as_LHR_2_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -947,9 +948,9 @@ def test_RP_configured_as_FHR_1_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -1154,9 +1155,9 @@ def test_RP_configured_as_FHR_2_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -1279,9 +1280,9 @@ def test_SPT_RPT_path_different_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -1303,9 +1304,9 @@ def test_SPT_RPT_path_different_p1(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py
index ef638bc964..088b54e33e 100755
--- a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py
+++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py
@@ -452,9 +452,9 @@ def test_restart_pimd_process_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -620,9 +620,9 @@ def test_multiple_groups_same_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -644,9 +644,9 @@ def test_multiple_groups_same_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
@@ -765,9 +765,9 @@ def test_multiple_groups_same_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
@@ -787,9 +787,9 @@ def test_multiple_groups_same_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -963,9 +963,9 @@ def test_multiple_groups_different_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
@@ -985,9 +985,9 @@ def test_multiple_groups_different_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -1053,9 +1053,9 @@ def test_multiple_groups_different_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r4: Verify (S, G) ip mroutes")
@@ -1073,8 +1073,11 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -1224,9 +1227,9 @@ def test_multiple_groups_different_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
@@ -1246,9 +1249,9 @@ def test_multiple_groups_different_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -1314,9 +1317,9 @@ def test_multiple_groups_different_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r4: Verify (S, G) ip mroutes")
@@ -1336,9 +1339,9 @@ def test_multiple_groups_different_RP_address_p2(request):
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
@@ -1462,9 +1465,8 @@ def test_shutdown_primary_path_p1(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (*, G) ip mroutes")
@@ -1474,9 +1476,8 @@ def test_shutdown_primary_path_p1(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (*, G) ip mroutes")
@@ -1486,9 +1487,9 @@ def test_shutdown_primary_path_p1(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R1 to R3 \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: No shutdown the link from R1 to R3 from R3 node")
@@ -1647,9 +1648,9 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R1 to R0 \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (*, G) ip mroutes cleared")
@@ -1659,9 +1660,9 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R1 to R0 \n"
+ "Found: {}".format(tc_name, dut, result)
)
write_test_footer(tc_name)
@@ -1770,9 +1771,9 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R2 to R3 \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (*, G) ip mroutes cleared")
@@ -1782,9 +1783,9 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request):
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R2 to R3 \n"
+ "Found: {}".format(tc_name, dut, result)
)
write_test_footer(tc_name)
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt
index 6bafbbb556..86c089ab3b 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r1/zebra-vrf-default.txt
@@ -5,5 +5,5 @@ B>* 10.0.3.0/24 [20/20] via 10.0.30.3, r1-eth2 (vrf neno), weight 1, XX:XX:XX
O>* 10.0.4.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX
O 10.0.20.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r1-eth1, XX:XX:XX
-B>* 10.0.30.0/24 [20/0] is directly connected, neno (vrf neno), weight 1, XX:XX:XX
+B>* 10.0.30.0/24 [20/0] is directly connected, r1-eth2 (vrf neno), weight 1, XX:XX:XX
O>* 10.0.40.0/24 [110/20] via 10.0.20.2, r1-eth1, weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt
index 3ed6b1b3a1..9681d8a04e 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-default.txt
@@ -7,4 +7,4 @@ B>* 10.0.4.0/24 [20/20] via 10.0.40.4, r2-eth2 (vrf ray), weight 1, XX:XX:XX
O 10.0.20.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX
C>* 10.0.20.0/24 is directly connected, r2-eth1, XX:XX:XX
O>* 10.0.30.0/24 [110/20] via 10.0.20.1, r2-eth1, weight 1, XX:XX:XX
-B>* 10.0.40.0/24 [20/0] is directly connected, ray (vrf ray), weight 1, XX:XX:XX
+B>* 10.0.40.0/24 [20/0] is directly connected, r2-eth2 (vrf ray), weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt
index 4ad8441d85..ce9903ae71 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/r2/zebra-vrf-ray.txt
@@ -1,9 +1,9 @@
VRF ray:
B 10.0.1.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX
-B 10.0.2.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX
+B 10.0.2.0/24 [20/0] is directly connected, r2-eth0 (vrf default) inactive, weight 1, XX:XX:XX
B>* 10.0.3.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX
O>* 10.0.4.0/24 [110/20] via 10.0.40.4, r2-eth2, weight 1, XX:XX:XX
-B 10.0.20.0/24 [20/0] is directly connected, lo (vrf default) inactive, weight 1, XX:XX:XX
+B 10.0.20.0/24 [20/0] is directly connected, r2-eth1 (vrf default) inactive, weight 1, XX:XX:XX
B>* 10.0.30.0/24 [20/20] via 10.0.20.1, r2-eth1 (vrf default), weight 1, XX:XX:XX
O 10.0.40.0/24 [110/10] is directly connected, r2-eth2, weight 1, XX:XX:XX
C>* 10.0.40.0/24 is directly connected, r2-eth2, XX:XX:XX
diff --git a/tests/topotests/pim_basic/test_pim.py b/tests/topotests/pim_basic/test_pim.py
index 2c1bc52d09..ca01a56636 100644
--- a/tests/topotests/pim_basic/test_pim.py
+++ b/tests/topotests/pim_basic/test_pim.py
@@ -125,7 +125,7 @@ def test_pim_rp_setup():
test_func = partial(
topotest.router_json_cmp, r1, "show ip pim rp-info json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=15, wait=5)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(r1.name)
assert result is None, assertmsg
# tgen.mininet_cli()
@@ -148,13 +148,13 @@ def test_pim_send_mcast_stream():
# 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(
+ "{}/mcast-tx.py --ttl 5 --count 40 --interval 2 229.1.1.1 r2-eth0 > /tmp/bar".format(
CWD
)
)
# And from r3 -> r1
r3.run(
- "{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r3-eth0 > /tmp/bar".format(
+ "{}/mcast-tx.py --ttl 5 --count 40 --interval 2 229.1.1.1 r3-eth0 > /tmp/bar".format(
CWD
)
)
@@ -175,7 +175,7 @@ def test_pim_send_mcast_stream():
test_func = partial(
topotest.router_json_cmp, r1, "show ip pim upstream json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=1)
assert result is None, "failed to converge pim"
# tgen.mininet_cli()
@@ -191,7 +191,7 @@ def test_pim_rp_sees_stream():
test_func = partial(
topotest.router_json_cmp, rp, "show ip pim upstream json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(rp.name)
assert result is None, assertmsg
@@ -225,7 +225,7 @@ def test_pim_igmp_report():
test_func = partial(
topotest.router_json_cmp, r1, "show ip pim upstream json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(r1.name)
assert result is None, assertmsg
finally:
diff --git a/tests/topotests/pim_igmp_vrf/test_pim_vrf.py b/tests/topotests/pim_igmp_vrf/test_pim_vrf.py
index f845a4a6ee..64001deade 100755
--- a/tests/topotests/pim_igmp_vrf/test_pim_vrf.py
+++ b/tests/topotests/pim_igmp_vrf/test_pim_vrf.py
@@ -166,6 +166,11 @@ def setup_module(module):
tgen = Topogen(build_topo, module.__name__)
tgen.start_topology()
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("4.19")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
vrf_setup_cmds = [
"ip link add name blue type vrf table 11",
"ip link add name red type vrf table 12",
@@ -210,11 +215,6 @@ def test_ospf_convergence():
"Test for OSPFv2 convergence"
tgen = get_topogen()
- # Required linux kernel version for this suite to run.
- result = required_linux_kernel_version("4.15")
- if result is not True:
- pytest.skip("Kernel requirements are not met")
-
# iproute2 needs to support VRFs for this suite to run.
if not iproute2_is_vrf_capable():
pytest.skip("Installed iproute2 version does not support VRFs")
diff --git a/tests/topotests/route_scale/scale_test_common.py b/tests/topotests/route_scale/scale_test_common.py
index 856a2d0fa7..b9f324d561 100644
--- a/tests/topotests/route_scale/scale_test_common.py
+++ b/tests/topotests/route_scale/scale_test_common.py
@@ -178,7 +178,7 @@ def route_install_helper(iter):
# Table of defaults, used for timeout values and 'expected' objects
scale_defaults = dict(
- zip(scale_keys, [None, None, 7, 30, expected_installed, expected_removed])
+ zip(scale_keys, [None, None, 10, 50, expected_installed, expected_removed])
)
# List of params for each step in the test; note extra time given
diff --git a/tests/topotests/zebra_netlink/test_zebra_netlink.py b/tests/topotests/zebra_netlink/test_zebra_netlink.py
index ca90c5cb15..6d7b99291a 100644
--- a/tests/topotests/zebra_netlink/test_zebra_netlink.py
+++ b/tests/topotests/zebra_netlink/test_zebra_netlink.py
@@ -109,7 +109,7 @@ def test_zebra_netlink_batching(tgen):
pfx = str(ipaddress.ip_network((i, 32)))
match[pfx] = [dict(entry, prefix=pfx)]
- ok = topotest.router_json_cmp_retry(r1, "show ip route json", match)
+ ok = topotest.router_json_cmp_retry(r1, "show ip route json", match, False, 30)
assert ok, '"r1" JSON output mismatches'
r1.vtysh_cmd("sharp remove routes 2.1.3.7 " + str(count))
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index bf402e1bef..dfbc9b8008 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -1914,6 +1914,7 @@ if __name__ == "__main__":
"bgpd",
"fabricd",
"isisd",
+ "babeld",
"ospf6d",
"ospfd",
"pbrd",
@@ -1925,6 +1926,7 @@ if __name__ == "__main__":
"staticd",
"vrrpd",
"ldpd",
+ "nhrpd",
"pathd",
"bfdd",
"eigrpd",
diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang
index 08b6073479..d3e756e0bf 100644
--- a/yang/frr-bfdd.yang
+++ b/yang/frr-bfdd.yang
@@ -242,6 +242,36 @@ module frr-bfdd {
}
}
+ grouping bfd-monitoring {
+ description
+ "BFD monitoring template for protocol integration.";
+
+ leaf source {
+ type inet:ip-address;
+ description
+ "Source address to use for liveness check.
+
+ When source is not set and multi-hop is `false` the source
+ address will be `0.0.0.0` (any).
+
+ When source is not set and multi-hop is `true` the source
+ address will be automatic selected through Next Hop Tracking (NHT).";
+ }
+
+ leaf multi-hop {
+ description
+ "Use multi hop session instead of single hop.";
+ type boolean;
+ default false;
+ }
+
+ leaf profile {
+ description
+ "BFD pre configured profile.";
+ type frr-bfdd:profile-ref;
+ }
+ }
+
grouping session-states {
/*
* Local settings.
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 380fce3859..5483410d04 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -881,6 +881,9 @@ module frr-isisd {
description
"This leaf describes the state of the interface.";
}
+
+ uses adjacency-sids;
+ uses lan-adjacency-sids;
}
}
}
@@ -1004,6 +1007,76 @@ module frr-isisd {
}
}
+ grouping adjacency-sids {
+ description
+ "IS-IS segment routing adjacency SID grouping.";
+ container adjacency-sids {
+ description
+ "This container lists the information of adjacency SID.";
+ list adjacency-sid {
+ leaf af {
+ type uint8;
+ description
+ "This leaf describes the protocol-family associated with the
+ adjacency SID.";
+ }
+
+ leaf value {
+ type uint32;
+ description
+ "This leaf describes the value of adjacency SID.";
+ }
+
+ leaf weight {
+ type uint8;
+ description
+ "This leaf describes the weight of the adjacency SID.";
+ }
+
+ leaf protection-requested {
+ type boolean;
+ description
+ "This leaf describes if the adjacency SID must be protected.";
+ }
+ }
+ }
+ }
+
+ grouping lan-adjacency-sids {
+ description
+ "IS-IS segment routing LAN adjacency SID grouping.";
+ container lan-adjacency-sids {
+ description
+ "This container lists the information of LAN adjacency SID.";
+ list lan-adjacency-sid {
+ leaf af {
+ type uint8;
+ description
+ "This leaf describes the protocol-family associated with the
+ LAN adjacency SID.";
+ }
+
+ leaf value {
+ type uint32;
+ description
+ "This leaf describes the value of LAN adjacency SID.";
+ }
+
+ leaf weight {
+ type uint8;
+ description
+ "This leaf describes the weight of the LAN adjacency SID.";
+ }
+
+ leaf protection-requested {
+ type boolean;
+ description
+ "This leaf describes if the LAN adjacency SID must be protected.";
+ }
+ }
+ }
+ }
+
container isis {
description
"Configuration of the IS-IS routing daemon.";
diff --git a/yang/frr-staticd.yang b/yang/frr-staticd.yang
index 98ff3a83c6..cb5e25b877 100644
--- a/yang/frr-staticd.yang
+++ b/yang/frr-staticd.yang
@@ -15,6 +15,10 @@ module frr-staticd {
prefix inet;
}
+ import frr-bfdd {
+ prefix frr-bfdd;
+ }
+
organization
"FRRouting";
contact
@@ -114,7 +118,19 @@ module frr-staticd {
"AFI-SAFI type.";
}
- uses staticd-prefix-attributes;
+ uses staticd-prefix-attributes {
+ augment "path-list/frr-nexthops/nexthop" {
+ container bfd-monitoring {
+ description "BFD monitoring options.";
+ presence
+ "Present if BFD configuration is available.";
+
+ when "../nh-type = 'ip4' or ../nh-type = 'ip4-ifindex' or
+ ../nh-type = 'ip6' or ../nh-type = 'ip6-ifindex'";
+ uses frr-bfdd:bfd-monitoring;
+ }
+ }
+ }
list src-list {
key "src-prefix";
diff --git a/zebra/connected.c b/zebra/connected.c
index 57c7f1925b..c01be58e82 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -387,14 +387,10 @@ void connected_down(struct interface *ifp, struct connected *ifc)
.ifindex = ifp->ifindex,
.vrf_id = ifp->vrf->vrf_id,
};
- struct zebra_vrf *zvrf, *zvrf_iter;
- uint32_t count_ipv4 = 0;
+ struct zebra_vrf *zvrf;
+ uint32_t count = 0;
struct listnode *cnode;
struct connected *c;
- struct route_table *table;
- struct route_node *rn;
- struct route_entry *re, *next;
- struct vrf *vrf;
zvrf = ifp->vrf->info;
if (!zvrf) {
@@ -460,14 +456,12 @@ void connected_down(struct interface *ifp, struct connected *ifc)
prefix_copy(&cp, CONNECTED_PREFIX(c));
apply_mask(&cp);
- if (CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
- continue;
+ if (prefix_same(&p, &cp) &&
+ !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN))
+ count++;
- if (prefix_same(&p, &cp))
+ if (count >= 1)
return;
-
- if (cp.family == AF_INET)
- count_ipv4++;
}
/*
@@ -480,60 +474,6 @@ void connected_down(struct interface *ifp, struct connected *ifc)
rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false);
- /* When the last IPv4 address of an interface is deleted, Linux removes
- * all routes using this interface without any Netlink advertisement.
- * The removed routes include those that only have this particular
- * interface as a nexthop. Among those, remove the kernel one from the
- * FRR RIB and reinstall the other that have been added from FRR.
- */
- if (afi == AFI_IP && count_ipv4 == 0 && if_is_operative(ifp)) {
- RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- zvrf_iter = vrf->info;
-
- if (!zvrf_iter)
- continue;
-
- table = zvrf_iter->table[AFI_IP][SAFI_UNICAST];
- if (!table)
- continue;
-
- for (rn = route_top(table); rn;
- rn = srcdest_route_next(rn)) {
- RNODE_FOREACH_RE_SAFE (rn, re, next) {
- if (CHECK_FLAG(re->status,
- ROUTE_ENTRY_REMOVED))
- continue;
- if (re->nhe->ifp != ifp)
- continue;
- if (re->type == ZEBRA_ROUTE_KERNEL)
- rib_delete(
- afi, SAFI_UNICAST,
- zvrf_iter->vrf->vrf_id,
- re->type, 0, re->flags,
- &rn->p, NULL, &nh, 0,
- zvrf_iter->table_id,
- re->metric,
- re->distance, false);
- else if (re->type !=
- ZEBRA_ROUTE_CONNECT) {
- SET_FLAG(re->status,
- ROUTE_ENTRY_CHANGED);
- UNSET_FLAG(
- re->status,
- ROUTE_ENTRY_INSTALLED);
- rib_add(afi, SAFI_UNICAST,
- zvrf_iter->vrf->vrf_id,
- re->type, 0, 0, &rn->p,
- NULL, &nh, re->nhe_id,
- zvrf_iter->table_id,
- re->metric, 0,
- re->distance, 0, false);
- }
- }
- }
- }
- }
-
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
if (IS_ZEBRA_DEBUG_MPLS)
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 8550d7e304..af75ddf742 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -604,7 +604,10 @@ static void fpm_read(struct thread *t)
hdr, 0, false, ctx) != 1) {
dplane_ctx_fini(&ctx);
stream_pulldown(fnc->ibuf);
- return;
+ /*
+ * Let's continue to read other messages
+ * Even if we ignore this one.
+ */
}
break;
default:
diff --git a/zebra/interface.c b/zebra/interface.c
index 87bb49042a..59563834ef 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1436,7 +1436,8 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"%s: if %s(%u) zebra info pointer is NULL",
- __func__, ifp->name, ifp->ifindex);
+ __func__, ifp ? ifp->name : "(null)",
+ ifp ? ifp->ifindex : ifindex);
return;
}
if (afi == AFI_IP) {
diff --git a/zebra/rt.h b/zebra/rt.h
index d8a22d2cfc..4cf4c9d780 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -35,6 +35,8 @@
extern "C" {
#endif
+#define ROUTE_INSTALLATION_METRIC 20
+
#define RKERNEL_ROUTE(type) ((type) == ZEBRA_ROUTE_KERNEL)
#define RSYSTEM_ROUTE(type) \
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 10725665e8..79d79d74be 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -223,7 +223,7 @@ static inline bool is_selfroute(int proto)
return false;
}
-static inline int zebra2proto(int proto)
+int zebra2proto(int proto)
{
switch (proto) {
case ZEBRA_ROUTE_BABEL:
@@ -2077,7 +2077,7 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
* by the routing protocol and for communicating with protocol peers.
*/
if (!nl_attr_put32(&req->n, datalen, RTA_PRIORITY,
- NL_DEFAULT_ROUTE_METRIC))
+ ROUTE_INSTALLATION_METRIC))
return 0;
#if defined(SUPPORT_REALMS)
@@ -4389,7 +4389,7 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
"Tx %s family %s IF %s(%u) Neigh %pIA %s %s flags 0x%x state 0x%x %sext_flags 0x%x",
nl_msg_type_to_str(cmd), nl_family_to_str(family),
dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx),
- ip, link_ip ? "Link " : "MAC ", buf2, flags, state,
+ ip, link_ip ? "Link" : "MAC", buf2, flags, state,
ext ? "ext " : "", ext_flags);
return netlink_neigh_update_msg_encode(
diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h
index b67169d6f0..8506367ae4 100644
--- a/zebra/rt_netlink.h
+++ b/zebra/rt_netlink.h
@@ -30,7 +30,6 @@
extern "C" {
#endif
-#define NL_DEFAULT_ROUTE_METRIC 20
/*
* Additional protocol strings to push into routes
@@ -151,6 +150,9 @@ const char *ifa_flags2str(uint32_t flags, char *buf, size_t buflen);
const char *nh_flags2str(uint32_t flags, char *buf, size_t buflen);
void nl_dump(void *msg, size_t msglen);
+
+extern int zebra2proto(int proto);
+
#endif /* NETLINK_DEBUG */
#ifdef __cplusplus
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 84dae7f2d6..739f6adce9 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -5070,8 +5070,8 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
ipaddr2str(link_ip, buf1, sizeof(buf1));
zlog_debug("init neigh ctx %s: ifp %s, %s %s, ip %pIA",
dplane_op2str(op), ifp->name,
- link_family == AF_ETHERNET ? "mac " : "link ",
- buf1, ip);
+ link_family == AF_ETHERNET ? "mac" : "link", buf1,
+ ip);
}
ctx = dplane_ctx_alloc();
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 218184ad0d..2c953eef15 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -653,8 +653,13 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
json_object_int_add(json_mac, "vlan", vid);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
json_object_string_add(json_mac, "type", "remote");
- json_object_string_addf(json_mac, "remoteVtep", "%pI4",
- &mac->fwd_info.r_vtep_ip);
+ if (mac->es)
+ json_object_string_add(json_mac, "remoteEs",
+ mac->es->esi_str);
+ else
+ json_object_string_addf(
+ json_mac, "remoteVtep", "%pI4",
+ &mac->fwd_info.r_vtep_ip);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
json_object_string_add(json_mac, "type", "auto");
@@ -937,8 +942,13 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
"", mac->loc_seq, mac->rem_seq);
} else {
json_object_string_add(json_mac, "type", "remote");
- json_object_string_addf(json_mac, "remoteVtep", "%pI4",
- &mac->fwd_info.r_vtep_ip);
+ if (mac->es)
+ json_object_string_add(json_mac, "remoteEs",
+ mac->es->esi_str);
+ else
+ json_object_string_addf(
+ json_mac, "remoteVtep", "%pI4",
+ &mac->fwd_info.r_vtep_ip);
json_object_object_add(json_mac_hdr, buf1, json_mac);
json_object_int_add(json_mac, "localSequence",
mac->loc_seq);
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index 5cefa16cdd..06c45578a6 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -253,14 +253,7 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri,
*/
static uint8_t netlink_proto_from_route_type(int type)
{
- switch (type) {
- case ZEBRA_ROUTE_KERNEL:
- case ZEBRA_ROUTE_CONNECT:
- return RTPROT_KERNEL;
-
- default:
- return RTPROT_ZEBRA;
- }
+ return zebra2proto(type);
}
/*
@@ -511,7 +504,7 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
done:
if (ri->pref_src) {
- nl_attr_put(&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src,
+ nl_attr_put(&req->n, in_buf_len, RTA_PREFSRC, ri->pref_src,
bytelen);
}
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 6ad54d5c50..50b7ff9233 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -288,6 +288,7 @@ static void zebra_ns_notify_read(struct thread *t)
struct inotify_event *event;
char buf[BUFSIZ];
ssize_t len;
+ char event_name[NAME_MAX + 1];
thread_add_read(zrouter.master, zebra_ns_notify_read, NULL, fd_monitor,
&zebra_netns_notify_current);
@@ -320,11 +321,41 @@ static void zebra_ns_notify_read(struct thread *t)
break;
}
+ /*
+ * Coverity Scan extra steps to satisfy `STRING_NULL` warning:
+ * - Make sure event name is present by checking `len != 0`
+ * - Event name length must be at most `NAME_MAX + 1`
+ * (null byte inclusive)
+ * - Copy event name to a stack buffer to make sure it
+ * includes the null byte. `event->name` includes at least
+ * one null byte and `event->len` accounts the null bytes,
+ * so the operation after `memcpy` will look like a
+ * truncation to satisfy Coverity Scan null byte ending.
+ *
+ * Example:
+ * if `event->name` is `abc\0` and `event->len` is 4,
+ * `memcpy` will copy the 4 bytes and then we set the
+ * null byte again at the position 4.
+ *
+ * For more information please read inotify(7) man page.
+ */
+ if (event->len == 0)
+ continue;
+
+ if (event->len > sizeof(event_name)) {
+ flog_err(EC_ZEBRA_NS_NOTIFY_READ,
+ "NS notify error: unexpected big event name");
+ break;
+ }
+
+ memcpy(event_name, event->name, event->len);
+ event_name[event->len - 1] = 0;
+
if (event->mask & IN_DELETE) {
- zebra_ns_delete(event->name);
+ zebra_ns_delete(event_name);
continue;
}
- netnspath = ns_netns_pathname(NULL, event->name);
+ netnspath = ns_netns_pathname(NULL, event_name);
if (!netnspath)
continue;
netnspath = XSTRDUP(MTYPE_NETNS_MISC, netnspath);
diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h
index f8e843cc73..2eed7f301c 100644
--- a/zebra/zebra_ptm.h
+++ b/zebra/zebra_ptm.h
@@ -63,14 +63,12 @@ struct zebra_ptm_cb {
#define ZEBRA_IF_PTM_ENABLE_ON 1
#define ZEBRA_IF_PTM_ENABLE_UNSPEC 2
-#define IS_BFD_ENABLED_PROTOCOL(protocol) ( \
- (protocol) == ZEBRA_ROUTE_BGP || \
- (protocol) == ZEBRA_ROUTE_OSPF || \
- (protocol) == ZEBRA_ROUTE_OSPF6 || \
- (protocol) == ZEBRA_ROUTE_ISIS || \
- (protocol) == ZEBRA_ROUTE_PIM || \
- (protocol) == ZEBRA_ROUTE_OPENFABRIC \
-)
+#define IS_BFD_ENABLED_PROTOCOL(protocol) \
+ ((protocol) == ZEBRA_ROUTE_BGP || (protocol) == ZEBRA_ROUTE_OSPF || \
+ (protocol) == ZEBRA_ROUTE_OSPF6 || (protocol) == ZEBRA_ROUTE_ISIS || \
+ (protocol) == ZEBRA_ROUTE_PIM || \
+ (protocol) == ZEBRA_ROUTE_OPENFABRIC || \
+ (protocol) == ZEBRA_ROUTE_STATIC)
void zebra_ptm_init(void);
void zebra_ptm_finish(void);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 9551f26d80..81910f68b7 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1306,6 +1306,7 @@ static void rib_process(struct route_node *rn)
vrf),
vrf_id, rn);
rib_unlink(rn, re);
+ continue;
} else
SET_FLAG(re->status,
ROUTE_ENTRY_REMOVED);
@@ -2711,10 +2712,6 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
if (ere->src_p_provided)
apply_mask_ipv6(&ere->src_p);
- /* Set default distance by route type. */
- if (re->distance == 0)
- re->distance = route_distance(re->type);
-
/* Lookup route node.*/
rn = srcdest_rnode_get(table, &ere->p,
ere->src_p_provided ? &ere->src_p : NULL);
@@ -2761,6 +2758,22 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
}
}
+ /* Set default distance by route type. */
+ if (re->distance == 0) {
+ if (same && !zebra_router_notify_on_ack())
+ re->distance = same->distance;
+ else
+ re->distance = route_distance(re->type);
+ }
+
+ if (re->metric == ROUTE_INSTALLATION_METRIC &&
+ CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE)) {
+ if (same && !zebra_router_notify_on_ack())
+ re->metric = same->metric;
+ else
+ re->metric = 0;
+ }
+
/* If this route is kernel/connected route, notify the dataplane. */
if (RIB_SYSTEM_ROUTE(re)) {
/* Notify dataplane */
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index aac1c9b471..ccd6eb2631 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -3169,11 +3169,11 @@ DEFUN (no_vrf_vni_mapping,
}
/* show vrf */
-DEFUN (show_vrf_vni,
+DEFPY (show_vrf_vni,
show_vrf_vni_cmd,
- "show vrf vni [json]",
+ "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
SHOW_STR
- "VRF\n"
+ VRF_FULL_CMD_HELP_STR
"VNI\n"
JSON_STR)
{
@@ -3182,20 +3182,69 @@ DEFUN (show_vrf_vni,
json_object *json = NULL;
json_object *json_vrfs = NULL;
bool uj = use_json(argc, argv);
+ bool use_vrf = false;
- if (uj) {
+ if (uj)
json = json_object_new_object();
- json_vrfs = json_object_new_array();
+
+ /* show vrf vni used to display across all vrfs
+ * This is enhanced to support only for specific
+ * vrf based output.
+ */
+ if (vrf_all || !vrf_name) {
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ zvrf = vrf->info;
+ if (!zvrf)
+ continue;
+
+ use_vrf = true;
+ break;
+ }
+ if (use_vrf) {
+ if (!uj)
+ vty_out(vty,
+ "%-37s %-10s %-20s %-20s %-5s %-18s\n",
+ "VRF", "VNI", "VxLAN IF", "L3-SVI",
+ "State", "Rmac");
+ else
+ json_vrfs = json_object_new_array();
+ } else {
+ if (uj)
+ vty_json(vty, json);
+ else
+ vty_out(vty, "%% VRF does not exist\n");
+
+ return CMD_WARNING;
+ }
}
- if (!uj)
- vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
- "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
+ if (use_vrf) {
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ zvrf = vrf->info;
+ if (!zvrf)
+ continue;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- zvrf = vrf->info;
- if (!zvrf)
- continue;
+ zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
+ }
+ } else if (vrf_name) {
+ zvrf = zebra_vrf_lookup_by_name(vrf_name);
+ if (!zvrf) {
+ if (uj)
+ vty_json(vty, json);
+ else
+ vty_out(vty,
+ "%% VRF '%s' specified does not exist\n",
+ vrf_name);
+
+ return CMD_WARNING;
+ }
+
+ if (!uj)
+ vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
+ "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
+ "Rmac");
+ else
+ json_vrfs = json_object_new_array();
zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
}
@@ -3511,7 +3560,26 @@ DEFUN (show_evpn_mac_vni,
vni = strtoul(argv[4]->arg, NULL, 10);
zvrf = zebra_vrf_get_evpn();
- zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
+ zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj, false);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_evpn_mac_vni_detail,
+ show_evpn_mac_vni_detail_cmd,
+ "show evpn mac vni " CMD_VNI_RANGE " detail [json]",
+ SHOW_STR
+ "EVPN\n"
+ "MAC addresses\n"
+ "VXLAN Network Identifier\n"
+ "VNI number\n"
+ "Detailed Information On Each VNI MAC\n"
+ JSON_STR)
+{
+ struct zebra_vrf *zvrf;
+ bool uj = use_json(argc, argv);
+
+ zvrf = zebra_vrf_get_evpn();
+ zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj, true);
return CMD_SUCCESS;
}
@@ -4819,6 +4887,7 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd);
+ install_element(VIEW_NODE, &show_evpn_mac_vni_detail_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index f1c7debe11..7e86d15b4b 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -2869,7 +2869,7 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
* Display MACs for a VNI (VTY command handler).
*/
void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
- vni_t vni, bool use_json)
+ vni_t vni, bool use_json, bool detail)
{
struct zebra_evpn *zevpn;
uint32_t num_macs;
@@ -2902,17 +2902,28 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
wctx.json = json_mac;
if (!use_json) {
- vty_out(vty,
- "Number of MACs (local and remote) known for this VNI: %u\n",
- num_macs);
- vty_out(vty,
- "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
- vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", "Type",
- "Flags", "Intf/Remote ES/VTEP", "VLAN", "Seq #'s");
+ if (detail) {
+ vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
+ zevpn->vni, num_macs);
+ } else {
+ vty_out(vty,
+ "Number of MACs (local and remote) known for this VNI: %u\n",
+ num_macs);
+ vty_out(vty,
+ "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
+ vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
+ "Type", "Flags", "Intf/Remote ES/VTEP", "VLAN",
+ "Seq #'s");
+ }
} else
json_object_int_add(json, "numMacs", num_macs);
- hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx);
+ if (detail)
+ hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash_detail,
+ &wctx);
+ else
+ hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash,
+ &wctx);
if (use_json) {
json_object_object_add(json, "macs", json_mac);
@@ -3511,6 +3522,12 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
json = json_object_new_object();
json_object_string_add(json, "advertiseGatewayMacip",
zvrf->advertise_gw_macip ? "Yes" : "No");
+ json_object_string_add(json, "advertiseSviMacip",
+ zvrf->advertise_svi_macip ? "Yes"
+ : "No");
+ json_object_string_add(json, "advertiseSviMac",
+ zebra_evpn_mh_do_adv_svi_mac() ? "Yes"
+ : "No");
json_object_int_add(json, "numVnis", num_vnis);
json_object_int_add(json, "numL2Vnis", num_l2vnis);
json_object_int_add(json, "numL3Vnis", num_l3vnis);
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 121e5633d6..16c5bc0a1a 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -95,7 +95,7 @@ extern void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
struct ethaddr *rmac,
bool use_json);
extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
- vni_t vni, bool use_json);
+ vni_t vni, bool use_json, bool detail);
extern void zebra_vxlan_print_macs_all_vni(struct vty *vty,
struct zebra_vrf *zvrf,
bool print_dup,
diff --git a/zebra/zserv.c b/zebra/zserv.c
index d4fa6dadae..2024f34534 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -232,14 +232,16 @@ static void zserv_write(struct thread *thread)
struct stream *msg;
uint32_t wcmd = 0;
struct stream_fifo *cache;
+ uint64_t time_now = monotime(NULL);
/* If we have any data pending, try to flush it first */
switch (buffer_flush_all(client->wb, client->sock)) {
case BUFFER_ERROR:
goto zwrite_fail;
case BUFFER_PENDING:
- atomic_store_explicit(&client->last_write_time, monotime(NULL),
- memory_order_relaxed);
+ frr_with_mutex (&client->stats_mtx) {
+ client->last_write_time = time_now;
+ }
zserv_client_event(client, ZSERV_CLIENT_WRITE);
return;
case BUFFER_EMPTY:
@@ -273,20 +275,19 @@ static void zserv_write(struct thread *thread)
case BUFFER_ERROR:
goto zwrite_fail;
case BUFFER_PENDING:
- atomic_store_explicit(&client->last_write_time, monotime(NULL),
- memory_order_relaxed);
+ frr_with_mutex (&client->stats_mtx) {
+ client->last_write_time = time_now;
+ }
zserv_client_event(client, ZSERV_CLIENT_WRITE);
return;
case BUFFER_EMPTY:
break;
}
- atomic_store_explicit(&client->last_write_cmd, wcmd,
- memory_order_relaxed);
-
- atomic_store_explicit(&client->last_write_time, monotime(NULL),
- memory_order_relaxed);
-
+ frr_with_mutex (&client->stats_mtx) {
+ client->last_write_cmd = wcmd;
+ client->last_write_time = time_now;
+ }
return;
zwrite_fail:
@@ -433,11 +434,13 @@ static void zserv_read(struct thread *thread)
}
if (p2p < p2p_orig) {
+ uint64_t time_now = monotime(NULL);
+
/* update session statistics */
- atomic_store_explicit(&client->last_read_time, monotime(NULL),
- memory_order_relaxed);
- atomic_store_explicit(&client->last_read_cmd, hdr.command,
- memory_order_relaxed);
+ frr_with_mutex (&client->stats_mtx) {
+ client->last_read_time = time_now;
+ client->last_read_cmd = hdr.command;
+ }
/* publish read packets on client's input queue */
frr_with_mutex (&client->ibuf_mtx) {
@@ -631,6 +634,7 @@ static void zserv_client_free(struct zserv *client)
buffer_free(client->wb);
/* Free buffer mutexes */
+ pthread_mutex_destroy(&client->stats_mtx);
pthread_mutex_destroy(&client->obuf_mtx);
pthread_mutex_destroy(&client->ibuf_mtx);
@@ -751,14 +755,13 @@ static struct zserv *zserv_client_create(int sock)
client->obuf_fifo = stream_fifo_new();
client->ibuf_work = stream_new(stream_size);
client->obuf_work = stream_new(stream_size);
+ client->connect_time = monotime(NULL);
pthread_mutex_init(&client->ibuf_mtx, NULL);
pthread_mutex_init(&client->obuf_mtx, NULL);
+ pthread_mutex_init(&client->stats_mtx, NULL);
client->wb = buffer_new(0);
TAILQ_INIT(&(client->gr_info_queue));
- atomic_store_explicit(&client->connect_time, monotime(NULL),
- memory_order_relaxed);
-
/* Initialize flags */
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
@@ -1019,8 +1022,14 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
vty_out(vty, "------------------------ \n");
vty_out(vty, "FD: %d \n", client->sock);
- connect_time = (time_t) atomic_load_explicit(&client->connect_time,
- memory_order_relaxed);
+ frr_with_mutex (&client->stats_mtx) {
+ connect_time = client->connect_time;
+ last_read_time = client->last_read_time;
+ last_write_time = client->last_write_time;
+
+ last_read_cmd = client->last_read_cmd;
+ last_write_cmd = client->last_write_cmd;
+ }
vty_out(vty, "Connect Time: %s \n",
zserv_time_buf(&connect_time, cbuf, ZEBRA_TIME_BUF));
@@ -1041,16 +1050,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
"Client will %sbe notified about the status of its routes.\n",
client->notify_owner ? "" : "Not ");
- last_read_time = (time_t)atomic_load_explicit(&client->last_read_time,
- memory_order_relaxed);
- last_write_time = (time_t)atomic_load_explicit(&client->last_write_time,
- memory_order_relaxed);
-
- last_read_cmd = atomic_load_explicit(&client->last_read_cmd,
- memory_order_relaxed);
- last_write_cmd = atomic_load_explicit(&client->last_write_cmd,
- memory_order_relaxed);
-
vty_out(vty, "Last Msg Rx Time: %s \n",
zserv_time_buf(&last_read_time, rbuf, ZEBRA_TIME_BUF));
vty_out(vty, "Last Msg Tx Time: %s \n",
@@ -1184,12 +1183,11 @@ static void zebra_show_client_brief(struct vty *vty, struct zserv *client)
char wbuf[ZEBRA_TIME_BUF];
time_t connect_time, last_read_time, last_write_time;
- connect_time = (time_t)atomic_load_explicit(&client->connect_time,
- memory_order_relaxed);
- last_read_time = (time_t)atomic_load_explicit(&client->last_read_time,
- memory_order_relaxed);
- last_write_time = (time_t)atomic_load_explicit(&client->last_write_time,
- memory_order_relaxed);
+ frr_with_mutex (&client->stats_mtx) {
+ connect_time = client->connect_time;
+ last_read_time = client->last_read_time;
+ last_write_time = client->last_write_time;
+ }
if (client->instance || client->session_id)
snprintfrr(client_string, sizeof(client_string), "%s[%u:%u]",
diff --git a/zebra/zserv.h b/zebra/zserv.h
index de784e382a..cfc33f9169 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -215,16 +215,21 @@ struct zserv {
* relative to last_read_time.
*/
+ pthread_mutex_t stats_mtx;
+ /* BEGIN covered by stats_mtx */
+
/* monotime of client creation */
- _Atomic uint64_t connect_time;
+ uint64_t connect_time;
/* monotime of last message received */
- _Atomic uint64_t last_read_time;
+ uint64_t last_read_time;
/* monotime of last message sent */
- _Atomic uint64_t last_write_time;
+ uint64_t last_write_time;
/* command code of last message read */
- _Atomic uint64_t last_read_cmd;
+ uint64_t last_read_cmd;
/* command code of last message written */
- _Atomic uint64_t last_write_cmd;
+ uint64_t last_write_cmd;
+
+ /* END covered by stats_mtx */
/*
* Number of instances configured with