-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlsrouter_listener.py
219 lines (200 loc) · 9.33 KB
/
lsrouter_listener.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
212
213
214
215
216
217
218
219
import threading
import logging
import time
from graph import graph
from dijkstra import *
from type import *
class LsRouterListener(threading.Thread):
def __init__(self, router_socket, routing_table, buffer):
threading.Thread.__init__(self)
self.router_socket = router_socket
self.routing_table = routing_table
self.buffer = buffer
self.listen = True
self.routing_table.graph = self.create_graph()
def create_graph(self):
newgraph = graph()
newgraph.add_node(self.routing_table.router_name)
# for key in self.routing_table.neighbours:
# newgraph.add_node(key)
# newgraph.add_edge((self.routing_table.router_name, key), \
# int(self.routing_table.neighbours[key][2]))
# self.routing_table.table = get_next_step(newgraph, \
# self.routing_table.router_name)
self.routing_table.update()
return newgraph
def run(self):
""" Listens and received packets from network"""
logging.info("Starting listener thread")
while self.listen:
data,addr = self.router_socket.recvfrom(4096)
if not data:
logging.error("Error packet received from ", addr)
else:
self.package_handling(data, addr)
def package_handling(self, packet, addr):
""" Handles the received packets based on the type"""
packet = packet.decode('ASCII')
tokens = packet.split(' ')
if tokens[0] == Type.HELLO:
self.handle_hello(tokens)
elif tokens[0] == Type.LSP:
self.handle_lsp(tokens,addr)
elif tokens[0] == Type.LSACK:
self.handle_ack(tokens, addr)
elif tokens[0] == Type.DATA:
logging.debug("Received DATA packet from " + tokens[1])
if len(tokens) != 4:
logging.error("Hello Packet error")
sender = tokens[1]
receiver = tokens[2]
msg = " "
msg = msg.join(tokens[3:])
if receiver == self.routing_table.router_name:
# Packet destination is self
print("Message received from " + tokens[1] +":\n"+msg)
else:
self.buffer.add_send([Type.DATA,sender, receiver, msg])
else:
logging.error("Invalid packet received")
def handle_hello(self, tokens):
logging.debug("Received HELLO packet from " + tokens[1])
if len(tokens) != 3:
logging.error("Hello Packet error")
sender = tokens[1]
receiver = tokens[2]
if receiver == self.routing_table.router_name:
if sender in self.routing_table.neighbours:
self.routing_table.neighbours[sender][3] = time.time()
if not self.routing_table.neighbours[sender][4] :
# Link is now active
logging.info("New active link "+sender)
self.routing_table.neighbours[sender][4] = True
if not self.routing_table.graph.has_node(sender):
self.routing_table.graph.add_node(sender)
if not self.routing_table.graph.has_edge((self.routing_table.router_name, sender)):
self.routing_table.graph.add_edge((self.routing_table.router_name, sender), \
int(self.routing_table.neighbours[sender][2]))
self.routing_table.table = get_next_step(self.routing_table.graph, \
self.routing_table.router_name)
self.routing_table.update()
self.send_lsp()
else:
logging.error("Received HELLO from unknown")
else:
logging.warning("Received HELLO not intended to router")
def handle_lsp(self, tokens, addr):
""" Handle LSP packets. Discard if already received,
update routing table and forward if not already received"""
sender = tokens[1]
seq_nb = tokens[2]
# Keep track of seq to avoid multiple receive and send of lsack
if sender == self.routing_table.router_name:
# Skip forwarded packet that was initited by this router
logging.debug("Skipping LSP initiatest by us "+seq_nb+ " from "+sender)
self.buffer.add_send([Type.LSACK, sender, seq_nb, addr])
return
if sender in self.routing_table.seq:
if self.routing_table.seq[sender] == seq_nb:
# LSP already received, skip it
logging.debug("Skipping already received LSP "+seq_nb)
self.buffer.add_send([Type.LSACK, sender, seq_nb,addr])
return
else:
old_seq = self.routing_table.seq[sender]
if int(seq_nb) == int(old_seq)+1:
# Good Seq received, ack it
# Excpected Newer
logging.debug("Received LSP from "+sender+" seq # "+seq_nb)
self.routing_table.seq[sender] = seq_nb
else:
# Check if packet is newer of older
if (int(old_seq)+1)%100 <= int(seq_nb) and int(seq_nb) <= (int(old_seq)+51)%100:
# Newer
logging.debug("Received LSP from "+sender+" seq # "+seq_nb)
self.routing_table.seq[sender] = seq_nb
else:
# Older. Ack it
self.buffer.add_send([Type.LSACK, sender, seq_nb, addr])
return
else:
# Add entry to routing table
# Parse lsp and put it in table
#sender not in routing table and thus, not in graph
self.routing_table.seq[sender] = seq_nb
if sender not in self.routing_table.table and sender not in self.routing_table.graph:
self.routing_table.graph.add_node(sender)
changed = self.add_edges(tokens)
if changed:
self.routing_table.table = get_next_step(self.routing_table.graph, \
self.routing_table.router_name)
self.routing_table.update()
self.send_lsp()
# Send ack to sender
self.buffer.add_send([Type.LSACK, sender, seq_nb, addr])
# Forward to neighboors (LSP Packet)
self.buffer.add_send(tokens)
def add_edges(self, tokens):
sender = tokens[1]
changed = False
i = 3
active_links= []
while i < (len(tokens) - 1):
active_links += [tokens[i]]
#The edge is already in the graph
if self.routing_table.graph.has_edge((sender, tokens[i])):
#The edge weight isn't the same as known in the graph
if not int(self.routing_table.graph.edge_weight((sender, tokens[i]))) == int(tokens[i+1]):
self.routing_table.graph.set_edge_weight((sender, tokens[i]), int(tokens[i+1]))
changed = True
else:
if not self.routing_table.graph.has_node(tokens[i]):
self.routing_table.graph.add_node(tokens[i])
self.routing_table.graph.add_edge((sender, tokens[i]), int(tokens[i+1]))
changed = True
i += 2
to_rm = []
for node in self.routing_table.graph.neighbors(tokens[1]):
if node not in active_links:
to_rm += [node]
if to_rm:
changed = True
for node in to_rm:
self.routing_table.graph.del_edge((tokens[1], node))
if not self.routing_table.graph.neighbors(node) and node in self.routing_table.seq:
self.routing_table.seq.pop(node)
return changed
def handle_ack(self, tokens, addr):
""" Handle received lsack"""
if len(tokens) < 3:
logging.error("LSACK packet error")
return
receiver = tokens[1]
sender = None
neighbours = self.routing_table.neighbours
# Find associated HOST'S IP
for key, value in neighbours.items():
if value[Field.HOST] == addr[0] :
sender = key
if sender is None:
logging.error("LSACK Sender not found "+addr[0]+":"+str(addr[1]))
return
# Browse the LSP not acked table for the LSACK sender
for lsp_seq, lspo in neighbours[sender][Field.LSPLIST].items():
if int(tokens[2]) == int(lsp_seq):
# LSP found, remove it from the map
del(neighbours[sender][Field.LSPLIST][lsp_seq])
logging.debug("LSACK received from "+sender+" seq # "+tokens[2])
return
logging.debug("Received old or unintended LSACK "+tokens[2])
def send_lsp(self):
""" Sends LSP to all neighbours"""
sender = self.routing_table.router_name
msg = 'LSP '+sender+' '+str(self.routing_table.seq_nb)+' '
neighbours_table = self.routing_table.neighbours
# Build LSP Packet
for key, value in neighbours_table.items():
if value[Field.ACTIVE]:
msg+=key+' '+value[2]+' '
self.routing_table.seq_nb = (self.routing_table.seq_nb+1)%100
self.buffer.add_send(msg.split(' '))