blob: a58d79661fae3e0c2194202a44ddb60be9951103 [file] [log] [blame]
alshabibf1216ed2014-09-03 11:53:54 -07001package org.onlab.onos.of.controller.impl;
alshabib54ebd9c2014-08-27 18:38:41 -07002
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;
tom69012372014-09-08 01:58:45 -07009import org.apache.felix.scr.annotations.Component;
alshabib54ebd9c2014-08-27 18:38:41 -070010import org.apache.felix.scr.annotations.Deactivate;
tom69012372014-09-08 01:58:45 -070011import org.apache.felix.scr.annotations.Service;
alshabib54ebd9c2014-08-27 18:38:41 -070012import 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;
alshabib6171f182014-09-02 19:00:32 -070018import org.onlab.onos.of.controller.driver.OpenFlowAgent;
alshabib54ebd9c2014-08-27 18:38:41 -070019import org.projectfloodlight.openflow.protocol.OFMessage;
alshabibc4901cd2014-09-05 16:50:40 -070020import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib54ebd9c2014-08-27 18:38:41 -070021import org.slf4j.Logger;
22import org.slf4j.LoggerFactory;
23
tom69012372014-09-08 01:58:45 -070024@Component(immediate = true)
25@Service
alshabib54ebd9c2014-08-27 18:38:41 -070026public class OpenFlowControllerImpl implements OpenFlowController {
27
alshabibd777b202014-08-28 17:52:55 -070028 private static final Logger log =
29 LoggerFactory.getLogger(OpenFlowControllerImpl.class);
30
alshabib6171f182014-09-02 19:00:32 -070031 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
32 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
33 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
34 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
35 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
36 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
alshabib54ebd9c2014-08-27 18:38:41 -070037
38 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
alshabibd777b202014-08-28 17:52:55 -070039 protected ArrayList<OpenFlowSwitchListener> ofEventListener =
40 new ArrayList<OpenFlowSwitchListener>();
alshabib54ebd9c2014-08-27 18:38:41 -070041
alshabibc4901cd2014-09-05 16:50:40 -070042 protected ArrayList<PacketListener> ofPacketListener =
43 new ArrayList<PacketListener>();
44
alshabib54ebd9c2014-08-27 18:38:41 -070045 private final Controller ctrl = new Controller();
46
47 @Activate
48 public void activate() {
49 ctrl.start(agent);
50 }
51
52 @Deactivate
53 public void deactivate() {
54 ctrl.stop();
55 }
56
57 @Override
58 public Iterable<OpenFlowSwitch> getSwitches() {
59 return connectedSwitches.values();
60 }
61
62 @Override
63 public Iterable<OpenFlowSwitch> getMasterSwitches() {
64 return activeMasterSwitches.values();
65 }
66
67 @Override
68 public Iterable<OpenFlowSwitch> getEqualSwitches() {
69 return activeEqualSwitches.values();
70 }
71
72 @Override
73 public OpenFlowSwitch getSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070074 return connectedSwitches.get(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -070075 }
76
77 @Override
78 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070079 return activeMasterSwitches.get(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -070080 }
81
82 @Override
83 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070084 return activeEqualSwitches.get(dpid);
85 }
alshabib54ebd9c2014-08-27 18:38:41 -070086
87 @Override
88 public void addListener(OpenFlowSwitchListener listener) {
89 if (!ofEventListener.contains(listener)) {
90 this.ofEventListener.add(listener);
91 }
92 }
93
94 @Override
95 public void removeListener(OpenFlowSwitchListener listener) {
96 this.ofEventListener.remove(listener);
97 }
98
99 @Override
100 public void addPacketListener(int priority, PacketListener listener) {
alshabibc4901cd2014-09-05 16:50:40 -0700101 ofPacketListener.add(priority, listener);
alshabib54ebd9c2014-08-27 18:38:41 -0700102 }
103
104 @Override
105 public void removePacketListener(PacketListener listener) {
alshabibc4901cd2014-09-05 16:50:40 -0700106 ofPacketListener.remove(listener);
alshabib54ebd9c2014-08-27 18:38:41 -0700107 }
108
109 @Override
110 public void write(Dpid dpid, OFMessage msg) {
alshabibd777b202014-08-28 17:52:55 -0700111 this.getSwitch(dpid).sendMsg(msg);
alshabib54ebd9c2014-08-27 18:38:41 -0700112 }
113
114 @Override
alshabibc4901cd2014-09-05 16:50:40 -0700115 public void processPacket(Dpid dpid, OFMessage msg) {
116 switch (msg.getType()) {
117 case PORT_STATUS:
118 for (OpenFlowSwitchListener l : ofEventListener) {
119 l.portChanged(dpid, (OFPortStatus) msg);
120 }
121 break;
122 case PACKET_IN:
123 for (PacketListener p : ofPacketListener) {
124 //TODO fix me!
125 p.handlePacket(null);
126 }
127 break;
128 default:
129 log.warn("Handling message type {} not yet implemented", msg.getType());
130 }
alshabib54ebd9c2014-08-27 18:38:41 -0700131 }
132
133 @Override
134 public void setRole(Dpid dpid, RoleState role) {
alshabibf1216ed2014-09-03 11:53:54 -0700135 getSwitch(dpid).setRole(role);
alshabib54ebd9c2014-08-27 18:38:41 -0700136 }
137
alshabibf1216ed2014-09-03 11:53:54 -0700138 /**
139 * Implementation of an OpenFlow Agent which is responsible for
140 * keeping track of connected switches and the state in which
141 * they are.
142 *
143 */
alshabib6171f182014-09-02 19:00:32 -0700144 public class OpenFlowSwitchAgent implements OpenFlowAgent {
alshabib54ebd9c2014-08-27 18:38:41 -0700145
146 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
alshabib6171f182014-09-02 19:00:32 -0700147 private final Lock switchLock = new ReentrantLock();
alshabib54ebd9c2014-08-27 18:38:41 -0700148
alshabib6171f182014-09-02 19:00:32 -0700149 @Override
150 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700151 if (connectedSwitches.get(dpid) != null) {
152 log.error("Trying to add connectedSwitch but found a previous "
153 + "value for dpid: {}", dpid);
154 return false;
155 } else {
156 log.error("Added switch {}", dpid);
157 connectedSwitches.put(dpid, sw);
158 for (OpenFlowSwitchListener l : ofEventListener) {
alshabib6171f182014-09-02 19:00:32 -0700159 l.switchAdded(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700160 }
161 return true;
162 }
163 }
164
alshabib6171f182014-09-02 19:00:32 -0700165 @Override
166 public boolean validActivation(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700167 if (connectedSwitches.get(dpid) == null) {
168 log.error("Trying to activate switch but is not in "
169 + "connected switches: dpid {}. Aborting ..",
alshabib6171f182014-09-02 19:00:32 -0700170 dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700171 return false;
172 }
173 if (activeMasterSwitches.get(dpid) != null ||
174 activeEqualSwitches.get(dpid) != null) {
175 log.error("Trying to activate switch but it is already "
176 + "activated: dpid {}. Found in activeMaster: {} "
177 + "Found in activeEqual: {}. Aborting ..", new Object[] {
alshabib6171f182014-09-02 19:00:32 -0700178 dpid,
alshabib54ebd9c2014-08-27 18:38:41 -0700179 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
alshabib6171f182014-09-02 19:00:32 -0700180 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
alshabib54ebd9c2014-08-27 18:38:41 -0700181 return false;
182 }
183 return true;
184 }
185
alshabib6171f182014-09-02 19:00:32 -0700186
187 @Override
188 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700189 switchLock.lock();
190 try {
191 if (!validActivation(dpid)) {
192 return false;
193 }
194 activeMasterSwitches.put(dpid, sw);
195 return true;
196 } finally {
197 switchLock.unlock();
198 }
alshabib6171f182014-09-02 19:00:32 -0700199 }
alshabib54ebd9c2014-08-27 18:38:41 -0700200
alshabib6171f182014-09-02 19:00:32 -0700201 @Override
202 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700203 switchLock.lock();
204 try {
alshabib6171f182014-09-02 19:00:32 -0700205 if (!validActivation(dpid)) {
206 return false;
207 }
208 activeEqualSwitches.put(dpid, sw);
209 log.info("Added Activated EQUAL Switch {}", dpid);
210 return true;
alshabib54ebd9c2014-08-27 18:38:41 -0700211 } finally {
212 switchLock.unlock();
213 }
214 }
215
alshabib6171f182014-09-02 19:00:32 -0700216 @Override
217 public void transitionToMasterSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700218 switchLock.lock();
219 try {
alshabibd777b202014-08-28 17:52:55 -0700220 if (activeMasterSwitches.containsKey(dpid)) {
221 return;
222 }
alshabib54ebd9c2014-08-27 18:38:41 -0700223 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
224 if (sw == null) {
225 log.error("Transition to master called on sw {}, but switch "
226 + "was not found in controller-cache", dpid);
227 return;
228 }
alshabibf1216ed2014-09-03 11:53:54 -0700229 log.info("Transitioned switch {} to MASTER", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700230 activeMasterSwitches.put(dpid, sw);
231 } finally {
232 switchLock.unlock();
233 }
234 }
235
236
alshabib6171f182014-09-02 19:00:32 -0700237 @Override
238 public void transitionToEqualSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700239 switchLock.lock();
240 try {
alshabibd777b202014-08-28 17:52:55 -0700241 if (activeEqualSwitches.containsKey(dpid)) {
242 return;
243 }
alshabib54ebd9c2014-08-27 18:38:41 -0700244 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
245 if (sw == null) {
246 log.error("Transition to equal called on sw {}, but switch "
247 + "was not found in controller-cache", dpid);
248 return;
249 }
alshabibf1216ed2014-09-03 11:53:54 -0700250 log.info("Transitioned switch {} to EQUAL", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700251 activeEqualSwitches.put(dpid, sw);
252 } finally {
253 switchLock.unlock();
254 }
255
256 }
257
alshabib6171f182014-09-02 19:00:32 -0700258 @Override
259 public void removeConnectedSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700260 connectedSwitches.remove(dpid);
261 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
262 if (sw == null) {
263 sw = activeEqualSwitches.remove(dpid);
264 }
265 for (OpenFlowSwitchListener l : ofEventListener) {
alshabib6171f182014-09-02 19:00:32 -0700266 l.switchRemoved(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700267 }
268 }
269
alshabib6171f182014-09-02 19:00:32 -0700270 @Override
alshabibc4901cd2014-09-05 16:50:40 -0700271 public void processMessage(Dpid dpid, OFMessage m) {
272 processPacket(dpid, m);
alshabib54ebd9c2014-08-27 18:38:41 -0700273 }
274 }
275
276
277
278}