]> git.proxmox.com Git - mirror_frr.git/commitdiff
toptests/isis_sr_te_topo1: test out-of-order route/route-map changes
authorG. Paul Ziemba <p-fbsd-bugs@ziemba.us>
Fri, 20 May 2022 16:26:56 +0000 (09:26 -0700)
committerG. Paul Ziemba <paulz@labn.net>
Sun, 26 Jun 2022 21:38:22 +0000 (14:38 -0700)
    A SR policy matches a BGP nexthop based on the IP address of
    the nexthop and the color of the route (color may be assigned
    to routes using a route-map).

    The order of events (BGP route arrival, route-map definition,
    policy and candidate-path definition) should not affect the
    matching/mapping.

    These changes add tests for:

- removing/adding BGP route after policy and routemap are
  defined and held constant

- changing route map color to be different from policy color,
  and then changing back to match

    after each change, the policy should be observed to be in effect
    unchanged from before, i.e., the route's nexthops should reflect
    the matching SR policy.

Signed-off-by: G. Paul Ziemba <paulz@labn.net>
tests/topotests/isis_sr_te_topo1/rt1/step5/show_ip_route_bgp_empty.ref [new file with mode: 0644]
tests/topotests/isis_sr_te_topo1/test_isis_sr_te_topo1.py

diff --git a/tests/topotests/isis_sr_te_topo1/rt1/step5/show_ip_route_bgp_empty.ref b/tests/topotests/isis_sr_te_topo1/rt1/step5/show_ip_route_bgp_empty.ref
new file mode 100644 (file)
index 0000000..2c63c08
--- /dev/null
@@ -0,0 +1,2 @@
+{
+}
index fb987ba4892f63721068b49382460d4b23bbb9b4..b3b14b557bcad68e9a0e18fa055bab89f75e2b5e 100755 (executable)
@@ -232,13 +232,52 @@ def cmp_json_output_exact(rname, command, reference):
     return cmp_json_output(rname, command, reference, True)
 
 
-def add_candidate_path(rname, endpoint, pref, name, segment_list="default"):
+def compare_json_test_inverted(router, command, reference, exact):
+    "logically inverts result of compare_json_test"
+
+    # None vs something else
+    result = compare_json_test(router, command, reference, exact)
+    if result is None:
+        return "Some"
+    return None
+
+
+def cmp_json_output_doesnt(rname, command, reference):
+    "Compare router JSON output, shouldn't include reference"
+
+    logger.info('Comparing (anti) router "%s" "%s" output', rname, command)
+
+    tgen = get_topogen()
+    filename = "{}/{}/{}".format(CWD, rname, reference)
+    expected = json.loads(open(filename).read())
+
+    # Run test function until we get an result. Wait at most 60 seconds.
+    test_func = partial(
+        compare_json_test_inverted, tgen.gears[rname], command, expected, exact=False
+    )
+    _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
+    assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
+    assert diff is None, assertmsg
+
+
+def dump_json(v):
+    if isinstance(v, (dict, list)):
+        return "\t" + "\t".join(
+            json.dumps(v, indent=4, separators=(",", ": ")).splitlines(True)
+        )
+    else:
+        return "'{}'".format(v)
+
+
+def add_candidate_path(rname, endpoint, pref, name, segment_list="default", color=1):
     get_topogen().net[rname].cmd(
         """ \
         vtysh -c "conf t" \
               -c "segment-routing" \
               -c "traffic-eng" \
-              -c "policy color 1 endpoint """
+              -c "policy color """
+        + str(color)
+        + " endpoint "
         + endpoint
         + """" \
               -c "candidate-path preference """
@@ -251,13 +290,15 @@ def add_candidate_path(rname, endpoint, pref, name, segment_list="default"):
     )
 
 
-def delete_candidate_path(rname, endpoint, pref):
+def delete_candidate_path(rname, endpoint, pref, color=1):
     get_topogen().net[rname].cmd(
         """ \
         vtysh -c "conf t" \
               -c "segment-routing" \
               -c "traffic-eng" \
-              -c "policy color 1 endpoint """
+              -c "policy color """
+        + str(color)
+        + " endpoint "
         + endpoint
         + """" \
               -c "no candidate-path preference """
@@ -349,6 +390,50 @@ def delete_prefix_sid(rname, prefix):
     )
 
 
+def set_route_map_color(rname, color):
+    get_topogen().net[rname].cmd(
+        ''' \
+        vtysh -c "conf t" \
+              -c "route-map SET_SR_POLICY permit 10" \
+              -c "set sr-te color  "'''
+        + str(color)
+    )
+
+
+def router_bgp_shutdown_neighbor(rname, neighbor):
+    get_topogen().net[rname].cmd(
+        """ \
+        vtysh -c "conf t" \
+              -c "router bgp 1" \
+              -c " neighbor """
+        + neighbor
+        + ' shutdown"'
+    )
+
+
+def router_bgp_no_shutdown_neighbor(rname, neighbor):
+    get_topogen().net[rname].cmd(
+        """ \
+        vtysh -c "conf t" \
+              -c "router bgp 1" \
+              -c " no neighbor """
+        + neighbor
+        + ' shutdown"'
+    )
+
+
+def show_running_cfg(rname):
+    output = (
+        get_topogen()
+        .net[rname]
+        .cmd(
+            """ \
+        vtysh -c "show run" """
+        )
+    )
+    logger.info(output)
+
+
 #
 # Step 1
 #
