def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() #History data structure # {(port, destination), latency} self.history = {} #Poisoned Routes self.poisoned_routes = set()
def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() self.history = {} self.removedHosts = [] self.emptyFwdTableList = [] self.poisonedHosts = [] self.removedHostKeys = [] self.removedFromPoisonedHosts = [] self.trickledHosts = []
def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() # History data structure, dictionary within a dictionary. Maps ports to a dictionary, inner dictionary maps hosts/dst to advertisement packets self.history = {}
def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Maps a port to the route most recently advertised self.routes_advertised = {} # A random index self.index = 0 # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable()
class DVRouter(basics.DVRouterBase): # NO_LOG = True # Set to True on an instance to disable its logging. # POISON_MODE = True # Can override POISON_MODE here. # DEFAULT_TIMER_INTERVAL = 5 # Can override this yourself for testing. def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() self.history = {} self.port_table = set() 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?" # TODO: fill this in! self.peer_tables[port][host]=PeerTableEntry(host,0,PeerTableEntry.FOREVER) self.update_forwarding_table() self.send_routes(force=False) def handle_link_up(self, port, latency): """ Called by the framework when a link attached to this router goes up. :param port: the port that the link is attached to. :param latency: the link latency. :returns: nothing. """ self.link_latency[port] = latency self.peer_tables[port] = PeerTable() self.port_table.add(port) # TODO: fill in the rest! for neighbor in self.forwarding_table.keys(): packet=basics.RoutePacket(self.forwarding_table[neighbor].dst,self.forwarding_table[neighbor].latency) self.history[(self.forwarding_table[neighbor].dst,port)]=latency self.send(packet,port,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 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 update_forwarding_table(self): """ Computes and stores a new forwarding table merged from all peer tables. :returns: nothing. """ self.forwarding_table.clear() # First, clear the old forwarding table. # TODO: populate `self.forwarding_table` by combining peer tables. for peer in self.peer_tables.keys(): for entry in self.peer_tables[peer].values(): if entry.dst not in self.forwarding_table.keys(): latency = entry.latency + self.link_latency[peer] if entry.latency + self.link_latency[peer] < INFINITY else INFINITY self.forwarding_table[entry.dst]=ForwardingTableEntry(entry.dst,peer,latency) else: if(entry.latency + self.link_latency[peer] < self.forwarding_table[entry.dst].latency): self.forwarding_table[entry.dst] = ForwardingTableEntry(entry.dst,peer,entry.latency + self.link_latency[peer]) def handle_data_packet(self, packet, in_port): """ Called when a data packet arrives at this router. You may want to forward the packet, drop the packet, etc. here. :param packet: the packet that arrived. :param in_port: the port from which the packet arrived. :return: nothing. """ # TODO: fill this in! if packet.dst not in self.forwarding_table: return elif self.forwarding_table[packet.dst].latency >= INFINITY: return else: if self.forwarding_table[packet.dst].port == in_port: return self.send(packet,self.forwarding_table[packet.dst].port,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. """ # TODO: fill this in! if(force==True): if(self.POISON_MODE==True): for neighbor in self.peer_tables: for host, table in self.forwarding_table.items(): if neighbor in self.port_table: #poison only 1 neighbor if neighbor == table.port: packet=basics.RoutePacket(table.dst,INFINITY) self.history[(host,neighbor)]=INFINITY self.send(packet,neighbor) else: packet1=basics.RoutePacket(table.dst,table.latency) self.history[(host,neighbor)]=table.latency self.send(packet1,neighbor) else: for neighbor in self.peer_tables: for host, table in self.forwarding_table.items(): #advertise only to neighbors that are not the same port if(neighbor != table.port): packet1=basics.RoutePacket(table.dst,table.latency) self.history[(host,neighbor)]=table.latency self.send(packet1,neighbor) if(force==False): if(self.POISON_MODE==True): for neighbor in self.peer_tables: for host, table in self.forwarding_table.items(): if neighbor in self.port_table: if (host,neighbor) in self.history.keys() and table.latency != self.history[(host,neighbor)]: if neighbor == table.port: if self.history[(host,neighbor)] != INFINITY: packet=basics.RoutePacket(table.dst,INFINITY) self.history[(host,neighbor)]=INFINITY self.send(packet,neighbor) else: packet1=basics.RoutePacket(table.dst,table.latency) self.history[(host,neighbor)]=table.latency self.send(packet1,neighbor) else: if (host,neighbor) not in self.history.keys(): if neighbor == table.port: packet=basics.RoutePacket(table.dst,INFINITY) self.history[(host,neighbor)]=INFINITY self.send(packet,neighbor) else: packet1=basics.RoutePacket(table.dst,table.latency) self.history[(host,neighbor)]=table.latency self.send(packet1,neighbor) else: for neighbor in self.peer_tables: for host, table in self.forwarding_table.items(): if (host,neighbor) in self.history.keys() and self.forwarding_table[host].latency != self.history[(host,neighbor)]: if neighbor != table.port: if(table.latency >= INFINITY): packet_new = basics.RoutePacket(table.dst,INFINITY) self.history[(host,neighbor)]=INFINITY self.send(packet_new,neighbor) else: packet1=basics.RoutePacket(table.dst,table.latency) self.history[(host,neighbor)]=table.latency self.send(packet1,neighbor) else: if (host,neighbor) not in self.history.keys(): if neighbor != table.port: if(table.latency >= INFINITY): packet_new = basics.RoutePacket(table.dst,INFINITY) self.history[(host,neighbor)]=INFINITY self.send(packet_new,neighbor) else: packet1=basics.RoutePacket(table.dst,table.latency) self.history[(host,neighbor)]=table.latency self.send(packet1,neighbor) 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_timer(self): """ Called periodically. This function simply calls helpers to clear out expired routes and to send the forwarding table to neighbors. """ self.expire_routes() self.send_routes(force=True)
class DVRouter(basics.DVRouterBase): # NO_LOG = True # Set to True on an instance to disable its logging. # POISON_MODE = True # Can override POISON_MODE here. # DEFAULT_TIMER_INTERVAL = 5 # Can override this yourself for testing. def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() #History data structure # {(port, destination), latency} self.history = {} #Poisoned Routes self.poisoned_routes = set() #different route available for a host, do not poison 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?" # TODO: fill this in! self.peer_tables[port] = PeerTable() self.peer_tables[port][host] = PeerTableEntry(host, 0, PeerTableEntry.FOREVER) self.update_forwarding_table() def handle_link_up(self, port, latency): """ Called by the framework when a link attached to this router goes up. :param port: the port that the link is attached to. :param latency: the link latency. :returns: nothing. """ self.link_latency[port] = latency self.peer_tables[port] = PeerTable() for key in self.forwarding_table: if (self.forwarding_table[key].latency) > INFINITY: self.send(basics.RoutePacket(self.forwarding_table[key].dst, INFINITY), port) else: self.send(basics.RoutePacket(self.forwarding_table[key].dst, self.forwarding_table[key].latency), port) 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 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! peer_table = self.peer_tables[port] peer_table[dst] = PeerTableEntry(dst, route_latency, (api.current_time() + ROUTE_TTL)) self.update_forwarding_table() self.send_routes(force=False) def update_forwarding_table(self): """ Computes and stores a new forwarding table merged from all peer tables. :returns: nothing. """ self.forwarding_table.clear() # First, clear the old forwarding table. # TODO: populate `self.forwarding_table` by combining peer tables. # print(self.peer_tables) count = 0 d = {} for port, peer_table in self.peer_tables.items(): for pte in peer_table: if peer_table[pte].dst in d: # print(peer_table) if (peer_table[pte].latency + self.link_latency[port]) < self.forwarding_table[(peer_table[pte].dst)].latency: d[(peer_table[pte].dst)] = peer_table[pte] lat = peer_table[pte].latency + self.link_latency[port] self.forwarding_table[(peer_table[pte].dst)] = ForwardingTableEntry((peer_table[pte].dst), port, lat) else: pass else: d[peer_table[pte].dst] = peer_table[pte] lat = peer_table[pte].latency + self.link_latency[port] self.forwarding_table[peer_table[pte].dst] = ForwardingTableEntry((peer_table[pte].dst), port, lat) # for port, peer_table in self.peer_tables.items(): # if port == 1: # for pte in peer_table: # print(peer_table[pte]) # print(self.forwarding_table) # for key in self.forwarding_table: # print(key) def handle_data_packet(self, packet, in_port): """ Called when a data packet arrives at this router. You may want to forward the packet, drop the packet, etc. here. :param packet: the packet that arrived. :param in_port: the port from which the packet arrived. :return: nothing. """ # TODO: fill this in! for key in self.forwarding_table: if (self.forwarding_table[key].dst == packet.dst): if (self.forwarding_table[key].port != in_port): if (self.forwarding_table[key].latency < INFINITY): self.send(packet, self.forwarding_table[key].port) 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. """ # History data structure # { (port, destination), latency} # self.history = {} # TODO: fill this in! if (force == False): for key in self.forwarding_table: for p in self.peer_tables: # if self.POISON_MODE: if p in self.poisoned_routes: continue if p == self.forwarding_table[key].port: if self.POISON_MODE: if (p, self.forwarding_table[key].dst) in self.history.keys(): if self.history[(p, self.forwarding_table[key].dst)] != self.forwarding_table[key].latency and self.history[(p, self.forwarding_table[key].dst)] != INFINITY: self.history[(p, self.forwarding_table[key].dst)] = INFINITY self.send(basics.RoutePacket(self.forwarding_table[key].dst, INFINITY), p) else: self.history[p, self.forwarding_table[key].dst] = INFINITY self.send(basics.RoutePacket(self.forwarding_table[key].dst, INFINITY), p) else: pass elif (self.forwarding_table[key].latency >= INFINITY): if (p, self.forwarding_table[key].dst) in self.history.keys(): if self.history[(p, self.forwarding_table[key].dst)] != self.forwarding_table[key].latency and self.history[(p, self.forwarding_table[key].dst)] != INFINITY: self.history[(p, self.forwarding_table[key].dst)] = INFINITY self.send(basics.RoutePacket(self.forwarding_table[key].dst, INFINITY), p) else: self.history[(p, self.forwarding_table[key].dst)] = INFINITY self.send(basics.RoutePacket(self.forwarding_table[key].dst, INFINITY), p) else: if (p, self.forwarding_table[key].dst) in self.history.keys(): if self.history[(p, self.forwarding_table[key].dst)] != self.forwarding_table[key].latency: self.history[(p, self.forwarding_table[key].dst)] = self.forwarding_table[key].latency self.send(basics.RoutePacket(self.forwarding_table[key].dst, self.forwarding_table[key].latency), p) else: self.history[(p, self.forwarding_table[key].dst)] = self.forwarding_table[key].latency self.send(basics.RoutePacket(self.forwarding_table[key].dst, self.forwarding_table[key].latency), p) elif (force): for key in self.forwarding_table: for p in self.peer_tables: if p in self.poisoned_routes: continue elif p == self.forwarding_table[key].port: if (self.POISON_MODE): self.history[p, self.forwarding_table[key].dst] = INFINITY self.send(basics.RoutePacket(self.forwarding_table[key].dst, INFINITY), p) else: pass else: if (self.forwarding_table[key].latency) >= INFINITY: self.history[p, self.forwarding_table[key].dst] = INFINITY self.send(basics.RoutePacket(self.forwarding_table[key].dst, INFINITY), p) else: self.history[p, self.forwarding_table[key].dst] = self.forwarding_table[key].latency self.send(basics.RoutePacket(self.forwarding_table[key].dst, self.forwarding_table[key].latency), p) 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_timer(self): """ Called periodically. This function simply calls helpers to clear out expired routes and to send the forwarding table to neighbors. """ self.expire_routes() self.send_routes(force=True) # Feel free to add any helper methods!
class DVRouter(basics.DVRouterBase): # NO_LOG = True # Set to True on an instance to disable its logging. # POISON_MODE = True # Can override POISON_MODE here. # DEFAULT_TIMER_INTERVAL = 5 # Can override this yourself for testing. def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() 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?" # TODO: fill this in! self.update_forwarding_table() def handle_link_up(self, port, latency): """ Called by the framework when a link attached to this router goes up. :param port: the port that the link is attached to. :param latency: the link latency. :returns: nothing. """ self.link_latency[port] = latency self.peer_tables[port] = PeerTable() # TODO: fill in the rest! 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! 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! def update_forwarding_table(self): """ Computes and stores a new forwarding table merged from all peer tables. :returns: nothing. """ self.forwarding_table.clear() # First, clear the old forwarding table. # TODO: populate `self.forwarding_table` by combining peer tables. def handle_data_packet(self, packet, in_port): """ Called when a data packet arrives at this router. You may want to forward the packet, drop the packet, etc. here. :param packet: the packet that arrived. :param in_port: the port from which the packet arrived. :return: nothing. """ # TODO: fill this in! 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. """ # TODO: fill this in! def expire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ # TODO: fill this in! def handle_timer(self): """ Called periodically. This function simply calls helpers to clear out expired routes and to send the forwarding table to neighbors. """ self.expire_routes() self.send_routes(force=True)
class DVRouter(basics.DVRouterBase): # NO_LOG = True # Set to True on an instance to disable its logging. # POISON_MODE = True # Can override POISON_MODE here. # DEFAULT_TIMER_INTERVAL = 5 # Can override this yourself for testing. def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} self.route_hist = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() 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 handle_link_up(self, port, latency): """ Called by the framework when a link attached to this router goes up. :param port: the port that the link is attached to. :param latency: the link latency. :returns: nothing. """ self.link_latency[port] = latency self.peer_tables[port] = PeerTable() for dst, fte in self.forwarding_table.items(): packet = basics.RoutePacket(fte.dst, fte.latency) self.send(packet, port) 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 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. """ pte = PeerTableEntry(dst, route_latency, api.current_time() + ROUTE_TTL) self.peer_tables[port][dst] = pte self.update_forwarding_table() self.send_routes() def update_forwarding_table(self): """ Computes and stores a new forwarding table merged from all peer tables. :returns: nothing. """ self.forwarding_table.clear() # First, clear the old forwarding table. # TODO: populate `self.forwarding_table` by combining peer tables. for port, peer_table in self.peer_tables.items(): # if self.link_latency[port] < INFINITY: for host, entry in peer_table.items(): if host not in self.forwarding_table: self.forwarding_table[host] = ForwardingTableEntry( host, port, min(INFINITY, entry.latency + self.link_latency[port])) elif entry.latency + self.link_latency[ port] < self.forwarding_table[host].latency: self.forwarding_table[host] = ForwardingTableEntry( host, port, min(INFINITY, entry.latency + self.link_latency[port])) def handle_data_packet(self, packet, in_port): """ Called when a data packet arrives at this router. You may want to forward the packet, drop the packet, etc. here. :param packet: the packet that arrived. :param in_port: the port from which the packet arrived. :return: nothing. """ packet_dst = packet.dst if packet_dst in self.forwarding_table and self.forwarding_table[packet_dst].latency < INFINITY and \ in_port != self.forwarding_table[packet_dst].port: self.send(packet, self.forwarding_table[packet_dst].port) else: self.send(packet, None) 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. """ # TODO: fill this in! for dst, fte in self.forwarding_table.items(): for prt in self.link_latency.keys(): if self.link_latency[prt] < INFINITY: packet_key = (prt, dst) if not self.POISON_MODE and force: if prt != fte.port: packet = basics.RoutePacket(dst, fte.latency) self.route_hist[packet_key] = packet self.send(packet, prt) # else: # packet = basics.RoutePacket(fte.port, INFINITY) # self.route_hist[packet_key] = packet # self.send(packet, prt) elif self.POISON_MODE and force: if prt != fte.port: packet = basics.RoutePacket(dst, fte.latency) self.route_hist[packet_key] = packet self.send(packet, prt) else: self.send(basics.RoutePacket(dst, INFINITY), prt) self.route_hist[packet_key] = basics.RoutePacket( (dst, INFINITY), prt) elif self.POISON_MODE and not force: packet = basics.RoutePacket(dst, fte.latency) if packet_key not in self.route_hist or packet.latency != self.route_hist[ packet_key].latency: if prt != fte.port: self.route_hist[packet_key] = packet self.send(packet, prt) else: self.send(basics.RoutePacket(dst, INFINITY), prt) self.route_hist[packet_key] = packet elif not self.POISON_MODE and not force: if prt != fte.port: packet = basics.RoutePacket(dst, fte.latency) if packet_key not in self.route_hist or packet.latency != self.route_hist.get( packet_key ).latency or packet.destination != fte.dst: packet = basics.RoutePacket(dst, fte.latency) self.route_hist[packet_key] = packet self.send(packet, prt) 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_timer(self): """ Called periodically. This function simply calls helpers to clear out expired routes and to send the forwarding table to neighbors. """ self.expire_routes() self.send_routes(force=True)
class DVRouter(basics.DVRouterBase): # NO_LOG = True # Set to True on an instance to disable its logging. # POISON_MODE = True # Can override POISON_MODE here. # DEFAULT_TIMER_INTERVAL = 5 # Can override this yourself for testing. def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() # History data structure, dictionary within a dictionary. Maps ports to a dictionary, inner dictionary maps hosts/dst to advertisement packets self.history = {} 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_link_up(self, port, latency): """ Called by the framework when a link attached to this router goes up. :param port: the port that the link is attached to. :param latency: the link latency. :returns: nothing. """ self.link_latency[port] = latency self.peer_tables[port] = PeerTable() for host, entry in self.forwarding_table.items(): packet = basics.RoutePacket(destination=entry.dst, latency=entry.latency) self.send(packet, port=port) # TODO: fill in the rest! 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.peer_tables.pop(port) self.update_forwarding_table() self.send_routes(force=False) # TODO: fill this in! 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. """ pTable = self.peer_tables[port] pTable[dst] = PeerTableEntry(dst=dst, latency=route_latency, expire_time=api.current_time() + 15) self.update_forwarding_table() self.send_routes(force=False) # TODO: fill this in! def update_forwarding_table(self): """ Computes and stores a new forwarding table merged from all peer tables. :returns: nothing. """ self.forwarding_table.clear() # First, clear the old forwarding table. newFT = self.forwarding_table for port, table in self.peer_tables.items(): for host, entry in table.items(): # print(host, entry) currLatency = float(entry.latency) + float( self.link_latency[port]) # print(currLatency, int(entry.latency)) # Host exists, has a entry in it if (host in newFT): # Get old latency oldLatency = newFT[host].latency # Compare with newLatency, if less, replace object in forwarding table if (currLatency < oldLatency): newEntry = ForwardingTableEntry(dst=host, port=port, latency=currLatency) newFT[host] = newEntry else: # forwarding entry doesn't exist for this host, add it newEntry = ForwardingTableEntry(dst=host, port=port, latency=currLatency) newFT[host] = newEntry self.forwarding_table = newFT # TODO: populate `self.forwarding_table` by combining peer tables. def handle_data_packet(self, packet, in_port): """ Called when a data packet arrives at this router. You may want to forward the packet, drop the packet, etc. here. :param packet: the packet that arrived. :param in_port: the port from which the packet arrived. :return: nothing. """ toDST = packet.dst # Check if destination is in the forwarding table, if not drop packet if (toDST in self.forwarding_table): forwardingEntry = self.forwarding_table[toDST] # Check if distance to destination is not long, if it is, drop packet (to prevent loops) if (forwardingEntry.latency < INFINITY): # Check if packet's in_port is different from out_port, if yes, send packet if (forwardingEntry.port is not in_port): self.send(packet, port=forwardingEntry.port) # TODO: fill this in! 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) # for host, entry in self.forwarding_table.items(): # tempLatency = None # if (entry.latency > INFINITY): # tempLatency = INFINITY # else: # tempLatency = entry.latency # packet = basics.RoutePacket(destination=entry.dst, latency=tempLatency) # self.send(packet, port=entry.port, flood=force) # TODO: fill this in! def expire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ for port, table in self.peer_tables.items(): for host, entry in table.items(): if (entry.expire_time == PeerTableEntry.FOREVER): continue if (entry.expire_time < api.current_time()): table.pop(host) self.update_forwarding_table() # TODO: fill this in! def handle_timer(self): """ Called periodically. This function simply calls helpers to clear out expired routes and to send the forwarding table to neighbors. """ self.expire_routes() self.send_routes(force=True)
class DVRouter(basics.DVRouterBase): # NO_LOG = True # Set to True on an instance to disable its logging. # POISON_MODE = True # Can override POISON_MODE here. # DEFAULT_TIMER_INTERVAL = 5 # Can override this yourself for testing. def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() self.history = {} self.removedHosts = [] self.emptyFwdTableList = [] self.poisonedHosts = [] self.removedHostKeys = [] self.removedFromPoisonedHosts = [] self.trickledHosts = [] 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?" dst = host latency = 0 expire_time = PeerTableEntry.FOREVER pte = PeerTableEntry(dst, latency, expire_time) self.peer_tables[port][host] = pte self.update_forwarding_table() self.send_routes(force=False) def handle_link_up(self, port, latency): """ Called by the framework when a link attached to this router goes up. :param port: the port that the link is attached to. :param latency: the link latency. :returns: nothing. """ self.link_latency[port] = latency self.peer_tables[port] = PeerTable() for key in self.forwarding_table.keys(): adPacket = basics.RoutePacket( key, self.forwarding_table.get(key).latency) self.send(adPacket, port, flood=False) fte = ForwardingTableEntry(key, port, self.forwarding_table.get(key).latency) self.history[(port, key)] = fte 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. """ for x in self.forwarding_table.keys(): if self.forwarding_table[x][1] == port: if ([self.forwarding_table[x][0], port]) not in self.removedHosts: self.removedHosts += [[self.forwarding_table[x][0], port]] self.poisonedHosts += [[self.forwarding_table[x][0], port]] del self.forwarding_table[x] if (port in self.peer_tables.keys()): del self.peer_tables[port] for elem in self.removedHosts: for item in self.history.keys(): if elem[1] != item[0] and elem[0] == item[1]: del self.history[item] 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. """ currentPTE = PeerTableEntry(dst, route_latency, api.current_time() + ROUTE_TTL) self.peer_tables[port][dst] = currentPTE self.update_forwarding_table() self.send_routes(force=False) def update_forwarding_table(self): """ Computes and stores a new forwarding table merged from all peer tables. :returns: nothing. """ self.forwarding_table.clear() # First, clear the old forwarding table. for port, peer_table in self.peer_tables.items(): currCost = 0 key = None for host, value in peer_table.items(): key = host if (self.peer_tables.get(port)): currCost = self.link_latency[port] + value.latency else: currCost = self.link_latency[port] if ( currCost > INFINITY ): #Stage 3: Cap route latency at INFINITY when you create a ForwardingTableEntry currCost = INFINITY if (self.forwarding_table.get(key)): prevCost = self.forwarding_table.get(key).latency if (currCost < prevCost): prevCost = currCost fwdTableEntry = ForwardingTableEntry( key, port, prevCost) self.forwarding_table[key] = fwdTableEntry else: fwdTableEntry = ForwardingTableEntry(key, port, currCost) self.forwarding_table[key] = fwdTableEntry def handle_data_packet(self, packet, in_port): """ Called when a data packet arrives at this router. You may want to forward the packet, drop the packet, etc. here. :param packet: the packet that arrived. :param in_port: the port from which the packet arrived. :return: nothing. """ destination = packet.dst if (not self.forwarding_table.get(destination)): return dist = self.forwarding_table.get(destination).latency if (dist >= INFINITY): return out_port = self.forwarding_table.get(destination).port if (out_port == in_port): return self.send(packet, out_port, flood=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. """ for port, peer_table in self.peer_tables.items(): for key, item in self.forwarding_table.items(): fwdPorts = item.port if (self.POISON_MODE): if (port == fwdPorts): if force == False: if (port, key) not in self.history.keys() or ( self.history[(port, key)][0] != key or self.history[(port, key)][2] != INFINITY): adPacket = basics.RoutePacket(key, INFINITY) self.send(adPacket, port, flood=False) fte = ForwardingTableEntry(key, port, INFINITY) self.history[(port, key)] = fte else: adPacket = basics.RoutePacket(key, INFINITY) self.send(adPacket, port, flood=False) fte = ForwardingTableEntry(key, port, INFINITY) self.history[(port, key)] = fte else: if force == False: if (port, key) not in self.history.keys() or ( self.history[(port, key)][0] != key or self.history[ (port, key)][2] != item.latency): adPacket = basics.RoutePacket( key, item.latency) self.send(adPacket, port, flood=False) fte = ForwardingTableEntry( key, port, item.latency) self.history[(port, key)] = fte else: adPacket = basics.RoutePacket(key, item.latency) self.send(adPacket, port, flood=False) fte = ForwardingTableEntry(key, port, item.latency) self.history[(port, key)] = fte elif (not self.POISON_MODE and port != fwdPorts): adPacket = basics.RoutePacket(key, item.latency) if force == False: if (port, key) not in self.history.keys() or ( self.history[(port, key)][0] != key or self.history[(port, key)][2] != item.latency): self.send(adPacket, port, flood=False) fte = ForwardingTableEntry(key, port, item.latency) self.history[(port, key)] = fte else: self.send(adPacket, port, flood=False) fte = ForwardingTableEntry(key, port, item.latency) self.history[(port, key)] = fte tempList = [] if (self.POISON_MODE): for rem in self.removedHosts: for port in self.peer_tables.keys(): host = rem[0] if (force == False): if rem not in self.poisonedHosts: break if (force == True): if (port, host) in self.history.keys(): val = self.history[(port, host)] if val[2] != INFINITY: if (len(self.forwarding_table) == 0): if (port, host) in self.history.keys( ) and (port, host) not in self.emptyFwdTableList: self.emptyFwdTableList += [(port, host) ] elif (port, host) in self.emptyFwdTableList: break for key, value in self.forwarding_table.items( ): if host != key and ( port, host) in self.history.keys(): del self.history[(port, host)] elif (host == key): tempList += [(port, key)] else: if (len(self.forwarding_table) == 0): if (port, host) in self.history.keys( ) and (port, host) not in self.emptyFwdTableList: self.emptyFwdTableList += [(port, host) ] elif (port, host) in self.emptyFwdTableList: break for key, value in self.forwarding_table.items( ): if (key == host and value[1] == port): tempList += [(port, key)] else: if ((port, host) in self.history.keys()): if [ host, port ] in self.removedFromPoisonedHosts: pass else: del self.history[(port, host)] if ((port, host) not in self.history.keys() or self.emptyFwdTableList): if (port, host) in tempList: continue if [host, port] in self.removedFromPoisonedHosts: continue if [host, port] in self.trickledHosts: continue adPacket = basics.RoutePacket(host, INFINITY) self.send(adPacket, port, flood=False) fte = ForwardingTableEntry(host, port, INFINITY) self.history[(port, host)] = fte if (self.POISON_MODE): if (force == False): for elem in self.poisonedHosts: if elem in self.removedHosts: self.poisonedHosts.remove(elem) self.removedFromPoisonedHosts += [elem] def expire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ for port, peer_table in self.peer_tables.items(): for host, value in peer_table.items(): if (value.expire_time == PeerTableEntry.FOREVER): return if (api.current_time() > value.expire_time): for dest, fwdEntry in self.forwarding_table.items(): if (dest == host): if [dest, port] not in self.removedHosts: self.removedHosts += [[dest, port]] self.poisonedHosts += [[dest, port]] del self.peer_tables[port][dest] self.update_forwarding_table() def handle_timer(self): """ Called periodically. This function simply calls helpers to clear out expired routes and to send the forwarding table to neighbors. """ self.expire_routes() self.send_routes(force=True)
class DVRouter(basics.DVRouterBase): # NO_LOG = True # Set to True on an instance to disable its logging. POISON_MODE = True # Can override POISON_MODE here. # DEFAULT_TIMER_INTERVAL = 5 # Can override this yourself for testing. def __init__(self): """ Called when the instance is initialized. DO NOT remove any existing code from this method. """ self.start_timer() # Starts calling handle_timer() at correct rate. # Maps a port to the latency of the link coming out of that port. self.link_latency = {} # Maps a port to the PeerTable for that port. # Contains an entry for each port whose link is up, and no entries # for any other ports. self.peer_tables = {} # Maps a port to the route most recently advertised self.routes_advertised = {} # A random index self.index = 0 # Forwarding table for this router (constructed from peer tables). self.forwarding_table = ForwardingTable() 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?" staticRoute = PeerTableEntry(host, 0, PeerTableEntry.FOREVER) self.peer_tables.get(port).update({host: staticRoute}) self.update_forwarding_table() self.send_routes(force=False) def handle_link_up(self, port, latency): """ Called by the framework when a link attached to this router goes up. :param port: the port that the link is attached to. :param latency: the link latency. :returns: nothing. """ self.link_latency[port] = latency self.peer_tables[port] = PeerTable() for host, ftEntry in self.forwarding_table.items(): tempPacket = basics.RoutePacket(host, ftEntry.latency) self.send(tempPacket, port, flood=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. """ self.peer_tables = { tempPort: tempTable for tempPort, tempTable in self.peer_tables.items() if tempPort != port } 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. """ 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 update_forwarding_table(self): """ Computes and stores a new forwarding table merged from all peer tables. :returns: nothing. """ oldForwardingTable = dict(self.forwarding_table) self.forwarding_table.clear() # First, clear the old forwarding table. for port, tempPeerTable in self.peer_tables.items(): for host, entry in tempPeerTable.items(): if ((self.forwarding_table.get(host, 110010100) == 110010100) or ((entry.latency + self.link_latency.get(port)) < self.forwarding_table.get(host).latency)): tempFTE = ForwardingTableEntry( host, port, self.link_latency.get(port) + entry.latency) self.forwarding_table.update({host: tempFTE}) # if (self.POISON_MODE): # balogneList = [] # self.index = 50 # for oldKey, oldValue in oldForwardingTable.items(): # marker = True # for key, value in self.forwarding_table.items(): # if (oldKey == key) and (oldValue == value): # marker = False # if (marker): # balogneList.append((oldKey, oldValue)) # loopTimer = api.current_time() + 15 # while (self.index > 0): # for port in self.peer_tables.keys(): # # Maybe not same port endless loop # for tempRoute in balogneList: # self.send(basics.RoutePacket(tempRoute[0], tempRoute[1].latency), port, flood=False) # self.index = self.index - 1 def handle_data_packet(self, packet, in_port): """ Called when a data packet arrives at this router. You may want to forward the packet, drop the packet, etc. here. :param packet: the packet that arrived. :param in_port: the port from which the packet arrived. :return: nothing. """ forwardingTableEntry = self.forwarding_table.get(packet.dst, 110010100) if not (forwardingTableEntry == 110010100): if (in_port != forwardingTableEntry.port) and ( forwardingTableEntry.latency < INFINITY): self.send(packet, forwardingTableEntry.port, flood=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. """ listOfPorts = self.peer_tables.keys() ftEntries = self.forwarding_table.values() routes_advertised_toUpdate = [] if (force): for ftEntry in ftEntries: for port in listOfPorts: if (port != ftEntry.port): tempPacket = basics.RoutePacket( ftEntry.dst, ftEntry.latency if ftEntry.latency < INFINITY else INFINITY) self.send(tempPacket, port, flood=False) # self.routes_advertised.update({(ftEntry.dst, port): ftEntry.latency}) routes_advertised_toUpdate.append({ (ftEntry.dst, port): ftEntry.latency }) elif ((self.POISON_MODE) and (port == ftEntry.port) and (ftEntry.latency != self.link_latency.get(port))): tempPacket = basics.RoutePacket(ftEntry.dst, INFINITY) self.send(tempPacket, port, flood=False) # self.routes_advertised.update({(ftEntry.dst, port): ftEntry.latency}) routes_advertised_toUpdate.append({ (ftEntry.dst, port): ftEntry.latency }) self.routes_advertised.update({ (ftEntry.dst, port): ftEntry.latency }) else: # for host, entry in self.forwarding_table.items(): # for port in listOfPorts: # toSend = None # if (port != entry.port): # toSend = basics.RoutePacket(entry.dst, entry.latency if entry.latency < INFINITY else INFINITY) # elif (self.POISON_MODE and port == entry.port and entry.latency != self.link_latency.get(port)): # toSend = basics.RoutePacket(entry.dst, entry.latency if entry.latency < INFINITY else INFINITY) # if (toSend != None): # if ((self.routes_advertised.get((entry.dst, port)) != (entry.latency)) or ((entry.dst, port) not in self.routes_advertised.keys())): # self.send(toSend, port, flood=False) # self.routes_advertised.update({(toSend.dst, port): toSend.latency}) # make packet -> compare packet latency history # key = (destination, port (advertised out of)) -> (latency) # if (self.routes_advertised.get(port) == ) # for ftEntry in ftEntries: # for port in listOfPorts: # if (self.POISON_MODE): # if (port == ftEntry.port): # tempPacket = basics.RoutePacket(ftEntry.dst, INFINITY) # if ((not self.packet_in_list(tempPacket, self.routes_advertised.values())) # or (not self.compare_packets(tempPacket, self.routes_advertised.get(ftEntry.port)))): # self.send(tempPacket, port, flood=False) # self.routes_advertised.update({port: tempPacket}) # if (port != ftEntry.port): # tempPacket = basics.RoutePacket(ftEntry.dst, ftEntry.latency if ftEntry.latency < INFINITY else INFINITY) # if ((not self.packet_in_list(tempPacket, self.routes_advertised.values())) # or (not self.compare_packets(tempPacket, self.routes_advertised.get(ftEntry.port)))): # self.send(tempPacket, port, flood=False) # self.routes_advertised.update({port: tempPacket}) # if ((not self.POISON_MODE) and (port != ftEntry.port)): # self.send(tempPacket, port, flood=False) # self.routes_advertised.update({port: tempPacket}) # elif ((self.POISON_MODE) and (port == ftEntry.port) and (ftEntry.latency != self.link_latency.get(port))): # tempPacket = basics.RoutePacket(ftEntry.dst, INFINITY) # if ((not self.packet_in_list(tempPacket, self.routes_advertised.values())) # or (not self.compare_packets(tempPacket, self.routes_advertised.get(ftEntry.port)))): # self.send(tempPacket, port, flood=False) # self.routes_advertised.update({port: tempPacket}) # for entry in ftEntries: # for port in listOfPorts: # if (port != entry.port): # # self.send(tempPacket, port, flood=False) # # routes_advertised_toUpdate.append({(entry.dst, port): entry.latency}) # packetToSend = basics.RoutePacket(entry.dst, entry.latency if entry.latency < INFINITY else INFINITY) # elif (self.POISON_MODE): # if ((port == entry.port) and (entry.latency != self.link_latency.get(port))): # packetToSend = basics.RoutePacket(entry.dst, INFINITY) # else: # packetToSend = basics.RoutePacket(entry.dst, -1) # if ((self.routes_advertised.get((entry.dst, port)) != entry.latency) # or (self.history_checker(entry, port))): # if (packetToSend.latency != -1): # self.send(packetToSend, port, flood=False) # self.routes_advertised.update({(entry.dst, port): packetToSend.latency}) # else: # continue # routes_advertised_toUpdate.append({(entry.dst, port): entry.latency}) # [self.routes_advertised.update(tempRoute) for tempRoute in routes_advertised_toUpdate] # 25/29 IMPLEMENTATION COPY for entry in ftEntries: tempPacket = basics.RoutePacket( entry.dst, entry.latency if entry.latency < INFINITY else INFINITY) for port in listOfPorts: if ((self.routes_advertised.get( (entry.dst, port)) != entry.latency) or (self.history_checker(entry, port))): if (port != entry.port): self.send(tempPacket, port, flood=False) # self.send_helper(tempPacket, port) routes_advertised_toUpdate.append({ (entry.dst, port): entry.latency }) if (self.POISON_MODE): if ((port == entry.port) and (entry.latency != self.link_latency.get(port))): tempPacket = basics.RoutePacket( entry.dst, INFINITY) if ((self.routes_advertised.get( (entry.dst, port)) != (entry.latency)) or ((entry.dst, port) not in self.routes_advertised.keys())): self.send(tempPacket, entry.port, flood=False) # self.send_helper(tempPacket, port) routes_advertised_toUpdate.append({ (entry.dst, port): entry.latency }) tempPacket = basics.RoutePacket( entry.dst, entry.latency if entry.latency < INFINITY else INFINITY) routes_advertised_toUpdate.append({ (entry.dst, port): entry.latency }) [ self.routes_advertised.update(tempRoute) for tempRoute in routes_advertised_toUpdate ] # # 23/29 IMPLEMENTATION # for ftEntry in ftEntries: # tempPacket = basics.RoutePacket(ftEntry.dst, ftEntry.latency if ftEntry.latency < INFINITY else INFINITY) # if ((not self.packet_in_list(tempPacket, self.routes_advertised.values())) # or (not self.compare_packets(tempPacket, self.routes_advertised.get(ftEntry.port)))): # for port in listOfPorts: # if (port != ftEntry.port): # self.send(tempPacket, port, flood=False) # routes_advertised_toUpdate.append({ftEntry.port: tempPacket}) # if ((self.POISON_MODE) and (port == ftEntry.port) and (ftEntry.latency != self.link_latency.get(port))): # tempPacket = basics.RoutePacket(ftEntry.dst, INFINITY) # if ((not self.packet_in_list(tempPacket, self.routes_advertised.values())) # or (not self.compare_packets(self.routes_advertised.get(ftEntry.port), tempPacket))): # self.send(tempPacket, ftEntry.port, flood=False) # routes_advertised_toUpdate.append({ftEntry.port: tempPacket}) # tempPacket = basics.RoutePacket(ftEntry.dst, ftEntry.latency if ftEntry.latency < INFINITY else INFINITY) # # routes_advertised_toUpdate.append({ftEntry.port: tempPacket}) # [self.routes_advertised.update(tempRoute) for tempRoute in routes_advertised_toUpdate] # FIRST PART OF SEND # if (self.POISON_MODE): # for ftEntry in ftEntries: # for port in listOfPorts: # if ((port == ftEntry.port) and (ftEntry.latency != self.link_latency.get(port))): # tempPacket = basics.RoutePacket(ftEntry.dst, INFINITY) # self.send(tempPacket, port, flood=False) # self.routes_advertised.update({port: tempPacket}) # else: # tempPacket = basics.RoutePacket(ftEntry.dst, ftEntry.latency if ftEntry.latency < INFINITY else INFINITY) # self.send(tempPacket, port, flood=False) # self.routes_advertised.update({port: tempPacket}) # else: # for ftEntry in ftEntries: # tempPacket = basics.RoutePacket(ftEntry.dst, ftEntry.latency if ftEntry.latency < INFINITY else INFINITY) # for port in listOfPorts: # if (port != ftEntry.port): # self.send(tempPacket, port, flood=False) # self.routes_advertised.update({port: tempPacket}) # def send_helper(self, packet, port): # packetsAdvertisedList = self.routes_advertised.values() # marker = True # for tempRoute in packetsAdvertisedList: # if ((tempRoute.latency == packet.latency) and (tempRoute.dst == packet.dst)): # marker = False # if (self.routes_advertised.get(port) == packet): # marker = False # if (marker): # self.send(packet, port, flood=False) # self.routes_advertised.update({port: packet}) def compare_packets(self, packetA, packetB): """ Compares the the destinations and latency of two packets to see if they equate to the same route. """ if (type(packetB) == type(None)): return False if ((packetA.latency == packetB.latency) and (packetA.dst == packetB.dst)): return True return False def packet_in_list(self, packet, packetList): for tempPacket in packetList: if ((packet.latency == tempPacket.latency) and (packet.dst == tempPacket.dst)): return True return False def history_checker(self, entry, port): routeLatency = entry.latency destination = entry.dst for key, value in self.routes_advertised.items(): # pdb.set_trace() if ((key[0] == destination) and (value == routeLatency)): return False return True def expire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ for port, peerTable in self.peer_tables.items(): peerTable = { host: ptEntry for host, ptEntry in peerTable.items() if ptEntry.expire_time > api.current_time() } self.peer_tables.update({port: peerTable}) self.update_forwarding_table() def handle_timer(self): """ Called periodically. This function simply calls helpers to clear out expired routes and to send the forwarding table to neighbors. """ self.expire_routes() self.send_routes(force=True)