router.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. from packets import *
  2. import socket, sys, os
  3. # save values needed to talk to host emulator
  4. rid = int(sys.argv[1]) # RouterID
  5. haddr = sys.argv[2] # emulator host addr
  6. hport = int(sys.argv[3]) # emulator host port
  7. rport = int(sys.argv[4]) # router's port
  8. # random consts/globals
  9. inf = 65535
  10. # logfile; at end call log.close()
  11. logname = "router" + str(rid) + ".log"
  12. log = open(logname, "a")
  13. # create socket
  14. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  15. sock.bind(('', rport))
  16. # send init packet to the emulator
  17. init = ipacket(rid)
  18. sock.sendto(init.package(), (haddr, hport))
  19. log.write("sent init packet" + "\n")
  20. # receive circuitDB packet from emulator
  21. pack, addr = sock.recvfrom(4096)
  22. circuit = unpacket(pack)[1]
  23. log.write("received circuit packet" + "\n")
  24. # send shit out to emulator
  25. for i in circuit.getlink():
  26. sock.sendto(hpacket(rid, i.getlid()).package(), (haddr, hport))
  27. log.write("sent hello packet to link" + str(i.getlid()) + "\n")
  28. # CLASS AND FUNCTION DEFINITIONS
  29. # sends out our circuit as lspdus over link
  30. def send_links(link):
  31. for i in circuit.getlink():
  32. # make lspdu with link info, router as
  33. sock.sendto(lpacket(rid, rid, i.getlid(), i.getcost(), link).package(), (haddr, hport))
  34. log.write("sent lspdu packet: " + str(rid) + " " + str(rid) + " " + str(i.getlid()) + " " + str(i.getcost()) + " " + str(link) + "\n")
  35. # notify neighbours of this new lspdu entry
  36. def notify(connection):
  37. for i in neighbours:
  38. # if this is the sender, continue
  39. if (i[0] == connection.sender):
  40. continue
  41. else:
  42. # lookup shortest path to i (the neighbour)
  43. #dlink = graph.lookup(i[0])
  44. # send to neighbour using dlink
  45. sock.sendto(lpacket(rid, connection.src, connection.link, connection.cost, i[0]).package(), (haddr, hport))
  46. log.write("sent lspdu packet: " + str(rid) + " " + str(connection.src) + " " + str(connection.link) + " " + str(connection.cost) + " " + str(i[0]) + "\n")
  47. class connection:
  48. def __init__(this, sender, src, dest, link, cost):
  49. this.sender = sender
  50. this.src = src
  51. this.dest = dest
  52. this.link = link
  53. this.cost = cost
  54. def show(this):
  55. log.write("Link: " + str(this.sender) + " " + str(this.src) + " " + str(this.link) + " " + str(this.cost))
  56. # infers what this connection's (link's) destination is
  57. def infer(this, db):
  58. # search all known paths for one with this link
  59. for i in range(0, len(db.entries)):
  60. # don't search the list with this as the source, that's pointless
  61. if ((i + 1) == this.src):
  62. continue
  63. # check all entries for one w/ this link
  64. for j in db.entries[i]:
  65. # match! return
  66. if (j.link == this.link):
  67. this.dest = j.src
  68. j.dest = this.src
  69. return True
  70. return False
  71. class db:
  72. def __init__(this, routers):
  73. this.entries = [ [] for i in range(routers) ]
  74. def show(this):
  75. log.write("Topology DB: " + '\n')
  76. for i in this.entries:
  77. for j in i:
  78. j.show()
  79. def insert(this, connection):
  80. src = connection.src
  81. # check each entry in the source's list within entries
  82. # index is src - 1 since router #s start at 1
  83. for i in this.entries[src - 1]:
  84. # dupe entry
  85. if (connection.link == i.link):
  86. log.write("This was a duplicate packet. Ignoring.")
  87. return False
  88. # not a dupe, insert
  89. this.entries[src - 1].append(connection)
  90. this.show()
  91. # update entries and connection to contain
  92. got_dest = connection.infer(this)
  93. print("GOT_DEST + ", got_dest)
  94. # insert into graph if we have the endpoints for this edge
  95. if (got_dest):
  96. graph.insert(connection)
  97. print("DONE INSERT")
  98. graph.rebuild()
  99. print("DONE REBUILD")
  100. graph.show()
  101. # notify neighbours
  102. notify(connection)
  103. return True
  104. class graph:
  105. def __init__(this, routers):
  106. # stores shortest paths
  107. this.sssp = [(inf, 0)] * routers
  108. # stores adjacency list (Graph)
  109. this.alist = [ [-1, -1, -1, -1, -1] for i in range(routers) ]
  110. def lookup(this, dest):
  111. return this.sssp[dest - 1]
  112. def show(this):
  113. print("RIB: ")
  114. for i in range(0, 5):
  115. print("R" + str(rid) + " -> R"+ str(i + 1) + " = " + str(this.sssp[i][0]) + " using node " + str(this.sssp[i][1] + 1))
  116. def insert(this, connection):
  117. src = connection.src
  118. dest = connection.dest
  119. weight = connection.cost
  120. this.alist[src - 1][dest - 1] = weight
  121. this.alist[dest - 1][src - 1] = weight
  122. def rebuild(this):
  123. print("Before building")
  124. print(this.alist)
  125. #this.sssp = [(inf, rid - 1)] * 5
  126. # set the adjacent node for each node
  127. for i in range(0, 5):
  128. this.sssp[i - 1] = (this.sssp[i - 1][0], i)
  129. this.sssp[rid - 1] = (0, rid - 1)
  130. curnode = rid - 1
  131. unvisited = [1] * 5
  132. while(sum(unvisited)):
  133. # iterate on routers adjacent to curnode
  134. for i in range(0, 5):
  135. # don't check curnode
  136. if (i == curnode):
  137. continue
  138. # not an edge/neighbour
  139. if (this.alist[curnode][i] == -1):
  140. continue
  141. # visited already
  142. if (unvisited[i] == 0):
  143. continue
  144. result = min((this.sssp[curnode][0] + this.alist[curnode][i]), this.sssp[i][0])
  145. if (result != this.sssp[i][0]):
  146. this.sssp[i] = (result, this.sssp[curnode][1])
  147. else:
  148. this.sssp[i] = (result, this.sssp[i][1])
  149. unvisited[curnode] = 0
  150. # if we visited all, we're done
  151. if (sum(unvisited) == 0):
  152. break
  153. minsofar = inf
  154. mindexsofar = curnode
  155. # select next curnode
  156. for i in range(0, 5):
  157. # visited already
  158. if (unvisited[i] == 0):
  159. continue
  160. minsofar = min(minsofar, this.sssp[i][0])
  161. mindexsofar = i
  162. # no change, we are disconnected. breka
  163. if (mindexsofar == curnode):
  164. break
  165. curnode = mindexsofar
  166. # stores neighbours, topology db, and graph
  167. neighbours = []
  168. database = db(5) # change constant here to reflect network size
  169. graph = graph(5) # same as above
  170. # listen for network activity
  171. while (1):
  172. pack, addr = sock.recvfrom(4096)
  173. ptype, pack = unpacket(pack)
  174. # hello packet
  175. if (ptype == 1):
  176. log.write("received hello packet from: " + str(pack.rid) + " with link: " + str(pack.lid) + "\n")
  177. # save hello in hellodb
  178. neighbours.append((pack.rid, pack.lid))
  179. # reply with the links from circuit sent individually as lspdus
  180. send_links(pack.lid)
  181. continue
  182. # lspdu packet
  183. elif (ptype == 2):
  184. log.write("received lspdu packet: " + str(pack.sid) + " " + str(pack.rid) + " " + str(pack.lid) + " " + str(pack.cost) + " " + str(pack.slid) + "\n")
  185. # add router ID (link source), linkid, cost to db (only if not a dupe)
  186. conn = connection(pack.sid, pack.rid, None, pack.lid, pack.cost)
  187. database.insert(conn)
  188. # otherwise,send to all ppl that hello-d me (except who sent it) (but modify sid and slid)
  189. continue
  190. # undefined behaviour
  191. else:
  192. print("Recieved unexpected packet. Dropping.")
  193. continue
  194. print("Unexpected end of program.")