def handle_route_advertisement(self, route_dst, route_latency, port): """ Called when the router receives a route advertisement from a neighbor. :param route_dst: the destination of the advertised route. :param route_latency: latency from the neighbor to the destination. :param port: the port that the advertisement arrived on. :return: nothing. """ # TODO: fill this in! if route_dst in self.table: current_route = self.table.get(route_dst) if (route_latency + self.ports.get_latency(port) < current_route.latency) or (port == self.table[route_dst].port): if route_latency >= INFINITY: self.table[route_dst] = TableEntry(route_dst, port, route_latency, api.current_time()) else: self.table[route_dst] = TableEntry( route_dst, port, route_latency + self.ports.get_latency(port), api.current_time() + self.ROUTE_TTL) else: if (route_latency < INFINITY): self.table[route_dst] = TableEntry( route_dst, port, route_latency + self.ports.get_latency(port), api.current_time() + self.ROUTE_TTL)
def handle_route_advertisement(self, route_dst, route_latency, port): """ Called when the router receives a route advertisement from a neighbor. :param route_dst: the destination of the advertised route. :param route_latency: latency from the neighbor to the destination. :param port: the port that the advertisement arrived on. :return: nothing. """ # TODO: fill this in! # if its not in the table entry then I need to add it since it is a new destination if route_dst not in self.table.keys(): self.table[route_dst] = TableEntry( route_dst, port, self.ports.get_latency(port) + route_latency, api.current_time() + self.ROUTE_TTL) else: for host, entry in self.table.items(): if route_dst == host: # if my destination is in my table entry then maybe I have found a better path and must update my existing path if port == entry.port and route_latency >= INFINITY: self.table[host] = TableEntry(route_dst, port, INFINITY, api.current_time()) self.send_routes(False) elif port == entry.port or entry.latency > route_latency + self.ports.get_latency( port): self.table[host] = TableEntry( route_dst, port, route_latency + self.ports.get_latency(port), api.current_time() + self.ROUTE_TTL) self.send_routes(False)
def expire_routes(self): """ Clears out expired routes from table. accordingly. """ # TODO: fill this in! hosts = list(self.table.keys()) for host in hosts: table_entry = self.table[host] if table_entry.expire_time == FOREVER: return # route is poison and expired if self.POISON_EXPIRED and api.current_time( ) > table_entry.expire_time: current_route = self.table[host] poison_route = TableEntry(host, current_route.port, latency=INFINITY, expire_time=self.ROUTE_TTL) self.table[host] = poison_route # route is expired elif api.current_time() > table_entry.expire_time: del self.table[host]
def handle_route_advertisement(self, route_dst, route_latency, port): """Called when the router receives a route advertisement from a neighbor. :param route_dst: the destination of the advertised route. :param route_latency: latency from the neighbor to the destination. :param port: the port that the advertisement arrived on. :return: nothing.""" # TODO: fill this in! port_latency = self.ports.get_latency(port) new_latency = port_latency + route_latency new_expire_time = api.current_time() + self.ROUTE_TTL current_route = self.table.get(route_dst) new_route = TableEntry(dst=route_dst, port=port, latency=new_latency, expire_time=new_expire_time) # poison advertisement if route_latency >= INFINITY and current_route.port == port: current_expire_time = current_route.expire_time poison_route = TableEntry(dst=route_dst, port=port, latency=INFINITY, expire_time=current_expire_time) self.table[route_dst] = poison_route self.send_routes(force=False) return # if NO route currently exists, add/update the new route if not current_route: self.table[route_dst] = new_route self.send_routes(force=False) return # found a better route if new_latency < current_route.latency: self.table[route_dst] = new_route self.send_routes(force=False) return if current_route.port == port: self.table[route_dst] = new_route self.send_routes(force=False) return
def handle_route_advertisement(self, route_dst, route_latency, port): """ Called when the router receives a route advertisement from a neighbor. :param route_dst: the destination of the advertised route. :param route_latency: latency from the neighbor to the destination. :param port: the port that the advertisement arrived on. :return: nothing. """ if route_dst not in self.table or route_latency+self.ports.get_latency(port)<self.table[route_dst].latency or (port == self.table[route_dst].port and self.table[route_dst].latency<INFINITY): self.table[route_dst] = TableEntry(dst=route_dst,port=port,latency=min(INFINITY,route_latency+self.ports.get_latency(port)),expire_time=api.current_time()+self.ROUTE_TTL) self.send_routes()
def add_static_route(self, host, port): """ Adds a static route to this router's table. Called automatically by the framework whenever a host is connected to this router. :param host: the host. :param port: the port that the host is attached to. :returns: nothing. """ # `port` should have been added to `peer_tables` by `handle_link_up` # when the link came up. self.table[host] = TableEntry(dst=host,port=port,latency=self.ports.get_latency(port),expire_time=FOREVER) self.send_routes() assert port in self.ports.get_all_ports(), "Link should be up, but is not."
def expire_routes(self): """ Clears out expired routes from table. accordingly. """ l = [] for host,link in self.table.items(): if api.current_time()>link.expire_time: self.s_log("Route from {} to {} is expired.",self,host) l.append(host) for to_delete in l: if self.POISON_EXPIRED: self.table[to_delete] = TableEntry(dst = to_delete,port = self.table[to_delete].port,latency = INFINITY, expire_time=api.current_time()+self.ROUTE_TTL) #self.send_routes() else: del self.table[to_delete]
def expire_routes(self): """ Clears out expired routes from table. accordingly. """ # TODO: fill this in! toDelete = [] if self.POISON_EXPIRED is True: for host, entry in self.table.items(): if entry.has_expired: self.table[host] = TableEntry(host, entry.port, INFINITY, api.current_time()) else: for host, entry in self.table.items(): if entry.has_expired: toDelete.append(host) self.deleteRoutes(toDelete)
def handle_link_down(self, port): """ Called by the framework when a link attached to this router does down. :param port: the port number used by the link. :returns: nothing. """ del self.history[port] self.ports.remove_port(port) if not self.POISON_ON_LINK_DOWN: return l = [] for host,link in self.table.items(): if link.port == port: self.s_log("Route from {} to {} is down.",self,host) l.append(host) for to_delete in l: self.table[to_delete] = TableEntry(dst = to_delete,port = self.table[to_delete].port,latency = INFINITY, expire_time=api.current_time()+self.ROUTE_TTL) self.send_routes()
def handle_link_down(self, port): """ Called by the framework when a link attached to this router does down. :param port: the port number used by the link. :returns: nothing. """ self.ports.remove_port(port) # TODO: fill this in! toDelete = [] for host, entry in self.table.items(): if entry.port == port: if self.POISON_ON_LINK_DOWN: self.table[host] = TableEntry( host, port, INFINITY, api.current_time() + self.ROUTE_TTL) self.send_routes(False) else: toDelete.append(host) self.deleteRoutes(toDelete)
def expire_routes(self): """ Clears out expired routes from table. accordingly. """ # TODO: fill this in! keys = self.table.items() delete = [] for dst, entry in keys: if entry.has_expired: delete.append(dst) if not self.POISON_EXPIRED: for dest in delete: self.table.pop(dest) else: for dest in delete: self.table[dest] = TableEntry( dest, self.table[dest].port, INFINITY, api.current_time() + self.ROUTE_TTL)
def handle_link_down(self, port): """ Called by the framework when a link attached to this router does down. :param port: the port number used by the link. :returns: nothing. """ self.ports.remove_port(port) # TODO: fill this in! for host in list(self.table.keys()): if self.table[host].port == port: if self.POISON_ON_LINK_DOWN: # poison and immediately send any routes that need to be updated poison_route = TableEntry( host, port, latency=INFINITY, expire_time=self.table[host].expire_time) self.table[host] = poison_route self.send_routes(force=False) # remove any routes that go through that link del self.table[host]