blob: b36147827480c1b2505b2a69dbaab781adfc5ca8 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.openflow.controller.impl;
tom7ef8ff92014-09-17 13:08:06 -070017
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080018import com.google.common.collect.ArrayListMultimap;
alshabib64def642014-12-02 23:27:37 -080019import com.google.common.collect.Lists;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080020import com.google.common.collect.Multimap;
tom7ef8ff92014-09-17 13:08:06 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080024import org.apache.felix.scr.annotations.Modified;
alshabibb452fd72015-04-22 20:46:20 -070025import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
tom7ef8ff92014-09-17 13:08:06 -070027import org.apache.felix.scr.annotations.Service;
alshabibb452fd72015-04-22 20:46:20 -070028import org.onosproject.net.driver.DriverService;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
30import org.onosproject.openflow.controller.Dpid;
31import org.onosproject.openflow.controller.OpenFlowController;
32import org.onosproject.openflow.controller.OpenFlowEventListener;
33import org.onosproject.openflow.controller.OpenFlowPacketContext;
34import org.onosproject.openflow.controller.OpenFlowSwitch;
35import org.onosproject.openflow.controller.OpenFlowSwitchListener;
36import org.onosproject.openflow.controller.PacketListener;
37import org.onosproject.openflow.controller.RoleState;
38import org.onosproject.openflow.controller.driver.OpenFlowAgent;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080039import org.osgi.service.component.ComponentContext;
Marc De Leenheer631ffce2014-10-28 16:29:07 -070040import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
41import org.projectfloodlight.openflow.protocol.OFExperimenter;
alshabib64def642014-12-02 23:27:37 -080042import org.projectfloodlight.openflow.protocol.OFFactories;
43import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
44import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
sangho6a0bb172015-02-05 12:24:48 -080045import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
46import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
47import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
48import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070049import org.projectfloodlight.openflow.protocol.OFMessage;
50import org.projectfloodlight.openflow.protocol.OFPacketIn;
Marc De Leenheer631ffce2014-10-28 16:29:07 -070051import org.projectfloodlight.openflow.protocol.OFPortDesc;
sangho538108b2015-04-08 14:29:20 -070052import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
53import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070054import org.projectfloodlight.openflow.protocol.OFPortStatus;
Ayaka Koshibe38594c22014-10-22 13:36:12 -070055import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib64def642014-12-02 23:27:37 -080056import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
tom7ef8ff92014-09-17 13:08:06 -070057import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080060import java.util.Collection;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080061import java.util.Dictionary;
62import java.util.HashMap;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080063import java.util.Map;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080064import java.util.Set;
65import java.util.concurrent.ConcurrentHashMap;
Jonathan Hart6d44d192015-05-11 18:01:19 -070066import java.util.concurrent.CopyOnWriteArraySet;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080067import java.util.concurrent.ExecutorService;
68import java.util.concurrent.Executors;
69import java.util.concurrent.locks.Lock;
70import java.util.concurrent.locks.ReentrantLock;
71
72import static org.onlab.util.Tools.groupedThreads;
tom7ef8ff92014-09-17 13:08:06 -070073
74@Component(immediate = true)
75@Service
76public class OpenFlowControllerImpl implements OpenFlowController {
77
78 private static final Logger log =
79 LoggerFactory.getLogger(OpenFlowControllerImpl.class);
80
alshabibb452fd72015-04-22 20:46:20 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected DriverService driverService;
83
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080084 private final ExecutorService executorMsgs =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080085 Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d"));
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080086
87 private final ExecutorService executorBarrier =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080088 Executors.newFixedThreadPool(4, groupedThreads("onos/of", "event-barrier-%d"));
alshabib8f1cf4a2014-09-17 14:44:48 -070089
tom7ef8ff92014-09-17 13:08:06 -070090 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
Jonathan Hart6d44d192015-05-11 18:01:19 -070091 new ConcurrentHashMap<>();
tom7ef8ff92014-09-17 13:08:06 -070092 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
Jonathan Hart6d44d192015-05-11 18:01:19 -070093 new ConcurrentHashMap<>();
tom7ef8ff92014-09-17 13:08:06 -070094 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
Jonathan Hart6d44d192015-05-11 18:01:19 -070095 new ConcurrentHashMap<>();
tom7ef8ff92014-09-17 13:08:06 -070096
97 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
Jonathan Hart6d44d192015-05-11 18:01:19 -070098 protected Set<OpenFlowSwitchListener> ofSwitchListener = new CopyOnWriteArraySet<>();
tom7ef8ff92014-09-17 13:08:06 -070099
100 protected Multimap<Integer, PacketListener> ofPacketListener =
101 ArrayListMultimap.create();
102
Jonathan Hart6d44d192015-05-11 18:01:19 -0700103 protected Set<OpenFlowEventListener> ofEventListener = new CopyOnWriteArraySet<>();
tom7ef8ff92014-09-17 13:08:06 -0700104
sangho6a0bb172015-02-05 12:24:48 -0800105 protected Multimap<Dpid, OFFlowStatsEntry> fullFlowStats =
106 ArrayListMultimap.create();
107
108 protected Multimap<Dpid, OFGroupStatsEntry> fullGroupStats =
109 ArrayListMultimap.create();
110
111 protected Multimap<Dpid, OFGroupDescStatsEntry> fullGroupDescStats =
alshabib64def642014-12-02 23:27:37 -0800112 ArrayListMultimap.create();
113
sangho538108b2015-04-08 14:29:20 -0700114 protected Multimap<Dpid, OFPortStatsEntry> fullPortStats =
115 ArrayListMultimap.create();
116
tom7ef8ff92014-09-17 13:08:06 -0700117 private final Controller ctrl = new Controller();
118
119 @Activate
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800120 public void activate(ComponentContext context) {
121 Map<String, String> properties = readComponentConfiguration(context);
122 ctrl.setConfigParams(properties);
alshabibb452fd72015-04-22 20:46:20 -0700123 ctrl.start(agent, driverService);
tom7ef8ff92014-09-17 13:08:06 -0700124 }
125
126 @Deactivate
127 public void deactivate() {
128 ctrl.stop();
129 }
130
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800131 /**
132 * Extracts properties from the component configuration context.
133 *
134 * @param context the component context
135 */
136 private Map<String, String> readComponentConfiguration(ComponentContext context) {
137 Dictionary<?, ?> properties = context.getProperties();
138 Map<String, String> outProperties = new HashMap<>();
139 try {
140 String strDpid = (String) properties.get("corsaDpid");
141 if (strDpid != null) {
142 outProperties.put("corsaDpid", strDpid);
143 }
144 } catch (ClassCastException e) {
145 return outProperties;
146 }
147 return outProperties;
148 }
149
150 @Modified
151 public void modified(ComponentContext context) {
152 // Blank @Modified method to catch modifications to the context.
153 // If no @Modified method exists, @Activate is called again
154 // when the context is modified.
155 }
156
tom7ef8ff92014-09-17 13:08:06 -0700157 @Override
158 public Iterable<OpenFlowSwitch> getSwitches() {
159 return connectedSwitches.values();
160 }
161
162 @Override
163 public Iterable<OpenFlowSwitch> getMasterSwitches() {
164 return activeMasterSwitches.values();
165 }
166
167 @Override
168 public Iterable<OpenFlowSwitch> getEqualSwitches() {
169 return activeEqualSwitches.values();
170 }
171
172 @Override
173 public OpenFlowSwitch getSwitch(Dpid dpid) {
174 return connectedSwitches.get(dpid);
175 }
176
177 @Override
178 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
179 return activeMasterSwitches.get(dpid);
180 }
181
182 @Override
183 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
184 return activeEqualSwitches.get(dpid);
185 }
186
187 @Override
188 public void addListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700189 if (!ofSwitchListener.contains(listener)) {
190 this.ofSwitchListener.add(listener);
tom7ef8ff92014-09-17 13:08:06 -0700191 }
192 }
193
194 @Override
195 public void removeListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700196 this.ofSwitchListener.remove(listener);
tom7ef8ff92014-09-17 13:08:06 -0700197 }
198
199 @Override
200 public void addPacketListener(int priority, PacketListener listener) {
201 ofPacketListener.put(priority, listener);
202 }
203
204 @Override
205 public void removePacketListener(PacketListener listener) {
206 ofPacketListener.values().remove(listener);
207 }
208
209 @Override
alshabibeec3a062014-09-17 18:01:26 -0700210 public void addEventListener(OpenFlowEventListener listener) {
211 ofEventListener.add(listener);
212 }
213
214 @Override
215 public void removeEventListener(OpenFlowEventListener listener) {
216 ofEventListener.remove(listener);
217 }
218
219 @Override
tom7ef8ff92014-09-17 13:08:06 -0700220 public void write(Dpid dpid, OFMessage msg) {
221 this.getSwitch(dpid).sendMsg(msg);
222 }
223
224 @Override
225 public void processPacket(Dpid dpid, OFMessage msg) {
sangho6a0bb172015-02-05 12:24:48 -0800226 Collection<OFFlowStatsEntry> flowStats;
227 Collection<OFGroupStatsEntry> groupStats;
228 Collection<OFGroupDescStatsEntry> groupDescStats;
sangho538108b2015-04-08 14:29:20 -0700229 Collection<OFPortStatsEntry> portStats;
sangho6a0bb172015-02-05 12:24:48 -0800230
tom7ef8ff92014-09-17 13:08:06 -0700231 switch (msg.getType()) {
232 case PORT_STATUS:
alshabib8f1cf4a2014-09-17 14:44:48 -0700233 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700234 l.portChanged(dpid, (OFPortStatus) msg);
235 }
236 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700237 case FEATURES_REPLY:
238 for (OpenFlowSwitchListener l : ofSwitchListener) {
239 l.switchChanged(dpid);
240 }
241 break;
tom7ef8ff92014-09-17 13:08:06 -0700242 case PACKET_IN:
243 OpenFlowPacketContext pktCtx = DefaultOpenFlowPacketContext
244 .packetContextFromPacketIn(this.getSwitch(dpid),
245 (OFPacketIn) msg);
246 for (PacketListener p : ofPacketListener.values()) {
247 p.handlePacket(pktCtx);
248 }
249 break;
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800250 // TODO: Consider using separate threadpool for sensitive messages.
251 // ie. Back to back error could cause us to starve.
252 case FLOW_REMOVED:
253 case ERROR:
254 executorMsgs.submit(new OFMessageHandler(dpid, msg));
255 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700256 case STATS_REPLY:
257 OFStatsReply reply = (OFStatsReply) msg;
sangho6a0bb172015-02-05 12:24:48 -0800258 switch (reply.getStatsType()) {
259 case PORT_DESC:
260 for (OpenFlowSwitchListener l : ofSwitchListener) {
261 l.switchChanged(dpid);
262 }
263 break;
264 case FLOW:
265 flowStats = publishFlowStats(dpid, (OFFlowStatsReply) reply);
266 if (flowStats != null) {
267 OFFlowStatsReply.Builder rep =
268 OFFactories.getFactory(msg.getVersion()).buildFlowStatsReply();
269 rep.setEntries(Lists.newLinkedList(flowStats));
270 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
271 }
272 break;
273 case GROUP:
274 groupStats = publishGroupStats(dpid, (OFGroupStatsReply) reply);
275 if (groupStats != null) {
276 OFGroupStatsReply.Builder rep =
277 OFFactories.getFactory(msg.getVersion()).buildGroupStatsReply();
278 rep.setEntries(Lists.newLinkedList(groupStats));
279 rep.setXid(reply.getXid());
280 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
281 }
282 break;
283 case GROUP_DESC:
284 groupDescStats = publishGroupDescStats(dpid,
285 (OFGroupDescStatsReply) reply);
286 if (groupDescStats != null) {
287 OFGroupDescStatsReply.Builder rep =
288 OFFactories.getFactory(msg.getVersion()).buildGroupDescStatsReply();
289 rep.setEntries(Lists.newLinkedList(groupDescStats));
290 rep.setXid(reply.getXid());
291 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
292 }
293 break;
sangho538108b2015-04-08 14:29:20 -0700294 case PORT:
295 executorMsgs.submit(new OFMessageHandler(dpid, reply));
296 break;
sangho6a0bb172015-02-05 12:24:48 -0800297 default:
298 log.warn("Unsupported stats type : {}", reply.getStatsType());
alshabib64def642014-12-02 23:27:37 -0800299 }
300 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700301 case BARRIER_REPLY:
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800302 executorBarrier.submit(new OFMessageHandler(dpid, msg));
alshabib8f1cf4a2014-09-17 14:44:48 -0700303 break;
Marc De Leenheer631ffce2014-10-28 16:29:07 -0700304 case EXPERIMENTER:
305 // Handle optical port stats
306 if (((OFExperimenter) msg).getExperimenter() == 0x748771) {
307 OFCircuitPortStatus circuitPortStatus = (OFCircuitPortStatus) msg;
308 OFPortStatus.Builder portStatus = this.getSwitch(dpid).factory().buildPortStatus();
309 OFPortDesc.Builder portDesc = this.getSwitch(dpid).factory().buildPortDesc();
310 portDesc.setPortNo(circuitPortStatus.getPortNo())
311 .setHwAddr(circuitPortStatus.getHwAddr())
312 .setName(circuitPortStatus.getName())
313 .setConfig(circuitPortStatus.getConfig())
314 .setState(circuitPortStatus.getState());
315 portStatus.setReason(circuitPortStatus.getReason()).setDesc(portDesc.build());
316 for (OpenFlowSwitchListener l : ofSwitchListener) {
317 l.portChanged(dpid, portStatus.build());
318 }
319 } else {
320 log.warn("Handling experimenter type {} not yet implemented",
321 ((OFExperimenter) msg).getExperimenter(), msg);
322 }
323 break;
tom7ef8ff92014-09-17 13:08:06 -0700324 default:
325 log.warn("Handling message type {} not yet implemented {}",
326 msg.getType(), msg);
327 }
328 }
329
sangho6a0bb172015-02-05 12:24:48 -0800330 private synchronized Collection<OFFlowStatsEntry> publishFlowStats(Dpid dpid,
331 OFFlowStatsReply reply) {
alshabib64def642014-12-02 23:27:37 -0800332 //TODO: Get rid of synchronized
sangho6a0bb172015-02-05 12:24:48 -0800333 fullFlowStats.putAll(dpid, reply.getEntries());
alshabib64def642014-12-02 23:27:37 -0800334 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
sangho6a0bb172015-02-05 12:24:48 -0800335 return fullFlowStats.removeAll(dpid);
336 }
337 return null;
338 }
339
340 private synchronized Collection<OFGroupStatsEntry> publishGroupStats(Dpid dpid,
341 OFGroupStatsReply reply) {
342 //TODO: Get rid of synchronized
343 fullGroupStats.putAll(dpid, reply.getEntries());
344 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
345 return fullGroupStats.removeAll(dpid);
346 }
347 return null;
348 }
349
350 private synchronized Collection<OFGroupDescStatsEntry> publishGroupDescStats(Dpid dpid,
351 OFGroupDescStatsReply reply) {
352 //TODO: Get rid of synchronized
353 fullGroupDescStats.putAll(dpid, reply.getEntries());
354 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
355 return fullGroupDescStats.removeAll(dpid);
alshabib64def642014-12-02 23:27:37 -0800356 }
357 return null;
358 }
359
sangho538108b2015-04-08 14:29:20 -0700360 private synchronized Collection<OFPortStatsEntry> publishPortStats(Dpid dpid,
361 OFPortStatsReply reply) {
362 fullPortStats.putAll(dpid, reply.getEntries());
363 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
364 return fullPortStats.removeAll(dpid);
365 }
366 return null;
367 }
368
tom7ef8ff92014-09-17 13:08:06 -0700369 @Override
370 public void setRole(Dpid dpid, RoleState role) {
Yuta HIGUCHI79cbd1c2014-10-02 16:57:57 -0700371 final OpenFlowSwitch sw = getSwitch(dpid);
372 if (sw == null) {
373 log.debug("Switch not connected. Ignoring setRole({}, {})", dpid, role);
374 return;
375 }
376 sw.setRole(role);
tom7ef8ff92014-09-17 13:08:06 -0700377 }
378
379 /**
380 * Implementation of an OpenFlow Agent which is responsible for
381 * keeping track of connected switches and the state in which
382 * they are.
383 */
384 public class OpenFlowSwitchAgent implements OpenFlowAgent {
385
386 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
387 private final Lock switchLock = new ReentrantLock();
388
389 @Override
390 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib9eab22f2014-10-20 17:17:31 -0700391
tom7ef8ff92014-09-17 13:08:06 -0700392 if (connectedSwitches.get(dpid) != null) {
393 log.error("Trying to add connectedSwitch but found a previous "
394 + "value for dpid: {}", dpid);
395 return false;
396 } else {
Yuta HIGUCHIeb3f30b2014-10-22 11:34:49 -0700397 log.info("Added switch {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700398 connectedSwitches.put(dpid, sw);
alshabib8f1cf4a2014-09-17 14:44:48 -0700399 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700400 l.switchAdded(dpid);
401 }
402 return true;
403 }
404 }
405
406 @Override
407 public boolean validActivation(Dpid dpid) {
408 if (connectedSwitches.get(dpid) == null) {
409 log.error("Trying to activate switch but is not in "
410 + "connected switches: dpid {}. Aborting ..",
411 dpid);
412 return false;
413 }
414 if (activeMasterSwitches.get(dpid) != null ||
415 activeEqualSwitches.get(dpid) != null) {
416 log.error("Trying to activate switch but it is already "
417 + "activated: dpid {}. Found in activeMaster: {} "
418 + "Found in activeEqual: {}. Aborting ..", new Object[]{
419 dpid,
420 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
421 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
422 return false;
423 }
424 return true;
425 }
426
427
428 @Override
429 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
430 switchLock.lock();
431 try {
432 if (!validActivation(dpid)) {
433 return false;
434 }
435 activeMasterSwitches.put(dpid, sw);
436 return true;
437 } finally {
438 switchLock.unlock();
439 }
440 }
441
442 @Override
443 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
444 switchLock.lock();
445 try {
446 if (!validActivation(dpid)) {
447 return false;
448 }
449 activeEqualSwitches.put(dpid, sw);
450 log.info("Added Activated EQUAL Switch {}", dpid);
451 return true;
452 } finally {
453 switchLock.unlock();
454 }
455 }
456
457 @Override
458 public void transitionToMasterSwitch(Dpid dpid) {
459 switchLock.lock();
460 try {
461 if (activeMasterSwitches.containsKey(dpid)) {
462 return;
463 }
464 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
465 if (sw == null) {
466 sw = getSwitch(dpid);
467 if (sw == null) {
468 log.error("Transition to master called on sw {}, but switch "
469 + "was not found in controller-cache", dpid);
470 return;
471 }
472 }
473 log.info("Transitioned switch {} to MASTER", dpid);
474 activeMasterSwitches.put(dpid, sw);
475 } finally {
476 switchLock.unlock();
477 }
478 }
479
480
481 @Override
482 public void transitionToEqualSwitch(Dpid dpid) {
483 switchLock.lock();
484 try {
485 if (activeEqualSwitches.containsKey(dpid)) {
486 return;
487 }
488 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
489 if (sw == null) {
490 sw = getSwitch(dpid);
491 if (sw == null) {
492 log.error("Transition to equal called on sw {}, but switch "
493 + "was not found in controller-cache", dpid);
494 return;
495 }
496 }
497 log.info("Transitioned switch {} to EQUAL", dpid);
498 activeEqualSwitches.put(dpid, sw);
499 } finally {
500 switchLock.unlock();
501 }
502
503 }
504
505 @Override
506 public void removeConnectedSwitch(Dpid dpid) {
507 connectedSwitches.remove(dpid);
508 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
509 if (sw == null) {
Ayaka Koshibec4047702014-10-07 14:43:52 -0700510 log.warn("sw was null for {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700511 sw = activeEqualSwitches.remove(dpid);
512 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700513 for (OpenFlowSwitchListener l : ofSwitchListener) {
Ayaka Koshibec4047702014-10-07 14:43:52 -0700514 log.warn("removal for {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700515 l.switchRemoved(dpid);
516 }
517 }
518
519 @Override
520 public void processMessage(Dpid dpid, OFMessage m) {
521 processPacket(dpid, m);
522 }
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700523
524 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700525 public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response) {
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700526 for (OpenFlowSwitchListener l : ofSwitchListener) {
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700527 l.receivedRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700528 }
529 }
tom7ef8ff92014-09-17 13:08:06 -0700530 }
531
alshabib8f1cf4a2014-09-17 14:44:48 -0700532 private final class OFMessageHandler implements Runnable {
533
534 private final OFMessage msg;
535 private final Dpid dpid;
536
537 public OFMessageHandler(Dpid dpid, OFMessage msg) {
538 this.msg = msg;
539 this.dpid = dpid;
540 }
541
542 @Override
543 public void run() {
alshabibeec3a062014-09-17 18:01:26 -0700544 for (OpenFlowEventListener listener : ofEventListener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700545 listener.handleMessage(dpid, msg);
546 }
547 }
548
549 }
550
tom7ef8ff92014-09-17 13:08:06 -0700551}