-
Notifications
You must be signed in to change notification settings - Fork 0
/
LSrouter.py
129 lines (110 loc) · 4.37 KB
/
LSrouter.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
####################################################
# LSrouter.py
# Name:
# BU ID:
#####################################################
import sys
from collections import defaultdict
from router import Router
from packet import Packet
from json import dumps, loads
import networkx as nx # implement Dijkstra's algorithm as nx.dijkstra_path
class LSrouter(Router):
"""Link state 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
self.heartbeatTime = heartbeatTime
self.last_time = 0
# Hints: initialize local state
self.fwd_table = {} # Format is dstAddr:port
self.link_state = {self.addr:0} # Format is addr:cost
self.neighbors = {} # Format is addr:port
self.seq = 0
self.G = nx.Graph()
self.G.add_node(0)
def handlePacket(self, port, packet):
"""TODO: process incoming packet"""
if packet.isTraceroute():
# Hints: this is a normal data packet
# if the forwarding table contains packet.dstAddr
# send packet based on forwarding table, e.g., self.send(port, packet)
if packet.dstAddr in self.fwd_table:
sending_port = self.fwd_table[packet.dstAddr]
self.send(sending_port,packet)
else:
# Hints: this is a routing packet generated by your routing protocol
# check the sequence number
# if the sequence number is higher and the received link state is different
# update the local copy of the link state
# update the forwarding table
# broadcast the packet to other neighbors
msg = loads(packet.getContent())
seq_num = msg[0]
recv_state = msg[1]
if not self.seq < seq_num:
self.seq = seq_num
self.G.remove_node(packet.srcAddr)
self.G.add_node(packet.srcAddr)
for port in recv_state:
this_node = recv_state[port][0]
this_cost = recv_state[port][1]
self.G.add_edge(packet.srcAddr,this_node,weight=this_cost)
for dst in self.fwd_table:
path = nx.dijkstra_path(G,0,dst,weight='weight')
self.fwd_table[dst] = self.link_state[path[1]]
to_send_LS = dumps(self.link_state)
for dst in self.link_state:
if dst != port:
pkt = Packet(kind=Packet.ROUTING,srcAddr=self.addr,dstAddr=dst,content=[self.seq,to_send_LS])
self.send(dst,pkt)
def handleNewLink(self, port, endpoint, cost):
"""TODO: handle new link"""
# Hints:
# update the forwarding table
# broadcast the new link state of this router to all neighbors
self.link_state[endpoint] = cost
self.neighbors[endpoint] = port
self.G.add_node(endpoint)
self.G.add_edge(0,endpoint,weight=cost)
for dst in self.fwd_table:
path = nx.dijkstra_path(G,0,dst,weight='weight')
self.fwd_table[dst] = self.neighbors[path[1]]
self.seq += 1
to_send_LS = dumps(self.link_state)
for dst in self.fwd_table:
pkt = Packet(kind=packet.ROUTING,srcAddr=self.addr,dstAddr=dst,content=[self.seq,to_send_LS])
self.send(self.fwd_table[dst],pkt)
def handleRemoveLink(self, port):
"""TODO: handle removed link"""
# Hints:
# update the forwarding table
# broadcast the new link state of this router to all neighbors
self.G.remove_node(self.link_state[port])
for who in self.neighbors:
if self.neighbors[who] == port:
to_remove = who
break
self.link_state.pop(to_remove)
self.neighbors.pop(to_remove)
self.G.remove_node(self.link_state[to_remove])
for dst in self.fwd_table:
path = nx.dijkstra_path(G,0,dst,weight='weight')
self.fwd_table[dst] = self.neighbors[path[1]]
my_seq += 1
to_send_LS = dumps(self.link_state)
for dst in fwd_table:
pkt = Packet(kind=packet.ROUTING,srcAddr=self.addr,dstAddr=dst,content=[my_seq,to_send_LS])
self.send(self.fwd_table[dst],pkt)
def handleTime(self, timeMillisecs):
"""TODO: handle current time"""
if timeMillisecs - self.last_time >= self.heartbeatTime:
self.last_time = timeMillisecs
# Hints:
# broadcast the link state of this router to all neighbors
#for neighbor in link_state:
# self.send(neighbor,link_state)
#pass
def debugString(self):
"""TODO: generate a string for debugging in network visualizer"""
return ""