diff --git a/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_interface_down.json b/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_interface_down.json new file mode 100644 index 0000000000..50871ae038 --- /dev/null +++ b/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_interface_down.json @@ -0,0 +1,20 @@ +{ + "5.5.6.7/32":[ + { + "prefix":"5.5.6.7/32", + "prefixLen":32, + "protocol":"kernel", + "vrfName":"default", + "internalFlags":0, + "internalNextHopNum":1, + "internalNextHopActiveNum":0, + "nexthops":[ + { + "flags":0, + "interfaceName":"r1-eth2" + } + ] + + } + ] +} diff --git a/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_interface_up.json b/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_interface_up.json new file mode 100644 index 0000000000..d0ab2fa187 --- /dev/null +++ b/tests/topotests/zebra_multiple_connected/r1/ip_route_kernel_interface_up.json @@ -0,0 +1,21 @@ +{ + "5.5.6.7/32":[ + { + "prefix":"5.5.6.7/32", + "prefixLen":32, + "protocol":"kernel", + "vrfName":"default", + "internalFlags":8, + "internalNextHopNum":1, + "internalNextHopActiveNum":1, + "nexthops":[ + { + "flags":3, + "fib":true, + "interfaceName":"r1-eth2", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py index eda8c88706..89bc6cf8e0 100644 --- a/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py +++ b/tests/topotests/zebra_multiple_connected/test_zebra_multiple_connected.py @@ -65,6 +65,9 @@ def build_topo(tgen): switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r3"]) + # Create a p2p connection between r1 and r2 + tgen.add_link(tgen.gears["r1"], tgen.gears["r2"]) + ##################################################### ## @@ -222,6 +225,50 @@ def test_zebra_kernel_route_blackhole_add(): result, _ = topotest.run_and_expect(test_func, None, count=20, wait=1) assert result, "Blackhole Route should have not been removed\n{}".format(_) +def test_zebra_kernel_route_interface_linkdown(): + "Test that a kernel routes should be affected by interface change" + + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r1"] + router.run("ip route add 5.5.6.7/32 via 10.0.1.66 dev r1-eth2") + + kernel = "{}/{}/ip_route_kernel_interface_up.json".format(CWD, router.name) + expected = json.loads(open(kernel).read()) + + test_func = partial( + topotest.router_json_cmp, router, "show ip route 5.5.6.7/32 json", expected + ) + result, _ = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result, "Kernel Route should be selected:\n{}".format(_) + + # link down + router2 = tgen.gears["r2"] + router2.run("ip link set dev r2-eth2 down") + + kernel = "{}/{}/ip_route_kernel_interface_down.json".format(CWD, router.name) + expected = json.loads(open(kernel).read()) + + test_func = partial( + topotest.router_json_cmp, router, "show ip route 5.5.6.7/32 json", expected + ) + result, _ = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result, "Kernel Route should not be selected:\n{}".format(_) + + # link up + router2 = tgen.gears["r2"] + router2.run("ip link set dev r2-eth2 up") + + kernel = "{}/{}/ip_route_kernel_interface_up.json".format(CWD, router.name) + expected = json.loads(open(kernel).read()) + + test_func = partial( + topotest.router_json_cmp, router, "show ip route 5.5.6.7/32 json", expected + ) + result, _ = topotest.run_and_expect(test_func, None, count=20, wait=1) + assert result, "Kernel Route should be selected:\n{}".format(_) if __name__ == "__main__": args = ["-s"] + sys.argv[1:] diff --git a/zebra/interface.c b/zebra/interface.c index f7fd112cd4..1c86a6a5c7 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -972,6 +972,8 @@ void if_up(struct interface *ifp, bool install_connected) event_ignore_late_timer(zif->speed_update); if_addr_wakeup(ifp); + + rib_update_handle_vrf_all(RIB_UPDATE_KERNEL, ZEBRA_ROUTE_KERNEL); } /* Interface goes down. We have to manage different behavior of based diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 1519246c17..e61c158ca9 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2648,7 +2648,7 @@ static unsigned nexthop_active_check(struct route_node *rn, ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id); - if (ifp && ifp->vrf->vrf_id == vrf_id && if_is_up(ifp)) { + if (ifp && ifp->vrf->vrf_id == vrf_id && if_is_up(ifp) && if_is_operative(ifp)) { SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); goto skip_check; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 51458e4e84..0226c355c8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1421,7 +1421,7 @@ static void rib_process(struct route_node *rn) rib_process_update_fib(zvrf, rn, old_fib, new_fib); else if (new_fib) rib_process_add_fib(zvrf, rn, new_fib); - else if (old_fib) + else if (old_fib && !RIB_SYSTEM_ROUTE(old_fib)) rib_process_del_fib(zvrf, rn, old_fib); /* Remove all RE entries queued for removal */