def add_static_route(self, host, port): """ Adds a static route to a host directly connected to this router. 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. assert port in self.peer_tables, "Link is not up?" table = self.peer_tables[port] table[host] = PeerTableEntry(dst=host, latency=0, expire_time=PeerTableEntry.FOREVER) # TODO: fill this in! self.update_forwarding_table() self.send_routes(force=False)
def handle_route_advertisement(self, dst, port, route_latency): """ Called when the router receives a route advertisement from a neighbor. :param dst: the destination of the advertised route. :param port: the port that the advertisement came from. :param route_latency: latency from the neighbor to the destination. :return: nothing. """ # TODO: fill this in! self.peer_tables[port][dst]=PeerTableEntry(dst,route_latency,api.current_time()+ROUTE_TTL) self.update_forwarding_table() self.send_routes(force=False)
def expire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ # TODO: fill this in! for table in self.peer_tables.values(): for key, element in table.items(): if (api.current_time() > element.expire_time): if self.POISON_MODE: table[key]=PeerTableEntry(key,INFINITY,api.current_time()+ROUTE_TTL) else: table.pop(key) self.update_forwarding_table()
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. """ # TODO: fill this in!s self.link_latency[port] = INFINITY for dst, entry in self.peer_tables[port].items(): self.peer_tables[port][dst] = PeerTableEntry( dst, INFINITY, entry.expire_time) self.update_forwarding_table() self.send_routes()
def add_static_route(self, host, port): """ Adds a static route to a host directly connected to this router. 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. assert port in self.peer_tables, "Link is not up?" pte = PeerTableEntry(host, 0, PeerTableEntry.FOREVER) self.peer_tables[port][host] = pte self.update_forwarding_table()
def expire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ # TODO: fill this in! for port, peer_table_entry in self.peer_tables.items(): for host, entry in peer_table_entry.items(): if entry.expire_time <= api.current_time(): if self.POISON_MODE: peer_table_entry[host] = PeerTableEntry( host, INFINITY, api.current_time() + ROUTE_TTL) else: del peer_table_entry[host] self.update_forwarding_table()
def handle_route_advertisement(self, dst, port, route_latency): """ Called when the router receives a route advertisement from a neighbor. :param dst: the destination of the advertised route. :param port: the port that the advertisement came from. :param route_latency: latency from the neighbor to the destination. :return: nothing. """ neighborPeerTable = self.peer_tables.get(port) ptEntry = PeerTableEntry(dst, route_latency, api.current_time() + ROUTE_TTL) neighborPeerTable.update({dst: ptEntry}) self.peer_tables.update({port: neighborPeerTable}) self.update_forwarding_table() self.send_routes(force=False)
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. """ # TODO: fill this in! if self.POISON_MODE: for host, entry in self.peer_tables[port].items(): self.peer_tables[port][host]=PeerTableEntry(host,INFINITY,api.current_time()+ROUTE_TTL) else: for key in self.peer_tables.keys(): if key == port: self.peer_tables.pop(key) self.port_table.remove(port) self.update_forwarding_table() self.send_routes()
def expire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ # TODO: fill this in! if self.POISON_MODE: for p, peer_table in self.peer_tables.items(): for pte in peer_table: if ((peer_table[pte].expire_time < api.current_time()) and (peer_table[pte].expire_time != PeerTableEntry.FOREVER)): peer_table[pte] = PeerTableEntry(peer_table[pte].dst, INFINITY, api.current_time() + ROUTE_TTL) else: for port, peer_table in self.peer_tables.items(): for pte in peer_table.keys(): if ((peer_table[pte].expire_time < api.current_time()) and (peer_table[pte].expire_time != PeerTableEntry.FOREVER)): del peer_table[pte] self.update_forwarding_table()
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. """ # TODO: fill this in! if self.POISON_MODE: for p, peer_table in self.peer_tables.items(): if p == port: for pte in peer_table: self.poisoned_routes.add(p) peer_table[pte] = PeerTableEntry(peer_table[pte].dst, INFINITY, api.current_time() + ROUTE_TTL) else: del self.peer_tables[port] del self.link_latency[port] self.update_forwarding_table() self.send_routes(force=False)
def send_routes(self, force=False): """ Send route advertisements for all routes in the forwarding table. :param force: if True, advertises ALL routes in the forwarding table; otherwise, advertises only those routes that have changed since the last advertisement. :return: nothing. """ # print(self.history) # print(self.forwarding_table) if (self.POISON_MODE): # print(self.history) # print(self.forwarding_table) for port in self.history: pTable = self.history[port] for host in pTable: if ((host not in self.forwarding_table) and (port in self.peer_tables)): packet = basics.RoutePacket(destination=host, latency=INFINITY) # self.send(packet, port=port) # pTable[host] = packet # self.history[port] = pTable temp = self.peer_tables[port] temp[host] = PeerTableEntry( dst=host, latency=INFINITY, expire_time=api.current_time() + ROUTE_TTL) self.update_forwarding_table() for port, table in self.peer_tables.items(): for host, entry in self.forwarding_table.items(): tempLatency = None if (self.POISON_MODE): if (entry.port == port): tempLatency = INFINITY else: if (entry.latency > INFINITY): tempLatency = INFINITY else: tempLatency = entry.latency # pTable = self.peer_tables[port] # pTable[host] = PeerTableEntry(dst=host, latency=INFINITY, expire_time=api.current_time()+ROUTE_TTL) # self.update_forwarding_table() elif (entry.port != port): if (entry.latency > INFINITY): tempLatency = INFINITY else: tempLatency = entry.latency if (tempLatency): packet = basics.RoutePacket(destination=entry.dst, latency=tempLatency) if (force): self.send(packet, port=port) pTable = {} # if port already in history, get the table if (port in self.history): pTable = self.history[port] # port not in history, create new dictionary entry else: self.history[port] = {} pTable = self.history[port] pTable[host] = packet self.history[port] = pTable # -------------------- Stage 8 -------------------- else: send = False pTable = {} # if port already in history, get the table if (port in self.history): pTable = self.history[port] # port not in history, create new dictionary entry else: self.history[port] = {} pTable = self.history[port] # Host in history if (host in pTable): prevEntry = pTable[host] # Packet is not the same, update history and send if ((prevEntry.latency != tempLatency) or (host != entry.dst)): pTable[host] = packet send = True # Host not in history, add to history and send else: pTable[host] = packet send = True self.history[port] = pTable if (send): self.send(packet, port=port)