/
DVrouter.py
211 lines (138 loc) · 8.01 KB
/
DVrouter.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
####################################################
# DVrouter.py
# Names: Jiachen Wang
# Names: Chang Lee
# Penn IDs: 49678282
# Penn IDs: 23888214
#####################################################
import sys
from collections import defaultdict
from router import Router
from packet import Packet
from json import dumps, loads
class DVrouter(Router):
"""Distance vector routing protocol implementation."""
def __init__(self, addr, heartbeatTime):
"""TODO: add your own class fields and initialization code here"""
Router.__init__(self, addr) # initialize superclass - don't remove
# so it has a destination address, a nextHop, a cost
# use dictionary,router has a table
self.routing_table = {}
self.hearbeatTime = heartbeatTime
self.lastTime = 0
self.infinity = 16
self.neighboursPort = {}
self.neighboursAddr = {}
def handlePacket(self, port, packet):
"""TODO: process incoming packet"""
# We should use that port to find who send us the packet!!!
# Port is where the packet arrives
if packet.kind == Packet.ROUTING:
content = packet.getContent()
new_table = loads(content)
neighbor_addr = packet.srcAddr
if self.updateTable(neighbor_addr, new_table):
# Table has been updated
# broadcasting the packet
self.broadcast()
elif packet.kind == Packet.TRACEROUTE:
# if it is traceroute, we just forward it
correct_port = None
for key in self.routing_table:
if (key == packet.dstAddr):
correct_port = self.routing_table[key]['egress']
break
if (correct_port != None):
self.send(correct_port, packet)
def handleNewLink(self, port, endpoint, cost):
"""TODO: handle new link"""
self.neighboursPort[port] = endpoint
self.neighboursAddr[endpoint] = {'port': port, 'cost': cost }
if endpoint not in self.routing_table :
self.routing_table[endpoint] = {'cost': cost, 'nextHop': endpoint, 'egress': port}
self.broadcast()
else:
if cost < self.routing_table[endpoint]['cost']:
# we have a better route
self.routing_table[endpoint] = {'cost': cost, 'nextHop': endpoint, 'egress': port}
self.broadcast()
def handleRemoveLink(self, port):
"""TODO: handle removed link"""
neighbor_addr = self.neighboursPort[port]
del self.neighboursPort[port]
del self.neighboursAddr[neighbor_addr]
for key in self.routing_table:
if (self.routing_table[key]['egress']== port):
self.routing_table[key]['cost'] = self.infinity
self.routing_table[key]['nextHop'] = ''
self.routing_table[key]['egress']== -1
self.broadcast()
def handleTime(self, timeMillisecs):
"""TODO: handle current time"""
if (timeMillisecs - self.lastTime) >= self.hearbeatTime:
self.broadcast()
self.lastTime = timeMillisecs
def debugString(self):
"""TODO: generate a string for debugging in network visualizer"""
#print ("not good")
return ""
def broadcast(self):
new_content = dumps(self.routing_table)
for port in self.neighboursPort:
packet = Packet(Packet.ROUTING, self.addr, self.neighboursPort[port], new_content)
self.send(port, packet)
# design a updateTable function, return true if we need to update the table, false otherwise
# the arguments are neighbor_addr and the new_table. neighbor_addr is the neighbor who send us the packet
# new_table is the content of its packet.
def updateTable(self, neighbor_addr, new_table):
# use this function to check if you need to update the Table or not
# if return false, it means that there is no update, we just don't need to send
# if return true, it means that the data has been updated, so we need to send packets
# we need to have a flag to check if we need to update our table.
flag= False
cost_to_neighbor = self.routing_table[neighbor_addr]['cost']
for destAddr in new_table:
if destAddr not in self.routing_table:
if(destAddr == self.addr):
if(new_table[destAddr]['cost']< self.routing_table[neighbor_addr]['cost']):
self.routing_table[neighbor_addr]['cost'] = new_table[destAddr]['cost']
flag = True
elif((new_table[destAddr]['cost']+ cost_to_neighbor) < self.infinity):
flag = True
# means we don't have this table entry in our table
self.routing_table[destAddr] = {'cost': (cost_to_neighbor + new_table[destAddr]['cost']), 'nextHop': self.routing_table[neighbor_addr]['nextHop'], 'egress': self.routing_table[neighbor_addr]['egress']}
elif((new_table[destAddr]['cost']+ cost_to_neighbor) >= self.infinity):
# means we don't have this table entry in our table, but it is infinity
# so we set it as infinity
flag = True
self.routing_table[destAddr] = {'cost': self.infinity, 'nextHop': '', 'egress': -1}
else:
cost_now = self.routing_table[destAddr]['cost']
cost_through = cost_to_neighbor + new_table[destAddr]['cost']
if cost_through > self.infinity:
cost_through = self.infinity
if cost_through < cost_now:
# we found a better route
self.routing_table[destAddr]['cost'] = cost_through
self.routing_table[destAddr]['nextHop'] = neighbor_addr
self.routing_table[destAddr]['egress'] = self.routing_table[neighbor_addr]['egress']
flag = True
elif neighbor_addr == self.routing_table[destAddr]['nextHop']:
# we need to go through this neighbour to get to the destination
if cost_through != cost_now:
if cost_through == self.infinity:
if destAddr in self.neighboursAddr:
# This means that the destination is our neighbour, so we go there directly
self.routing_table[destAddr]['cost'] = self.neighboursAddr[destAddr]['cost']
self.routing_table[destAddr]['nextHop'] = destAddr
self.routing_table[destAddr]['egress'] = self.neighboursAddr[destAddr]['port']
else:
# It is not our neighbour, we sould set that destination unreachable
self.routing_table[destAddr]['cost'] = self.infinity
self.routing_table[destAddr]['nextHop']= ''
self.routing_table[destAddr]['egress'] = -1
else:
# cost_through is not infinity, we should update
self.routing_table[destAddr]['cost'] = cost_through
flag = True
return flag