blob: 976e3478f994d3522abfa5cc72702b1c33b52414 [file] [log] [blame]
alshabib54ebd9c2014-08-27 18:38:41 -07001package org.onlab.onos.of.controller.impl.internal;
2
3import java.util.ArrayList;
4import java.util.concurrent.ConcurrentHashMap;
5import java.util.concurrent.locks.Lock;
6import java.util.concurrent.locks.ReentrantLock;
7
8import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Component;
10import org.apache.felix.scr.annotations.Deactivate;
11import org.apache.felix.scr.annotations.Service;
12import org.onlab.onos.of.controller.Dpid;
13import org.onlab.onos.of.controller.OpenFlowController;
14import org.onlab.onos.of.controller.OpenFlowSwitch;
15import org.onlab.onos.of.controller.OpenFlowSwitchListener;
16import org.onlab.onos.of.controller.PacketListener;
17import org.onlab.onos.of.controller.RoleState;
18import org.projectfloodlight.openflow.protocol.OFMessage;
19import org.projectfloodlight.openflow.util.HexString;
20import org.slf4j.Logger;
21import org.slf4j.LoggerFactory;
22
23@Component(immediate = true)
24@Service
25public class OpenFlowControllerImpl implements OpenFlowController {
26
27 protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches;
28 protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches;
29 protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches;
30
31 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
32 protected ArrayList<OpenFlowSwitchListener> ofEventListener;
33
34 private final Controller ctrl = new Controller();
35
36 @Activate
37 public void activate() {
38 ctrl.start(agent);
39 }
40
41 @Deactivate
42 public void deactivate() {
43 ctrl.stop();
44 }
45
46 @Override
47 public Iterable<OpenFlowSwitch> getSwitches() {
48 return connectedSwitches.values();
49 }
50
51 @Override
52 public Iterable<OpenFlowSwitch> getMasterSwitches() {
53 return activeMasterSwitches.values();
54 }
55
56 @Override
57 public Iterable<OpenFlowSwitch> getEqualSwitches() {
58 return activeEqualSwitches.values();
59 }
60
61 @Override
62 public OpenFlowSwitch getSwitch(Dpid dpid) {
63 return connectedSwitches.get(dpid.value());
64 }
65
66 @Override
67 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
68 return activeMasterSwitches.get(dpid.value());
69 }
70
71 @Override
72 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
73 return activeEqualSwitches.get(dpid.value()); }
74
75 @Override
76 public void addListener(OpenFlowSwitchListener listener) {
77 if (!ofEventListener.contains(listener)) {
78 this.ofEventListener.add(listener);
79 }
80 }
81
82 @Override
83 public void removeListener(OpenFlowSwitchListener listener) {
84 this.ofEventListener.remove(listener);
85 }
86
87 @Override
88 public void addPacketListener(int priority, PacketListener listener) {
89 // TODO Auto-generated method stub
90
91 }
92
93 @Override
94 public void removePacketListener(PacketListener listener) {
95 // TODO Auto-generated method stub
96
97 }
98
99 @Override
100 public void write(Dpid dpid, OFMessage msg) {
101 this.getSwitch(dpid).write(msg);
102 }
103
104 @Override
105 public void processPacket(OFMessage msg) {
106 }
107
108 @Override
109 public void setRole(Dpid dpid, RoleState role) {
110 switch (role) {
111 case MASTER:
112 agent.transitionToMasterSwitch(dpid.value());
113 break;
114 case EQUAL:
115 agent.transitionToEqualSwitch(dpid.value());
116 break;
117 case SLAVE:
118 //agent.transitionToSlaveSwitch(dpid.value());
119 break;
120 default:
121 //WTF role is this?
122 }
123
124 }
125
126 public class OpenFlowSwitchAgent {
127
128 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
129 private Lock switchLock = new ReentrantLock();
130
131 public boolean addConnectedSwitch(long dpid, AbstractOpenFlowSwitch sw) {
132 if (connectedSwitches.get(dpid) != null) {
133 log.error("Trying to add connectedSwitch but found a previous "
134 + "value for dpid: {}", dpid);
135 return false;
136 } else {
137 log.error("Added switch {}", dpid);
138 connectedSwitches.put(dpid, sw);
139 for (OpenFlowSwitchListener l : ofEventListener) {
140 l.switchAdded(new Dpid(dpid));
141 }
142 return true;
143 }
144 }
145
146 private boolean validActivation(long dpid) {
147 if (connectedSwitches.get(dpid) == null) {
148 log.error("Trying to activate switch but is not in "
149 + "connected switches: dpid {}. Aborting ..",
150 HexString.toHexString(dpid));
151 return false;
152 }
153 if (activeMasterSwitches.get(dpid) != null ||
154 activeEqualSwitches.get(dpid) != null) {
155 log.error("Trying to activate switch but it is already "
156 + "activated: dpid {}. Found in activeMaster: {} "
157 + "Found in activeEqual: {}. Aborting ..", new Object[] {
158 HexString.toHexString(dpid),
159 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
160 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
161 return false;
162 }
163 return true;
164 }
165
166 /**
167 * Called when a switch is activated, with this controller's role as MASTER.
168 */
169 protected boolean addActivatedMasterSwitch(long dpid, AbstractOpenFlowSwitch sw) {
170 switchLock.lock();
171 try {
172 if (!validActivation(dpid)) {
173 return false;
174 }
175 activeMasterSwitches.put(dpid, sw);
176 return true;
177 } finally {
178 switchLock.unlock();
179 }
180 }
181
182 /**
183 * Called when a switch is activated, with this controller's role as EQUAL.
184 */
185 protected boolean addActivatedEqualSwitch(long dpid, AbstractOpenFlowSwitch sw) {
186 switchLock.lock();
187 try {
188 if (!validActivation(dpid)) {
189 return false;
190 }
191 activeEqualSwitches.put(dpid, sw);
192 return true;
193 } finally {
194 switchLock.unlock();
195 }
196 }
197
198 /**
199 * Called when this controller's role for a switch transitions from equal
200 * to master. For 1.0 switches, we internally refer to the role 'slave' as
201 * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
202 */
203 protected void transitionToMasterSwitch(long dpid) {
204 switchLock.lock();
205 try {
206 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
207 if (sw == null) {
208 log.error("Transition to master called on sw {}, but switch "
209 + "was not found in controller-cache", dpid);
210 return;
211 }
212 activeMasterSwitches.put(dpid, sw);
213 } finally {
214 switchLock.unlock();
215 }
216 }
217
218
219 /**
220 * Called when this controller's role for a switch transitions to equal.
221 * For 1.0 switches, we internally refer to the role 'slave' as
222 * 'equal'.
223 */
224 protected void transitionToEqualSwitch(long dpid) {
225 switchLock.lock();
226 try {
227 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
228 if (sw == null) {
229 log.error("Transition to equal called on sw {}, but switch "
230 + "was not found in controller-cache", dpid);
231 return;
232 }
233 activeEqualSwitches.put(dpid, sw);
234 } finally {
235 switchLock.unlock();
236 }
237
238 }
239
240 /**
241 * Clear all state in controller switch maps for a switch that has
242 * disconnected from the local controller. Also release control for
243 * that switch from the global repository. Notify switch listeners.
244 */
245 public void removeConnectedSwitch(long dpid) {
246 connectedSwitches.remove(dpid);
247 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
248 if (sw == null) {
249 sw = activeEqualSwitches.remove(dpid);
250 }
251 for (OpenFlowSwitchListener l : ofEventListener) {
252 l.switchRemoved(new Dpid(dpid));
253 }
254 }
255
256 public void processMessage(OFMessage m) {
257 processPacket(m);
258 }
259 }
260
261
262
263}