]> git.puffer.fish Git - mirror/frr.git/commitdiff
tests: Check if we are not sending duplicate BGP UPDATEs
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Thu, 12 Nov 2020 10:31:30 +0000 (12:31 +0200)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Fri, 11 Dec 2020 12:51:07 +0000 (14:51 +0200)
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
14 files changed:
tests/topotests/bgp_community_change_update/__init__.py [new file with mode: 0644]
tests/topotests/bgp_community_change_update/c1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/c1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py [new file with mode: 0644]
tests/topotests/bgp_community_change_update/x1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/x1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/y1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/y1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/y2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/y2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/y3/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/y3/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/z1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_community_change_update/z1/zebra.conf [new file with mode: 0644]

diff --git a/tests/topotests/bgp_community_change_update/__init__.py b/tests/topotests/bgp_community_change_update/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_community_change_update/c1/bgpd.conf b/tests/topotests/bgp_community_change_update/c1/bgpd.conf
new file mode 100644 (file)
index 0000000..24cf9df
--- /dev/null
@@ -0,0 +1,11 @@
+!
+debug bgp updates
+!
+router bgp 65001
+  no bgp ebgp-requires-policy
+  neighbor 10.0.1.2 remote-as external
+  neighbor 10.0.1.2 timers 3 10
+  address-family ipv4 unicast
+    redistribute connected
+  exit-address-family
+!
diff --git a/tests/topotests/bgp_community_change_update/c1/zebra.conf b/tests/topotests/bgp_community_change_update/c1/zebra.conf
new file mode 100644 (file)
index 0000000..e3dbbc0
--- /dev/null
@@ -0,0 +1,6 @@
+!
+interface c1-eth0
+ ip address 10.0.1.1/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py b/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py
new file mode 100644 (file)
index 0000000..5fc4310
--- /dev/null
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2020 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Reference: https://www.cmand.org/communityexploration
+
+                     --y2--
+                    /  |   \
+  c1 ---- x1 ---- y1   |   z1
+                    \  |   /
+                     --y3--
+
+1. z1 announces 192.168.255.254/32 to y2, y3.
+2. y2 and y3 tags this prefix at ingress with appropriate
+communities 65004:2 (y2) and 65004:3 (y3).
+3. x1 filters all communities at the egress to c1.
+4. Shutdown the link between y1 and y2.
+5. y1 will generate a BGP UPDATE message regarding the next-hop change.
+6. x1 will generate a BGP UPDATE message regarding community change.
+
+To avoid sending duplicate BGP UPDATE messages we should make sure
+we send only actual route updates. In this example, x1 will skip
+BGP UPDATE to c1 because the actual route is the same
+(filtered communities - nothing changes).
+"""
+
+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.topolog import logger
+from mininet.topo import Topo
+
+from lib.common_config import step
+from time import sleep
+
+
+class TemplateTopo(Topo):
+    def build(self, *_args, **_opts):
+        tgen = get_topogen(self)
+
+        tgen.add_router("z1")
+        tgen.add_router("y1")
+        tgen.add_router("y2")
+        tgen.add_router("y3")
+        tgen.add_router("x1")
+        tgen.add_router("c1")
+
+        # 10.0.1.0/30
+        switch = tgen.add_switch("s1")
+        switch.add_link(tgen.gears["c1"])
+        switch.add_link(tgen.gears["x1"])
+
+        # 10.0.2.0/30
+        switch = tgen.add_switch("s2")
+        switch.add_link(tgen.gears["x1"])
+        switch.add_link(tgen.gears["y1"])
+
+        # 10.0.3.0/30
+        switch = tgen.add_switch("s3")
+        switch.add_link(tgen.gears["y1"])
+        switch.add_link(tgen.gears["y2"])
+
+        # 10.0.4.0/30
+        switch = tgen.add_switch("s4")
+        switch.add_link(tgen.gears["y1"])
+        switch.add_link(tgen.gears["y3"])
+
+        # 10.0.5.0/30
+        switch = tgen.add_switch("s5")
+        switch.add_link(tgen.gears["y2"])
+        switch.add_link(tgen.gears["y3"])
+
+        # 10.0.6.0/30
+        switch = tgen.add_switch("s6")
+        switch.add_link(tgen.gears["y2"])
+        switch.add_link(tgen.gears["z1"])
+
+        # 10.0.7.0/30
+        switch = tgen.add_switch("s7")
+        switch.add_link(tgen.gears["y3"])
+        switch.add_link(tgen.gears["z1"])
+
+
+def setup_module(mod):
+    tgen = Topogen(TemplateTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+
+    for i, (rname, router) in enumerate(router_list.items(), 1):
+        router.load_config(
+            TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+        )
+
+    tgen.start_router()
+
+
+def teardown_module(mod):
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+def test_bgp_community_update_path_change():
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    def _bgp_converge_initial():
+        output = json.loads(
+            tgen.gears["c1"].vtysh_cmd("show ip bgp neighbor 10.0.1.2 json")
+        )
+        expected = {
+            "10.0.1.2": {
+                "bgpState": "Established",
+                "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 8}},
+            }
+        }
+        return topotest.json_cmp(output, expected)
+
+    step("Check if an initial topology is converged")
+    test_func = functools.partial(_bgp_converge_initial)
+    success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+    assert result is None, "Failed to see bgp convergence in c1"
+
+    step("Disable link between y1 and y2")
+    tgen.gears["y1"].run("ip link set dev y1-eth1 down")
+
+    def _bgp_converge_link_disabled():
+        output = json.loads(tgen.gears["y1"].vtysh_cmd("show ip bgp nei 10.0.3.2 json"))
+        expected = {"10.0.3.2": {"bgpState": "Active"}}
+        return topotest.json_cmp(output, expected)
+
+    step("Check if a topology is converged after a link down between y1 and y2")
+    test_func = functools.partial(_bgp_converge_link_disabled)
+    success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+    assert result is None, "Failed to see bgp convergence in y1"
+
+    def _bgp_check_for_duplicate_updates():
+        duplicate = False
+        i = 0
+        while i < 5:
+            if (
+                len(
+                    tgen.gears["c1"].run(
+                        'grep "10.0.1.2 rcvd 192.168.255.254/32 IPv4 unicast...duplicate ignored" bgpd.log'
+                    )
+                )
+                > 0
+            ):
+                duplicate = True
+            i += 1
+            sleep(0.5)
+        return duplicate
+
+    step("Check if we see duplicate BGP UPDATE message in c1 (suppress-duplicates)")
+    assert (
+        _bgp_check_for_duplicate_updates() == False
+    ), "Seen duplicate BGP UPDATE message in c1 from x1"
+
+    step("Disable bgp suppress-duplicates at x1")
+    tgen.gears["x1"].run(
+        "vtysh -c 'conf' -c 'router bgp' -c 'no bgp suppress-duplicates'"
+    )
+
+    step("Enable link between y1 and y2")
+    tgen.gears["y1"].run("ip link set dev y1-eth1 up")
+
+    def _bgp_converge_link_enabled():
+        output = json.loads(tgen.gears["y1"].vtysh_cmd("show ip bgp nei 10.0.3.2 json"))
+        expected = {
+            "10.0.3.2": {
+                "bgpState": "Established",
+                "addressFamilyInfo": {
+                    "ipv4Unicast": {"acceptedPrefixCounter": 5, "sentPrefixCounter": 4}
+                },
+            }
+        }
+        return topotest.json_cmp(output, expected)
+
+    step("Check if a topology is converged after a link up between y1 and y2")
+    test_func = functools.partial(_bgp_converge_link_enabled)
+    success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+    assert result is None, "Failed to see bgp convergence in y1"
+
+    step(
+        "Check if we see duplicate BGP UPDATE message in c1 (no bgp suppress-duplicates)"
+    )
+    assert (
+        _bgp_check_for_duplicate_updates() == True
+    ), "Didn't see duplicate BGP UPDATE message in c1 from x1"
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_community_change_update/x1/bgpd.conf b/tests/topotests/bgp_community_change_update/x1/bgpd.conf
new file mode 100644 (file)
index 0000000..8d7bcb9
--- /dev/null
@@ -0,0 +1,20 @@
+!
+debug bgp updates
+!
+router bgp 65002
+  no bgp ebgp-requires-policy
+  neighbor 10.0.1.1 remote-as external
+  neighbor 10.0.1.1 timers 3 10
+  neighbor 10.0.2.2 remote-as external
+  neighbor 10.0.2.2 timers 3 10
+  address-family ipv4 unicast
+    redistribute connected
+    neighbor 10.0.1.1 route-map c1 out
+  exit-address-family
+!
+bgp community-list standard c1 seq 1 permit 65004:2
+bgp community-list standard c1 seq 2 permit 65004:3
+!
+route-map c1 permit 10
+  set comm-list c1 delete
+!
diff --git a/tests/topotests/bgp_community_change_update/x1/zebra.conf b/tests/topotests/bgp_community_change_update/x1/zebra.conf
new file mode 100644 (file)
index 0000000..8b7c03f
--- /dev/null
@@ -0,0 +1,9 @@
+!
+interface x1-eth0
+ ip address 10.0.1.2/30
+!
+interface x1-eth1
+ ip address 10.0.2.1/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_community_change_update/y1/bgpd.conf b/tests/topotests/bgp_community_change_update/y1/bgpd.conf
new file mode 100644 (file)
index 0000000..a010085
--- /dev/null
@@ -0,0 +1,12 @@
+router bgp 65003
+  no bgp ebgp-requires-policy
+  neighbor 10.0.2.1 remote-as external
+  neighbor 10.0.2.1 timers 3 10
+  neighbor 10.0.3.2 remote-as internal
+  neighbor 10.0.3.2 timers 3 10
+  neighbor 10.0.4.2 remote-as internal
+  neighbor 10.0.4.2 timers 3 10
+  address-family ipv4 unicast
+    redistribute connected
+  exit-address-family
+!
diff --git a/tests/topotests/bgp_community_change_update/y1/zebra.conf b/tests/topotests/bgp_community_change_update/y1/zebra.conf
new file mode 100644 (file)
index 0000000..4096f2a
--- /dev/null
@@ -0,0 +1,12 @@
+!
+interface y1-eth0
+ ip address 10.0.2.2/30
+!
+interface y1-eth1
+ ip address 10.0.3.1/30
+!
+interface y1-eth2
+ ip address 10.0.4.1/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_community_change_update/y2/bgpd.conf b/tests/topotests/bgp_community_change_update/y2/bgpd.conf
new file mode 100644 (file)
index 0000000..27f1e81
--- /dev/null
@@ -0,0 +1,18 @@
+router bgp 65003
+  no bgp ebgp-requires-policy
+  neighbor 10.0.3.1 remote-as internal
+  neighbor 10.0.3.1 timers 3 10
+  neighbor 10.0.5.2 remote-as internal
+  neighbor 10.0.5.2 timers 3 10
+  neighbor 10.0.6.2 remote-as external
+  neighbor 10.0.6.2 timers 3 10
+  address-family ipv4 unicast
+    redistribute connected
+    neighbor 10.0.3.1 route-reflector-client
+    neighbor 10.0.5.2 route-reflector-client
+    neighbor 10.0.6.2 route-map z1 in
+  exit-address-family
+!
+route-map z1 permit 10
+  set community 65004:2
+!
diff --git a/tests/topotests/bgp_community_change_update/y2/zebra.conf b/tests/topotests/bgp_community_change_update/y2/zebra.conf
new file mode 100644 (file)
index 0000000..7e9458a
--- /dev/null
@@ -0,0 +1,12 @@
+!
+interface y2-eth0
+ ip address 10.0.3.2/30
+!
+interface y2-eth1
+ ip address 10.0.5.1/30
+!
+interface y2-eth2
+ ip address 10.0.6.1/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_community_change_update/y3/bgpd.conf b/tests/topotests/bgp_community_change_update/y3/bgpd.conf
new file mode 100644 (file)
index 0000000..8e57284
--- /dev/null
@@ -0,0 +1,18 @@
+router bgp 65003
+  no bgp ebgp-requires-policy
+  neighbor 10.0.4.1 remote-as internal
+  neighbor 10.0.4.1 timers 3 10
+  neighbor 10.0.5.1 remote-as internal
+  neighbor 10.0.5.1 timers 3 10
+  neighbor 10.0.7.2 remote-as external
+  neighbor 10.0.7.2 timers 3 10
+  address-family ipv4 unicast
+    redistribute connected
+    neighbor 10.0.4.1 route-reflector-client
+    neighbor 10.0.5.1 route-reflector-client
+    neighbor 10.0.7.2 route-map z1 in
+  exit-address-family
+!
+route-map z1 permit 10
+  set community 65004:3
+!
diff --git a/tests/topotests/bgp_community_change_update/y3/zebra.conf b/tests/topotests/bgp_community_change_update/y3/zebra.conf
new file mode 100644 (file)
index 0000000..93dd87d
--- /dev/null
@@ -0,0 +1,12 @@
+!
+interface y3-eth0
+ ip address 10.0.4.2/30
+!
+interface y3-eth1
+ ip address 10.0.5.2/30
+!
+interface y3-eth2
+ ip address 10.0.7.1/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_community_change_update/z1/bgpd.conf b/tests/topotests/bgp_community_change_update/z1/bgpd.conf
new file mode 100644 (file)
index 0000000..2f470f1
--- /dev/null
@@ -0,0 +1,10 @@
+router bgp 65004
+  no bgp ebgp-requires-policy
+  neighbor 10.0.6.1 remote-as external
+  neighbor 10.0.6.1 timers 3 10
+  neighbor 10.0.7.1 remote-as external
+  neighbor 10.0.7.1 timers 3 10
+  address-family ipv4 unicast
+    redistribute connected
+  exit-address-family
+!
diff --git a/tests/topotests/bgp_community_change_update/z1/zebra.conf b/tests/topotests/bgp_community_change_update/z1/zebra.conf
new file mode 100644 (file)
index 0000000..7f6bbb6
--- /dev/null
@@ -0,0 +1,12 @@
+!
+interface lo
+ ip address 192.168.255.254/32
+!
+interface z1-eth0
+ ip address 10.0.6.2/30
+!
+interface z1-eth1
+ ip address 10.0.7.2/30
+!
+ip forwarding
+!