Untitled
unknown
plain_text
2 years ago
6.8 kB
9
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':1, '2':2, '3':3,'4':1}
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 dijkstra(graph,src,dest,visited=[],distances={},predecessors={}):
# a few sanity checks
if src not in graph:
raise TypeError('the root of the shortest path tree cannot be found in the graph')
if dest not in graph:
raise TypeError('the target of the shortest path cannot be found in the graph')
# ending condition
if src == dest:
# We build the shortest path and display it
pred=dest
while pred != None:
self.path.append(pred)
pred=predecessors.get(pred,None)
else :
# if it is the initial run, initializes the cost
if not visited:
distances[src]=0
# visit the neighbors
for neighbor in graph[src] :
if neighbor not in visited:
new_distance = distances[src] + 1
if new_distance < distances.get(neighbor,float('inf')):
distances[neighbor] = new_distance
predecessors[neighbor] = src
# mark as visited
visited.append(src)
# now that all neighbors have been visited: recurse
# select the non visited node with lowest distance 'x'
# run Dijskstra with src='x'
unvisited={}
for k in graph:
if k not in visited:
unvisited[k] = distances.get(k,float('inf'))
x=min(unvisited, key=unvisited.get)
dijkstra(graph,x,dest,visited,distances,predecessors)
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=[]
dijkstra(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