blob: 2b1d1da1ad85ad7f97eab6efe0ab7ac1acef22a3 [file] [log] [blame]
alshabibf1216ed2014-09-03 11:53:54 -07001package org.onlab.onos.of.controller.impl;
alshabib54ebd9c2014-08-27 18:38:41 -07002
alshabib54ebd9c2014-08-27 18:38:41 -07003import org.apache.felix.scr.annotations.Activate;
tom69012372014-09-08 01:58:45 -07004import org.apache.felix.scr.annotations.Component;
alshabib54ebd9c2014-08-27 18:38:41 -07005import org.apache.felix.scr.annotations.Deactivate;
tom69012372014-09-08 01:58:45 -07006import org.apache.felix.scr.annotations.Service;
alshabib54ebd9c2014-08-27 18:38:41 -07007import org.onlab.onos.of.controller.Dpid;
8import org.onlab.onos.of.controller.OpenFlowController;
9import org.onlab.onos.of.controller.OpenFlowSwitch;
10import org.onlab.onos.of.controller.OpenFlowSwitchListener;
11import org.onlab.onos.of.controller.PacketListener;
12import org.onlab.onos.of.controller.RoleState;
alshabib6171f182014-09-02 19:00:32 -070013import org.onlab.onos.of.controller.driver.OpenFlowAgent;
alshabib54ebd9c2014-08-27 18:38:41 -070014import org.projectfloodlight.openflow.protocol.OFMessage;
alshabibc4901cd2014-09-05 16:50:40 -070015import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib54ebd9c2014-08-27 18:38:41 -070016import org.slf4j.Logger;
17import org.slf4j.LoggerFactory;
18
tomff7eb7c2014-09-08 12:49:03 -070019import java.util.ArrayList;
20import java.util.HashSet;
21import java.util.List;
22import java.util.Set;
23import java.util.concurrent.ConcurrentHashMap;
24import java.util.concurrent.locks.Lock;
25import java.util.concurrent.locks.ReentrantLock;
26
tom69012372014-09-08 01:58:45 -070027@Component(immediate = true)
28@Service
alshabib54ebd9c2014-08-27 18:38:41 -070029public class OpenFlowControllerImpl implements OpenFlowController {
30
alshabibd777b202014-08-28 17:52:55 -070031 private static final Logger log =
32 LoggerFactory.getLogger(OpenFlowControllerImpl.class);
33
alshabib6171f182014-09-02 19:00:32 -070034 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
35 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
36 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
37 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
38 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
39 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
alshabib54ebd9c2014-08-27 18:38:41 -070040
41 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
tomff7eb7c2014-09-08 12:49:03 -070042 protected Set<OpenFlowSwitchListener> ofEventListener =
43 new HashSet<>();
alshabib54ebd9c2014-08-27 18:38:41 -070044
tomff7eb7c2014-09-08 12:49:03 -070045 protected List<PacketListener> ofPacketListener =
46 new ArrayList<>();
alshabibc4901cd2014-09-05 16:50:40 -070047
alshabib54ebd9c2014-08-27 18:38:41 -070048 private final Controller ctrl = new Controller();
49
50 @Activate
51 public void activate() {
52 ctrl.start(agent);
53 }
54
55 @Deactivate
56 public void deactivate() {
57 ctrl.stop();
58 }
59
60 @Override
61 public Iterable<OpenFlowSwitch> getSwitches() {
62 return connectedSwitches.values();
63 }
64
65 @Override
66 public Iterable<OpenFlowSwitch> getMasterSwitches() {
67 return activeMasterSwitches.values();
68 }
69
70 @Override
71 public Iterable<OpenFlowSwitch> getEqualSwitches() {
72 return activeEqualSwitches.values();
73 }
74
75 @Override
76 public OpenFlowSwitch getSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070077 return connectedSwitches.get(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -070078 }
79
80 @Override
81 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070082 return activeMasterSwitches.get(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -070083 }
84
85 @Override
86 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070087 return activeEqualSwitches.get(dpid);
88 }
alshabib54ebd9c2014-08-27 18:38:41 -070089
90 @Override
91 public void addListener(OpenFlowSwitchListener listener) {
92 if (!ofEventListener.contains(listener)) {
93 this.ofEventListener.add(listener);
94 }
95 }
96
97 @Override
98 public void removeListener(OpenFlowSwitchListener listener) {
99 this.ofEventListener.remove(listener);
100 }
101
102 @Override
103 public void addPacketListener(int priority, PacketListener listener) {
alshabibc4901cd2014-09-05 16:50:40 -0700104 ofPacketListener.add(priority, listener);
alshabib54ebd9c2014-08-27 18:38:41 -0700105 }
106
107 @Override
108 public void removePacketListener(PacketListener listener) {
alshabibc4901cd2014-09-05 16:50:40 -0700109 ofPacketListener.remove(listener);
alshabib54ebd9c2014-08-27 18:38:41 -0700110 }
111
112 @Override
113 public void write(Dpid dpid, OFMessage msg) {
alshabibd777b202014-08-28 17:52:55 -0700114 this.getSwitch(dpid).sendMsg(msg);
alshabib54ebd9c2014-08-27 18:38:41 -0700115 }
116
117 @Override
alshabibc4901cd2014-09-05 16:50:40 -0700118 public void processPacket(Dpid dpid, OFMessage msg) {
119 switch (msg.getType()) {
tomff7eb7c2014-09-08 12:49:03 -0700120 case PORT_STATUS:
121 for (OpenFlowSwitchListener l : ofEventListener) {
122 l.portChanged(dpid, (OFPortStatus) msg);
123 }
124 break;
125 case PACKET_IN:
126 for (PacketListener p : ofPacketListener) {
127 //TODO fix me!
128 p.handlePacket(null);
129 }
130 break;
131 default:
132 log.warn("Handling message type {} not yet implemented", msg.getType());
alshabibc4901cd2014-09-05 16:50:40 -0700133 }
alshabib54ebd9c2014-08-27 18:38:41 -0700134 }
135
136 @Override
137 public void setRole(Dpid dpid, RoleState role) {
alshabibf1216ed2014-09-03 11:53:54 -0700138 getSwitch(dpid).setRole(role);
alshabib54ebd9c2014-08-27 18:38:41 -0700139 }
140
alshabibf1216ed2014-09-03 11:53:54 -0700141 /**
142 * Implementation of an OpenFlow Agent which is responsible for
143 * keeping track of connected switches and the state in which
144 * they are.
alshabibf1216ed2014-09-03 11:53:54 -0700145 */
alshabib6171f182014-09-02 19:00:32 -0700146 public class OpenFlowSwitchAgent implements OpenFlowAgent {
alshabib54ebd9c2014-08-27 18:38:41 -0700147
148 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
alshabib6171f182014-09-02 19:00:32 -0700149 private final Lock switchLock = new ReentrantLock();
alshabib54ebd9c2014-08-27 18:38:41 -0700150
alshabib6171f182014-09-02 19:00:32 -0700151 @Override
152 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700153 if (connectedSwitches.get(dpid) != null) {
154 log.error("Trying to add connectedSwitch but found a previous "
tomff7eb7c2014-09-08 12:49:03 -0700155 + "value for dpid: {}", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700156 return false;
157 } else {
158 log.error("Added switch {}", dpid);
159 connectedSwitches.put(dpid, sw);
160 for (OpenFlowSwitchListener l : ofEventListener) {
alshabib6171f182014-09-02 19:00:32 -0700161 l.switchAdded(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700162 }
163 return true;
164 }
165 }
166
alshabib6171f182014-09-02 19:00:32 -0700167 @Override
168 public boolean validActivation(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700169 if (connectedSwitches.get(dpid) == null) {
170 log.error("Trying to activate switch but is not in "
tomff7eb7c2014-09-08 12:49:03 -0700171 + "connected switches: dpid {}. Aborting ..",
172 dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700173 return false;
174 }
175 if (activeMasterSwitches.get(dpid) != null ||
176 activeEqualSwitches.get(dpid) != null) {
177 log.error("Trying to activate switch but it is already "
tomff7eb7c2014-09-08 12:49:03 -0700178 + "activated: dpid {}. Found in activeMaster: {} "
179 + "Found in activeEqual: {}. Aborting ..", new Object[]{
180 dpid,
181 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
182 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
alshabib54ebd9c2014-08-27 18:38:41 -0700183 return false;
184 }
185 return true;
186 }
187
alshabib6171f182014-09-02 19:00:32 -0700188
189 @Override
190 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700191 switchLock.lock();
192 try {
193 if (!validActivation(dpid)) {
194 return false;
195 }
196 activeMasterSwitches.put(dpid, sw);
197 return true;
198 } finally {
199 switchLock.unlock();
200 }
alshabib6171f182014-09-02 19:00:32 -0700201 }
alshabib54ebd9c2014-08-27 18:38:41 -0700202
alshabib6171f182014-09-02 19:00:32 -0700203 @Override
204 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700205 switchLock.lock();
206 try {
alshabib6171f182014-09-02 19:00:32 -0700207 if (!validActivation(dpid)) {
208 return false;
209 }
210 activeEqualSwitches.put(dpid, sw);
211 log.info("Added Activated EQUAL Switch {}", dpid);
212 return true;
alshabib54ebd9c2014-08-27 18:38:41 -0700213 } finally {
214 switchLock.unlock();
215 }
216 }
217
alshabib6171f182014-09-02 19:00:32 -0700218 @Override
219 public void transitionToMasterSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700220 switchLock.lock();
221 try {
alshabibd777b202014-08-28 17:52:55 -0700222 if (activeMasterSwitches.containsKey(dpid)) {
223 return;
224 }
alshabib54ebd9c2014-08-27 18:38:41 -0700225 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
226 if (sw == null) {
227 log.error("Transition to master called on sw {}, but switch "
tomff7eb7c2014-09-08 12:49:03 -0700228 + "was not found in controller-cache", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700229 return;
230 }
alshabibf1216ed2014-09-03 11:53:54 -0700231 log.info("Transitioned switch {} to MASTER", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700232 activeMasterSwitches.put(dpid, sw);
233 } finally {
234 switchLock.unlock();
235 }
236 }
237
238
alshabib6171f182014-09-02 19:00:32 -0700239 @Override
240 public void transitionToEqualSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700241 switchLock.lock();
242 try {
alshabibd777b202014-08-28 17:52:55 -0700243 if (activeEqualSwitches.containsKey(dpid)) {
244 return;
245 }
alshabib54ebd9c2014-08-27 18:38:41 -0700246 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
247 if (sw == null) {
248 log.error("Transition to equal called on sw {}, but switch "
tomff7eb7c2014-09-08 12:49:03 -0700249 + "was not found in controller-cache", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700250 return;
251 }
alshabibf1216ed2014-09-03 11:53:54 -0700252 log.info("Transitioned switch {} to EQUAL", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700253 activeEqualSwitches.put(dpid, sw);
254 } finally {
255 switchLock.unlock();
256 }
257
258 }
259
alshabib6171f182014-09-02 19:00:32 -0700260 @Override
261 public void removeConnectedSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700262 connectedSwitches.remove(dpid);
263 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
264 if (sw == null) {
265 sw = activeEqualSwitches.remove(dpid);
266 }
267 for (OpenFlowSwitchListener l : ofEventListener) {
alshabib6171f182014-09-02 19:00:32 -0700268 l.switchRemoved(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700269 }
270 }
271
alshabib6171f182014-09-02 19:00:32 -0700272 @Override
alshabibc4901cd2014-09-05 16:50:40 -0700273 public void processMessage(Dpid dpid, OFMessage m) {
274 processPacket(dpid, m);
alshabib54ebd9c2014-08-27 18:38:41 -0700275 }
276 }
277
278
alshabib54ebd9c2014-08-27 18:38:41 -0700279}