blob: 2a27ba9f16ea8184d550812370ba02a6b3e21be8 [file] [log] [blame]
alshabibf1216ed2014-09-03 11:53:54 -07001package org.onlab.onos.of.controller.impl;
alshabib54ebd9c2014-08-27 18:38:41 -07002
alshabibdf652ad2014-09-09 11:53:19 -07003import java.util.ArrayList;
4import java.util.HashSet;
5import java.util.List;
6import java.util.Set;
7import java.util.concurrent.ConcurrentHashMap;
8import java.util.concurrent.locks.Lock;
9import java.util.concurrent.locks.ReentrantLock;
10
alshabib54ebd9c2014-08-27 18:38:41 -070011import org.apache.felix.scr.annotations.Activate;
tom69012372014-09-08 01:58:45 -070012import org.apache.felix.scr.annotations.Component;
alshabib54ebd9c2014-08-27 18:38:41 -070013import org.apache.felix.scr.annotations.Deactivate;
tom69012372014-09-08 01:58:45 -070014import org.apache.felix.scr.annotations.Service;
alshabibdf652ad2014-09-09 11:53:19 -070015import org.onlab.onos.of.controller.DefaultPacketContext;
alshabib54ebd9c2014-08-27 18:38:41 -070016import org.onlab.onos.of.controller.Dpid;
17import org.onlab.onos.of.controller.OpenFlowController;
18import org.onlab.onos.of.controller.OpenFlowSwitch;
19import org.onlab.onos.of.controller.OpenFlowSwitchListener;
20import org.onlab.onos.of.controller.PacketListener;
21import org.onlab.onos.of.controller.RoleState;
alshabib6171f182014-09-02 19:00:32 -070022import org.onlab.onos.of.controller.driver.OpenFlowAgent;
alshabib54ebd9c2014-08-27 18:38:41 -070023import org.projectfloodlight.openflow.protocol.OFMessage;
alshabibdf652ad2014-09-09 11:53:19 -070024import org.projectfloodlight.openflow.protocol.OFPacketIn;
alshabibc4901cd2014-09-05 16:50:40 -070025import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib54ebd9c2014-08-27 18:38:41 -070026import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
28
tom69012372014-09-08 01:58:45 -070029@Component(immediate = true)
30@Service
alshabib54ebd9c2014-08-27 18:38:41 -070031public class OpenFlowControllerImpl implements OpenFlowController {
32
alshabibd777b202014-08-28 17:52:55 -070033 private static final Logger log =
34 LoggerFactory.getLogger(OpenFlowControllerImpl.class);
35
alshabib6171f182014-09-02 19:00:32 -070036 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
37 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
38 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
39 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
40 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
41 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
alshabib54ebd9c2014-08-27 18:38:41 -070042
43 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
tomff7eb7c2014-09-08 12:49:03 -070044 protected Set<OpenFlowSwitchListener> ofEventListener =
45 new HashSet<>();
alshabib54ebd9c2014-08-27 18:38:41 -070046
alshabibdf652ad2014-09-09 11:53:19 -070047 protected List<PacketListener> ofPacketListener =
48 new ArrayList<>();
alshabibc4901cd2014-09-05 16:50:40 -070049
alshabibdf652ad2014-09-09 11:53:19 -070050 private final Controller ctrl = new Controller();
alshabib54ebd9c2014-08-27 18:38:41 -070051
alshabibdf652ad2014-09-09 11:53:19 -070052 @Activate
53 public void activate() {
54 ctrl.start(agent);
55 }
alshabib54ebd9c2014-08-27 18:38:41 -070056
alshabibdf652ad2014-09-09 11:53:19 -070057 @Deactivate
58 public void deactivate() {
59 ctrl.stop();
60 }
alshabib54ebd9c2014-08-27 18:38:41 -070061
alshabibdf652ad2014-09-09 11:53:19 -070062 @Override
63 public Iterable<OpenFlowSwitch> getSwitches() {
64 return connectedSwitches.values();
65 }
alshabib54ebd9c2014-08-27 18:38:41 -070066
alshabibdf652ad2014-09-09 11:53:19 -070067 @Override
68 public Iterable<OpenFlowSwitch> getMasterSwitches() {
69 return activeMasterSwitches.values();
70 }
alshabib54ebd9c2014-08-27 18:38:41 -070071
alshabibdf652ad2014-09-09 11:53:19 -070072 @Override
73 public Iterable<OpenFlowSwitch> getEqualSwitches() {
74 return activeEqualSwitches.values();
75 }
alshabib54ebd9c2014-08-27 18:38:41 -070076
alshabibdf652ad2014-09-09 11:53:19 -070077 @Override
78 public OpenFlowSwitch getSwitch(Dpid dpid) {
79 return connectedSwitches.get(dpid);
80 }
alshabib54ebd9c2014-08-27 18:38:41 -070081
alshabibdf652ad2014-09-09 11:53:19 -070082 @Override
83 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
84 return activeMasterSwitches.get(dpid);
85 }
alshabib54ebd9c2014-08-27 18:38:41 -070086
alshabibdf652ad2014-09-09 11:53:19 -070087 @Override
88 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
89 return activeEqualSwitches.get(dpid);
90 }
alshabib54ebd9c2014-08-27 18:38:41 -070091
alshabibdf652ad2014-09-09 11:53:19 -070092 @Override
93 public void addListener(OpenFlowSwitchListener listener) {
94 if (!ofEventListener.contains(listener)) {
95 this.ofEventListener.add(listener);
96 }
97 }
alshabib54ebd9c2014-08-27 18:38:41 -070098
alshabibdf652ad2014-09-09 11:53:19 -070099 @Override
100 public void removeListener(OpenFlowSwitchListener listener) {
101 this.ofEventListener.remove(listener);
102 }
alshabib54ebd9c2014-08-27 18:38:41 -0700103
alshabibdf652ad2014-09-09 11:53:19 -0700104 @Override
105 public void addPacketListener(int priority, PacketListener listener) {
106 ofPacketListener.add(priority, listener);
107 }
alshabib54ebd9c2014-08-27 18:38:41 -0700108
alshabibdf652ad2014-09-09 11:53:19 -0700109 @Override
110 public void removePacketListener(PacketListener listener) {
111 ofPacketListener.remove(listener);
112 }
alshabib54ebd9c2014-08-27 18:38:41 -0700113
alshabibdf652ad2014-09-09 11:53:19 -0700114 @Override
115 public void write(Dpid dpid, OFMessage msg) {
116 this.getSwitch(dpid).sendMsg(msg);
117 }
alshabib54ebd9c2014-08-27 18:38:41 -0700118
alshabibdf652ad2014-09-09 11:53:19 -0700119 @Override
120 public void processPacket(Dpid dpid, OFMessage msg) {
121 switch (msg.getType()) {
122 case PORT_STATUS:
123 for (OpenFlowSwitchListener l : ofEventListener) {
124 l.portChanged(dpid, (OFPortStatus) msg);
125 }
126 break;
127 case PACKET_IN:
128 for (PacketListener p : ofPacketListener) {
129 //TODO fix me!
130 p.handlePacket(DefaultPacketContext
131 .packetContextFromPacketIn(this.getSwitch(dpid),
132 (OFPacketIn) msg));
133 }
134 break;
135 default:
136 log.warn("Handling message type {} not yet implemented {}",
137 msg.getType(), msg);
138 }
139 }
alshabib54ebd9c2014-08-27 18:38:41 -0700140
alshabibdf652ad2014-09-09 11:53:19 -0700141 @Override
142 public void setRole(Dpid dpid, RoleState role) {
143 getSwitch(dpid).setRole(role);
144 }
alshabib54ebd9c2014-08-27 18:38:41 -0700145
alshabibdf652ad2014-09-09 11:53:19 -0700146 /**
147 * Implementation of an OpenFlow Agent which is responsible for
148 * keeping track of connected switches and the state in which
149 * they are.
150 */
151 public class OpenFlowSwitchAgent implements OpenFlowAgent {
alshabib54ebd9c2014-08-27 18:38:41 -0700152
alshabibdf652ad2014-09-09 11:53:19 -0700153 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
154 private final Lock switchLock = new ReentrantLock();
alshabib54ebd9c2014-08-27 18:38:41 -0700155
alshabibdf652ad2014-09-09 11:53:19 -0700156 @Override
157 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
158 if (connectedSwitches.get(dpid) != null) {
159 log.error("Trying to add connectedSwitch but found a previous "
160 + "value for dpid: {}", dpid);
161 return false;
162 } else {
163 log.error("Added switch {}", dpid);
164 connectedSwitches.put(dpid, sw);
165 for (OpenFlowSwitchListener l : ofEventListener) {
166 l.switchAdded(dpid);
167 }
168 return true;
169 }
170 }
alshabib54ebd9c2014-08-27 18:38:41 -0700171
alshabibdf652ad2014-09-09 11:53:19 -0700172 @Override
173 public boolean validActivation(Dpid dpid) {
174 if (connectedSwitches.get(dpid) == null) {
175 log.error("Trying to activate switch but is not in "
176 + "connected switches: dpid {}. Aborting ..",
177 dpid);
178 return false;
179 }
180 if (activeMasterSwitches.get(dpid) != null ||
181 activeEqualSwitches.get(dpid) != null) {
182 log.error("Trying to activate switch but it is already "
183 + "activated: dpid {}. Found in activeMaster: {} "
184 + "Found in activeEqual: {}. Aborting ..", new Object[]{
185 dpid,
186 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
187 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
188 return false;
189 }
190 return true;
191 }
alshabib54ebd9c2014-08-27 18:38:41 -0700192
alshabib6171f182014-09-02 19:00:32 -0700193
alshabibdf652ad2014-09-09 11:53:19 -0700194 @Override
195 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
196 switchLock.lock();
197 try {
198 if (!validActivation(dpid)) {
199 return false;
200 }
201 activeMasterSwitches.put(dpid, sw);
202 return true;
203 } finally {
204 switchLock.unlock();
205 }
206 }
alshabib54ebd9c2014-08-27 18:38:41 -0700207
alshabibdf652ad2014-09-09 11:53:19 -0700208 @Override
209 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
210 switchLock.lock();
211 try {
212 if (!validActivation(dpid)) {
213 return false;
214 }
215 activeEqualSwitches.put(dpid, sw);
216 log.info("Added Activated EQUAL Switch {}", dpid);
217 return true;
218 } finally {
219 switchLock.unlock();
220 }
221 }
alshabib54ebd9c2014-08-27 18:38:41 -0700222
alshabibdf652ad2014-09-09 11:53:19 -0700223 @Override
224 public void transitionToMasterSwitch(Dpid dpid) {
225 switchLock.lock();
226 try {
227 if (activeMasterSwitches.containsKey(dpid)) {
228 return;
229 }
230 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
231 if (sw == null) {
232 sw = getSwitch(dpid);
233 if (sw == null) {
234 log.error("Transition to master called on sw {}, but switch "
235 + "was not found in controller-cache", dpid);
236 return;
237 }
238 }
239 log.info("Transitioned switch {} to MASTER", dpid);
240 activeMasterSwitches.put(dpid, sw);
241 } finally {
242 switchLock.unlock();
243 }
244 }
alshabib54ebd9c2014-08-27 18:38:41 -0700245
246
alshabibdf652ad2014-09-09 11:53:19 -0700247 @Override
248 public void transitionToEqualSwitch(Dpid dpid) {
249 switchLock.lock();
250 try {
251 if (activeEqualSwitches.containsKey(dpid)) {
252 return;
253 }
254 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
255 if (sw == null) {
256 log.error("Transition to equal called on sw {}, but switch "
257 + "was not found in controller-cache", dpid);
258 return;
259 }
260 log.info("Transitioned switch {} to EQUAL", dpid);
261 activeEqualSwitches.put(dpid, sw);
262 } finally {
263 switchLock.unlock();
264 }
alshabib54ebd9c2014-08-27 18:38:41 -0700265
alshabibdf652ad2014-09-09 11:53:19 -0700266 }
alshabib54ebd9c2014-08-27 18:38:41 -0700267
alshabibdf652ad2014-09-09 11:53:19 -0700268 @Override
269 public void removeConnectedSwitch(Dpid dpid) {
270 connectedSwitches.remove(dpid);
271 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
272 if (sw == null) {
273 sw = activeEqualSwitches.remove(dpid);
274 }
275 for (OpenFlowSwitchListener l : ofEventListener) {
276 l.switchRemoved(dpid);
277 }
278 }
alshabib54ebd9c2014-08-27 18:38:41 -0700279
alshabibdf652ad2014-09-09 11:53:19 -0700280 @Override
281 public void processMessage(Dpid dpid, OFMessage m) {
282 processPacket(dpid, m);
283 }
284 }
alshabib54ebd9c2014-08-27 18:38:41 -0700285
286
alshabib54ebd9c2014-08-27 18:38:41 -0700287}