Initialization: for all destinations y in N: D(x, y) = c(x,y) if y is not a neighbor then c(x,y) = ∞ for each neighbor w: D(w, y) = ? for all destinations y in N for each neighbor w: send distance vector D(x, y) = [D(x, y) : y in N] to w loop: wait (until I see a link cost change to some neighbor w or until I receive a distance vector from some neighbor w)
for each y in N: D(x, y) = minv(c(x, v) + D(v, y))
if D(x, y) changed for any destination y send sitance vector D(x, y) = [D(x, y) : y in N] to all neighbors forever
项目实现
计算转发表
1 2 3 4 5 6 7 8
defupdate_forwarding_table(self): for port, peer_table in self.peer_tables.items(): for host, entry in peer_table.items(): ifnot host in self.forwarding_table: self.forwarding_table[host] = ForwardingTableEntry(host, port, self.link_latency[port] + entry.latency) else: if self.forwarding_table[host].latency > self.link_latency[port] + entry.latency: self.forwarding_table[host] = ForwardingTableEntry(host, port, self.link_latency[port] + entry.latency)
defhandle_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 in self.forwarding_table and self.forwarding_table[packet.dst].latency < INFINITY and self.forwarding_table[packet.dst].port != in_port: self.send(packet, self.forwarding_table[packet.dst].port)
defhandle_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! for host, entry in self.forwarding_table.items(): packet = basics.RoutePacket(host, entry.latency) self.send(packet, port)
转发表中的每一个路由信息都发送给新加入的链路的另一端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defsend_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: for port in self.peer_tables: for host, entry in self.forwarding_table.items(): if entry.port != port: if entry.latency >= INFINITY: route_packet = basics.RoutePacket(host, INFINITY) else: route_packet = basics.RoutePacket(host, entry.latency) self.send(route_packet, port)
defadd_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()
处理路由通知(handle route advertisement)
1 2 3 4 5 6 7 8 9 10 11 12 13
defhandle_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()
defhandle_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! for host, entry in self.forwarding_table.items(): if entry.port == port: del self.forwarding_table[host] del self.peer_tables[port] del self.link_latency[port] self.update_forwarding_table() self.send_routes()
defexpire_routes(self): """ Clears out expired routes from peer tables; updates forwarding table accordingly. """ # TODO: fill this in! for port, table in self.peer_tables.items(): for dst, entry in table.items(): if api.current_time() > entry.expire_time: table.pop(dst) self.update_forwarding_table()