-
Notifications
You must be signed in to change notification settings - Fork 2
/
fattreeswitch.py
115 lines (100 loc) · 3.82 KB
/
fattreeswitch.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
from pox.core import core
import pox.openflow.libopenflow_01 as of
from pox.lib.util import dpid_to_str
from pox.lib.addresses import IPAddr
import pox.openflow.discovery
from random import randint
log = core.getLogger()
pox.openflow.discovery.launch()
class RegisterSwitch(object):
def __init__ (self):
core.openflow.addListeners(self)
core.openflow_discovery.addListenerByName("LinkEvent", self._handle_LinkEvent)
self.connections = set()
self.hostlist = dict()
def load_hostlist():
f = open("hostlist_fattree.csv", "r")
for line in f:
s = line.split(",")
self.hostlist[(s[0], int(s[1]))] = int(s[2])
f.close()
load_hostlist()
log.debug(self.hostlist)
def installFlows(self):
# delete all flows
msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)
for conn in self.connections:
conn.send(msg)
# for all host, ensure that every switch can forward packet to the host
for host in self.hostlist:
# install flow on the switch that is connected to the host
self.setFlow(host[0], self.hostlist[host], host[1])
# get a list of all switches, flag is set to 0=not visited
# start at the switch that is connected to the host, set it to 1=last visited
# search all neighbours of the last visited nodes
# pick a random path, install flow on the neighbour nodes
# last visited nodes are set to 2=finished
# neighbour nodes are set to 1=last visited
# continue
switches = self.getSwitchList()
switches[host[1]] = 1
is_finished = False
while not is_finished:
# search neighbours of last visited nodes
newlinks = dict()
for s in switches:
if switches[s] == 0:
for l in core.openflow_discovery.adjacency:
if l.dpid1 == s and switches[l.dpid2] == 1:
if not s in newlinks:
newlinks[s] = []
newlinks[s].append(l)
# set all last visited nodes to finished
for s in switches:
if switches[s] == 1:
switches[s] = 2
# check if there is a new neighbour
if len(newlinks) == 0:
is_finished = True
# establish flows, set switches to last visited
for n in newlinks:
# pick one link randomly (load-balancing)
log.debug("Number of links: "+str(len(newlinks[n])))
r = randint(0, len(newlinks[n])-1)
self.setFlow(host[0], newlinks[n][r].port1, n)
switches[n] = 1
log.debug("Flows installed")
def setFlow(self, ip, outport, dpid):
msg = of.ofp_flow_mod(action=of.ofp_action_output(port=outport),match=of.ofp_match(dl_type=0x800,nw_dst=ip))
self.getConnection(dpid).send(msg)
log.debug("Install flow: "+ip+" on switch"+str(dpid)+" on port "+str(outport))
def getSwitchList(self):
switches = dict()
for conn in self.connections:
switches[conn.dpid] = 0
return switches
def getConnection(self, dpid):
for conn in self.connections:
if dpid == conn.dpid:
return conn
log.debug("Connection with dpid "+str(dpid)+" not found!")
raise Exception("No connection with dpid "+str(dpid))
def _handle_ConnectionUp (self, event):
self.connections.add(event.connection)
#self.installFlows()
log.debug("Switch %s has come up.", dpid_to_str(event.dpid))
def _handle_PacketIn (self, event):
msg = of.ofp_packet_out(data = event.ofp)
#msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
event.connection.send(msg)
log.debug(event)
def _handle_LinkEvent (self, event):
self.installFlows()
log.debug("Handle LinkEvent")
def launch (disable_flood = False):
core.registerNew(RegisterSwitch)
log.debug("Switch started.")
msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)
for connection in core.openflow.connections: # _connections.values() before betta
connection.send(msg)
log.debug("Clearing all flows from %s." % (dpidToStr(connection.dpid),))