-
Notifications
You must be signed in to change notification settings - Fork 0
/
Router.py
112 lines (96 loc) · 4.44 KB
/
Router.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import copy
import math
INF = math.inf
class Router:
def __init__(self, name):
self._name = name
self.distance_table = {}
self.updates_to_process = [] # update[i] = (source, distance_table)
self.routing_table = {}
self.update_neighbors = False
def initialize_distance_table(self, nodes):
nodes = nodes.copy()
if self._name in nodes:
nodes.remove(self._name)
for node in nodes:
self.distance_table[node] = {}
for n in nodes:
self.distance_table[node][n] = float('inf')
def print_distance_table(self):
nodes = sorted(self.distance_table.keys())
header = [' '] + nodes
print('\t'.join(header))
for node in nodes:
row = [node] + [str(self.distance_table[node][n]).replace('inf', 'INF') for n in nodes]
print('\t'.join(row))
def update_self(self, graph, routers_list):
neighbors = graph.get_neighbors(self._name)
for neighbor in neighbors:
self.distance_table[neighbor][neighbor] = graph.adj_list[self._name][neighbor]
for router in routers_list:
if router._name not in neighbors and router._name != self._name:
for dest in self.distance_table:
self.distance_table[dest][router._name] = INF
self.update_neighbors = True
def send_updates(self, neighbors, routers_list):
if self.update_neighbors == True:
for router in routers_list:
if router._name in neighbors:
router.updates_to_process.append((self._name, copy.deepcopy(self.distance_table)))
self.update_neighbors = False
def process_received_tables(self):
for update in self.updates_to_process:
received_from = update[0]
received_distance_table = update[1]
for dest in self.distance_table:
if dest == received_from:
continue
for via_node in self.distance_table[dest]:
if via_node == received_from:
previous_cost = self.distance_table[dest][via_node]
cost_to_received_from = self.distance_table[received_from][received_from]
total_cost = cost_to_received_from + self.find_min_cost(received_distance_table, dest)[0]
self.distance_table[dest][received_from] = total_cost
if previous_cost != total_cost:
self.update_neighbors = True
# Reset updates to process
self.updates_to_process = []
def create_routing_table(self):
for dest in self.distance_table:
min_cost, next_hop = self.find_min_cost(self.distance_table, dest)
self.routing_table[dest] = (next_hop, min_cost)
def find_min_cost(self, distance_table, dest):
min_cost = INF
next_hop = None
for node in distance_table[dest]:
if distance_table[dest][node] < min_cost:
min_cost = distance_table[dest][node]
next_hop = node
return (min_cost, next_hop)
def print_routing_table(self):
self.create_routing_table()
print(f"{self._name} Routing Table:")
for dest in sorted(self.routing_table.keys()):
print(f"{dest},{self.routing_table[dest][0]},{self.routing_table[dest][1]}")
print()
def process_after_update(self, graph, routers_list):
original_distance_table = copy.deepcopy(self.distance_table)
self.updates_to_process = []
self.update_self(graph, routers_list)
# Update self with routing tables
neighbors = graph.get_neighbors(self._name)
for router in routers_list:
if (router._name in neighbors):
for dest in router.routing_table:
if dest == self._name:
continue
cost_to_via_node = self.distance_table[router._name][router._name]
via_node_to_dest = router.routing_table[dest][1]
self.distance_table[dest][router._name] = cost_to_via_node + via_node_to_dest
if self.distance_table != original_distance_table:
self.update_neighbors = True
def print_updates(self):
print(f"{self._name} Updates to Process:")
for update in self.updates_to_process:
print(update)
print()