@@ -542,6 +627,22 @@ def test_srte_segment_list_add_segment_check_mpls_table_step4():
     delete_candidate_path("rt1", "6.6.6.6", 100)
 
 
+def save_rt(routername, filename):
+    save_filename = routername + "/" + filename
+    tgen = get_topogen()
+    router = tgen.gears[routername]
+
+    config_output = router.vtysh_cmd("sh run")
+
+    route_output_json = json.loads(router.vtysh_cmd("show ip route bgp json"))
+    route_output = dump_json(route_output_json)
+
+    f = open(save_filename, "w")
+    f.write(config_output)
+    f.write(route_output)
+    f.close()
+
+
 #
 # Step 5
 #
@@ -576,6 +677,147 @@ def test_srte_route_map_with_sr_policy_check_nextop_step5():
         delete_candidate_path("rt1", "6.6.6.6", 100)
 
 
+def test_srte_route_map_sr_policy_vs_route_order_step5():
+    setup_testcase(
+        "Test (step 5): Config policy first, add route after and check route validity"
+    )
+
+    #
+    # BGP route and route-map are already configured.
+    # route-map sets color 1 on BGP routes
+
+    # Developer: to force pause here
+    # tgen = get_topogen()
+    # tgen.mininet_cli()
+
+    #
+    # Configure policy/path
+    #
+    add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
+
+    #
+    # Route should be valid
+    #
+    logger.info(
+        "BGP route and route-map are already configured, SR candidate path added after. Route should be valid"
+    )
+    cmp_json_output(
+        "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+    )
+
+    #
+    # shutdown/no-shutdown on BGP neighbor to delete/re-add BGP route
+    #
+    router_bgp_shutdown_neighbor("rt1", "6.6.6.6")
+    router_bgp_no_shutdown_neighbor("rt1", "6.6.6.6")
+
+    #
+    # Route should be valid (but isn't)
+    #
+    logger.info(
+        "After shutdown + no-shutdown neighbor. Route should be valid, but isn't"
+    )
+    cmp_json_output(
+        "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+    )
+
+    #
+    # delete and re-add policy/path
+    #
+    delete_candidate_path("rt1", "6.6.6.6", 100, 1)
+    add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
+
+    #
+    # Route should be valid
+    #
+    logger.info("After re-add candidate path. Route should be valid")
+    cmp_json_output(
+        "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+    )
+
+    # Developer: to force pause here
+    # tgen = get_topogen()
+    # tgen.mininet_cli()
+
+    # clean up
+    delete_candidate_path("rt1", "6.6.6.6", 100, 2)
+
+
+def test_srte_route_map_sr_policy_vs_routemap_order_step5():
+    setup_testcase(
+        "Test (step 5): Config policy first, set route-map after and check route validity"
+    )
+
+    #
+    # BGP route and route-map are already configured.
+    # route-map sets color 1 on BGP routes
+    #
+
+    #
+    # Configure policy/path
+    #
+    add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
+
+    #
+    # Route should be valid
+    #
+    logger.info("After add candidate path. Route should be valid")
+    cmp_json_output(
+        "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+    )
+
+    # Developer: to force pause here
+    # tgen = get_topogen()
+    # tgen.mininet_cli()
+
+    #
+    # change route-map color to someting else and back again
+    #
+    set_route_map_color("rt1", 2)
+    logger.info("route-map color was set to 2")
+    # show_running_cfg("rt1")
+    # 220625 nexthop no longer becomes empty. Colored routes without
+    # matching SR policies now fall back to their non-colored equivalent
+    # nexthops. So the route to 9.9.9.9/32 will now be valid, but with
+    # different nexthop values.
+    logger.info("now route table will lose policy-mapped route")
+    cmp_json_output_doesnt(
+        "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+    )
+    set_route_map_color("rt1", 1)
+    logger.info("route-map color was set to 1")
+    # show_running_cfg("rt1")
+
+    #
+    # Route should be valid (but isn't)
+    #
+    logger.info("After change route-map color. Route should be valid, but isn't")
+    cmp_json_output(
+        "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+    )
+
+    #
+    # delete and re-add policy/path
+    #
+    delete_candidate_path("rt1", "6.6.6.6", 100, 1)
+    add_candidate_path("rt1", "6.6.6.6", 100, "default", "default", 1)
+
+    #
+    # Route should be valid
+    #
+    logger.info("After delete/re-add candidate path. Route should be valid")
+    cmp_json_output(
+        "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+    )
+
+    # Developer: force pause
+    # tgen = get_topogen()
+    # tgen.mininet_cli()
+
+    # clean up
+    delete_candidate_path("rt1", "6.6.6.6", 100, 2)
+
+
 def test_srte_route_map_with_sr_policy_reinstall_prefix_sid_check_nextop_step5():
     setup_testcase(
         "Test (step 5): remove and re-install prefix SID on fist path element and check SR Policy activity"