def update_fib(self, prefix, child_prefix_strs): # The child_prefix_strs have to be passed as a parameter, because they need to be collected # before the parent is potentially deleted by the calling function. # Locate the best RIB route for the prefix (None if there is no RIB route for the prefix). prefix_str = ip_prefix_str(prefix) if self.destinations.has_key(prefix_str): destination = self.destinations.get(prefix_str) rib_route = destination.best_route() else: rib_route = None # Determine the next-hops for the corresponding FIB route. If the next-hops is an empty # list [] it means it is a discard route. If the next-hops is None it means there should not # be a FIB route. if rib_route: fib_next_hops = rib_route.compute_fib_next_hops() else: fib_next_hops = None # Update the FIB route accordingly. if fib_next_hops is not None: fib_route = FibRoute(prefix, fib_next_hops) self.fib.put_route(fib_route) else: self.fib.del_route(prefix) # Recursively update the FIB for all child routes: their negative next-hops, if any, may # have to be recomputed if a parent route changed. for child_prefix_str in child_prefix_strs: child_destination = self.destinations[child_prefix_str] child_rib_route = child_destination.best_route() child_prefix = child_rib_route.prefix grand_child_prefix_strs = self.destinations.children( child_prefix_str) self.update_fib(child_prefix, grand_child_prefix_strs)
def test_put_del_route(): kern = Kernel(simulated_interfaces=False, log=None, log_id="", table_name="5") if not kern.platform_supported: return # Put route with one next-hop (with interface but no address) prefix = make_ip_prefix("99.99.99.99/32") nhops = [NextHop(False, "lo", None, None)] rte = FibRoute(prefix, nhops) assert kern.put_route(rte) # Delete route just added assert kern.del_route(prefix) # Put route with one next-hop (with interface and address) prefix = make_ip_prefix("99.99.99.99/32") address = make_ip_address("127.0.0.1") nhops = [NextHop(False, "lo", address, None)] rte = FibRoute(prefix, nhops) assert kern.put_route(rte) # Delete route just added assert kern.del_route(prefix) # Put ECMP route with multiple next-hop (with interface and address) prefix = make_ip_prefix("99.99.99.99/32") address1 = make_ip_address("127.0.0.1") address2 = make_ip_address("127.0.0.2") nhops = [ NextHop(False, "lo", address1, None), NextHop(False, "lo", address2, None) ] rte = FibRoute(prefix, nhops) assert kern.put_route(rte) # Do we display the ECMP route properly? tab_str = kern.cli_route_prefix_table(5, prefix).to_string() pattern = (r"[|] Table +[|] 5 +[|]\n" r"[|] Address Family +[|] IPv4 +[|]\n" r"[|] Destination +[|] 99\.99\.99\.99/32 +[|]\n" r"[|] Type +[|] Unicast +[|]\n" r"[|] Protocol +[|] RIFT +[|]\n" r"[|] Scope +[|] Universe +[|]\n" r"[|] Next-hops +[|] lo 127\.0\.0\.1 1 +[|]\n" r"[|] +[|] lo 127\.0\.0\.2 1 +[|]\n") assert re.search(pattern, tab_str) is not None # Delete route just added assert kern.del_route(prefix)
def test_put_del_route_errors(): kern = Kernel(simulated_interfaces=False, log=None, log_id="", table_name="main") if not kern.platform_supported: return # Attempt to add route with nonsense next-hop interface prefix = make_ip_prefix("99.99.99.99/32") nhops = [NextHop(False, "nonsense", None, None)] rte = FibRoute(prefix, nhops) assert not kern.put_route(rte)
def test_put_del_route_unreachable(): kern = Kernel(simulated_interfaces=False, log=None, log_id="", table_name="main") if not kern.platform_supported: return # Add unreachable prefix in the kernel routing table (no next hops) prefix = make_ip_prefix("99.99.99.99/32") nhops = [] rte = FibRoute(prefix, nhops) assert kern.put_route(rte) tab_str = kern.cli_route_prefix_table(254, prefix).to_string() pattern = (r"[|] Table +[|] Main +[|]\n" r"[|] Address Family +[|] IPv4 +[|]\n" r"[|] Destination +[|] 99\.99\.99\.99/32 +[|]\n" r"[|] Type +[|] Unreachable +[|]\n" r"[|] Protocol +[|] RIFT +[|]\n" r"[|] Scope +[|] Universe +[|]\n" r"[|] Next-hops +[|] +[|]\n" r"[|] Priority +[|] 199 +[|]\n") assert re.search(pattern, tab_str) is not None # Replace unreachable route with a route containing one next hop new_nhops = [NextHop(False, "lo", make_ip_address("127.0.0.1"), None)] rte = FibRoute(prefix, new_nhops) assert kern.put_route(rte) tab_str = kern.cli_route_prefix_table(254, prefix).to_string() pattern = (r"[|] Table +[|] Main +[|]\n" r"[|] Address Family +[|] IPv4 +[|]\n" r"[|] Destination +[|] 99\.99\.99\.99/32 +[|]\n" r"[|] Type +[|] Unicast +[|]\n" r"[|] Protocol +[|] RIFT +[|]\n" r"[|] Scope +[|] Universe +[|]\n" r"[|] Next-hops +[|] lo 127.0.0.1 +[|]\n" r"[|] Priority +[|] 199 +[|]\n") assert re.search(pattern, tab_str) is not None # Delete next hops assert kern.del_route(prefix)
def put_route(self, prefix, nexthops): route = FibRoute(prefix, nexthops) self._routes[prefix] = route
def put_route(self, rte): if self._is_route_different(rte): fib_route = FibRoute(rte.prefix, rte.next_hops) self.routes[rte.prefix] = fib_route self.kernel.put_route(fib_route.prefix, fib_route.next_hops)
def test_property_prefix(): route = FibRoute("1.0.0.0/8", ["nh1", "nh2"]) assert route.prefix == "1.0.0.0/8"
def test_constructor(): _route = FibRoute("1.0.0.0/8", ["nh1", "nh2"])
def test_str(): route = FibRoute("1.0.0.0/8", ["nh2", "nh1"]) assert str(route) == "1.0.0.0/8 -> nh1, nh2" route = FibRoute("0.0.0.0/0", []) assert str(route) == "0.0.0.0/0 -> "