l3_routing_bellman.py
unknown
python
2 years ago
6.3 kB
4
Indexable
from pox.core import core import pox.openflow.libopenflow_01 as of from pox.lib.util import dpid_to_str from pox.lib.util import str_to_dpid from pox.lib.util import str_to_bool from pox.lib.packet.arp import arp from pox.lib.packet.ipv4 import ipv4 from pox.openflow.discovery import Discovery import pox.lib.packet as pkt import time log = core.getLogger() # We don't want to flood immediately when a switch connects. # Can be overriden on commandline. _flood_delay = 0 class L3Routing (object): def __init__ (self, connection, transparent): self.connection = connection self.transparent = transparent self.graph={} self.listSWitch=[] self.listHost=[] self.host={'1':2, '2':1, '3':1,'4':2} self.path=[] self.macToPort = {} # We want to hear PacketIn messages, so we listen # to the connection connection.addListeners(self) # We just use this to know when to log a helpful message self.hold_down_expired = _flood_delay == 0 def _handle_PacketIn (self, event): """ Handle packet in messages from the switch to implement above algorithm. """ packet = event.parsed def bellman_ford(graph, source, dst): # Step 1: Prepare the distance and predecessor for each node distance, predecessor = dict(), dict() for node in graph: distance[node], predecessor[node] = float('inf'), None distance[source] = 0 # Step 2: Relax the edges for _ in range(len(graph) - 1): for node in graph: for neighbour in graph[node]: # If the distance between the node and the neighbour is lower than the current, store it if distance[neighbour] > distance[node] + 1: distance[neighbour], predecessor[neighbour] = distance[node] + 1, node # Step 3: Check for negative weight cycles for node in graph: for neighbour in graph[node]: assert distance[neighbour] <= distance[node] + graph[node][neighbour], "Negative weight cycle." print predecessor check =True while check: for node in predecessor: if node == dst: if dst == source: self.path.append(dst) check=False break else: self.path.append(node) dst= predecessor[node] def flood (message = None): """ Floods the packet """ msg = of.ofp_packet_out() if time.time() - self.connection.connect_time >= _flood_delay: # Only flood if we've been connected for a little while... if self.hold_down_expired is False: # Oh yes it is! self.hold_down_expired = True log.info("%s: Flood hold-down expired -- flooding", dpid_to_str(event.dpid)) if message is not None: log.debug(message) #log.debug("%i: flood %s -> %s", event.dpid,packet.src,packet.dst) # OFPP_FLOOD is optional; on some switches you may need to change # this to OFPP_ALL. msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) else: pass #log.info("Holding down flood for %s", dpid_to_str(event.dpid)) msg.data = event.ofp msg.in_port = event.port self.connection.send(msg) if not self.transparent: if packet.type == packet.LLDP_TYPE or packet.dst.isBridgeFiltered(): drop() return if packet.dst.is_multicast: flood() else: for l in core.openflow_discovery.adjacency: sw_src = l.__str__().split("->")[0].split(".")[0].split("-")[5][1].strip() port_src= l.__str__().split("->")[0].split(".")[1].strip() sw_dst = l.__str__().split("->")[1].split(".")[0].split("-")[5][1].strip() port_dst=l.__str__().split("->")[1].split(".")[1].strip() log.debug("SW src: %s SW dst: %s Port src: %s Port dst: %s" %(sw_src, sw_dst, port_src, port_dst)) if sw_src in self.listSWitch: list = self.graph[sw_src] list[sw_dst]=int(port_src) self.graph[sw_src]=list else: tlist={} tlist[sw_dst]=int(port_src) self.graph[sw_src]= tlist self.listSWitch.append(sw_src) if isinstance (packet.next, arp): arp_packet = packet.find(pkt.arp) src_ip = arp_packet.protosrc.toStr().split(".")[3] dst_ip = arp_packet.protodst.toStr().split(".")[3] dpid = dpid_to_str(event.dpid).split("-")[5][1] if isinstance(packet.next, ipv4): ip_packet = packet.find(pkt.ipv4) if ip_packet is not None: src_ip = ip_packet.srcip.toStr().split(".")[3] dst_ip = ip_packet.dstip.toStr().split(".")[3] log.debug("IP src= %s IP dst= %s" %(src_ip, dst_ip)) self.path=[] bellman_ford(self.graph,dst_ip,src_ip) print self.path dpid = dpid_to_str(event.dpid).split("-")[5][1] for index in range(len(self.path)): if dpid is self.path[index]: if self.path[index] is self.path[-1]: msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(packet, event.port) msg.idle_timeout = 10 msg.hard_timeout = 30 msg.actions.append(of.ofp_action_output(port = self.host[dpid])) msg.data = event.ofp self.connection.send(msg) else: msg = of.ofp_flow_mod() msg.match = of.ofp_match.from_packet(packet, event.port) msg.idle_timeout = 10 msg.hard_timeout = 30 msg.actions.append(of.ofp_action_output(port = self.graph[self.path[index]][self.path[index+1]])) msg.data = event.ofp self.connection.send(msg) class l3_routing (object): def __init__ (self, transparent): core.openflow.addListeners(self) self.transparent = transparent def _handle_ConnectionUp (self, event): log.debug("Connection %s" % (event.connection,)) L3Routing(event.connection, self.transparent) def launch (transparent=False, hold_down=_flood_delay): """ Starts an L3 routing. """ try: global _flood_delay _flood_delay = int(str(hold_down), 10) assert _flood_delay >= 0 except: raise RuntimeError("Expected hold-down to be a number") core.registerNew(l3_routing, str_to_bool(transparent))
Editor is loading...
Leave a Comment