blob: b59ce189fa92198221cfb61e5146397502ce04c7 [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;
21import com.google.common.collect.Sets;
tom7ef8ff92014-09-17 13:08:06 -070022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080025import org.apache.felix.scr.annotations.Modified;
alshabibb452fd72015-04-22 20:46:20 -070026import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
tom7ef8ff92014-09-17 13:08:06 -070028import org.apache.felix.scr.annotations.Service;
alshabibb452fd72015-04-22 20:46:20 -070029import org.onosproject.net.driver.DriverService;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
31import org.onosproject.openflow.controller.Dpid;
32import org.onosproject.openflow.controller.OpenFlowController;
33import org.onosproject.openflow.controller.OpenFlowEventListener;
34import org.onosproject.openflow.controller.OpenFlowPacketContext;
35import org.onosproject.openflow.controller.OpenFlowSwitch;
36import org.onosproject.openflow.controller.OpenFlowSwitchListener;
37import org.onosproject.openflow.controller.PacketListener;
38import org.onosproject.openflow.controller.RoleState;
39import org.onosproject.openflow.controller.driver.OpenFlowAgent;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080040import org.osgi.service.component.ComponentContext;
Marc De Leenheer631ffce2014-10-28 16:29:07 -070041import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
42import org.projectfloodlight.openflow.protocol.OFExperimenter;
alshabib64def642014-12-02 23:27:37 -080043import org.projectfloodlight.openflow.protocol.OFFactories;
44import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
45import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
sangho6a0bb172015-02-05 12:24:48 -080046import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
47import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
48import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
49import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070050import org.projectfloodlight.openflow.protocol.OFMessage;
51import org.projectfloodlight.openflow.protocol.OFPacketIn;
Marc De Leenheer631ffce2014-10-28 16:29:07 -070052import org.projectfloodlight.openflow.protocol.OFPortDesc;
sangho538108b2015-04-08 14:29:20 -070053import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
54import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070055import org.projectfloodlight.openflow.protocol.OFPortStatus;
Ayaka Koshibe38594c22014-10-22 13:36:12 -070056import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib64def642014-12-02 23:27:37 -080057import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
tom7ef8ff92014-09-17 13:08:06 -070058import org.slf4j.Logger;
59import org.slf4j.LoggerFactory;
60
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080061import java.util.Collection;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080062import java.util.Dictionary;
63import java.util.HashMap;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080064import java.util.HashSet;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080065import java.util.Map;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080066import java.util.Set;
67import java.util.concurrent.ConcurrentHashMap;
68import java.util.concurrent.ExecutorService;
69import java.util.concurrent.Executors;
70import java.util.concurrent.locks.Lock;
71import java.util.concurrent.locks.ReentrantLock;
72
73import static org.onlab.util.Tools.groupedThreads;
tom7ef8ff92014-09-17 13:08:06 -070074
75@Component(immediate = true)
76@Service
77public class OpenFlowControllerImpl implements OpenFlowController {
78
79 private static final Logger log =
80 LoggerFactory.getLogger(OpenFlowControllerImpl.class);
81
alshabibb452fd72015-04-22 20:46:20 -070082 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected DriverService driverService;
84
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080085 private final ExecutorService executorMsgs =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080086 Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d"));
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080087
88 private final ExecutorService executorBarrier =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080089 Executors.newFixedThreadPool(4, groupedThreads("onos/of", "event-barrier-%d"));
alshabib8f1cf4a2014-09-17 14:44:48 -070090
tom7ef8ff92014-09-17 13:08:06 -070091 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
92 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
93 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
94 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
95 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
96 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
97
98 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
alshabib8f1cf4a2014-09-17 14:44:48 -070099 protected Set<OpenFlowSwitchListener> ofSwitchListener = new HashSet<>();
tom7ef8ff92014-09-17 13:08:06 -0700100
101 protected Multimap<Integer, PacketListener> ofPacketListener =
102 ArrayListMultimap.create();
103
alshabibeec3a062014-09-17 18:01:26 -0700104 protected Set<OpenFlowEventListener> ofEventListener = Sets.newHashSet();
tom7ef8ff92014-09-17 13:08:06 -0700105
sangho6a0bb172015-02-05 12:24:48 -0800106 protected Multimap<Dpid, OFFlowStatsEntry> fullFlowStats =
107 ArrayListMultimap.create();
108
109 protected Multimap<Dpid, OFGroupStatsEntry> fullGroupStats =
110 ArrayListMultimap.create();
111
112 protected Multimap<Dpid, OFGroupDescStatsEntry> fullGroupDescStats =
alshabib64def642014-12-02 23:27:37 -0800113 ArrayListMultimap.create();
114
sangho538108b2015-04-08 14:29:20 -0700115 protected Multimap<Dpid, OFPortStatsEntry> fullPortStats =
116 ArrayListMultimap.create();
117
tom7ef8ff92014-09-17 13:08:06 -0700118 private final Controller ctrl = new Controller();
119
120 @Activate
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800121 public void activate(ComponentContext context) {
122 Map<String, String> properties = readComponentConfiguration(context);
123 ctrl.setConfigParams(properties);
alshabibb452fd72015-04-22 20:46:20 -0700124 ctrl.start(agent, driverService);
tom7ef8ff92014-09-17 13:08:06 -0700125 }
126
127 @Deactivate
128 public void deactivate() {
129 ctrl.stop();
130 }
131
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800132 /**
133 * Extracts properties from the component configuration context.
134 *
135 * @param context the component context
136 */
137 private Map<String, String> readComponentConfiguration(ComponentContext context) {
138 Dictionary<?, ?> properties = context.getProperties();
139 Map<String, String> outProperties = new HashMap<>();
140 try {
141 String strDpid = (String) properties.get("corsaDpid");
142 if (strDpid != null) {
143 outProperties.put("corsaDpid", strDpid);
144 }
145 } catch (ClassCastException e) {
146 return outProperties;
147 }
148 return outProperties;
149 }
150
151 @Modified
152 public void modified(ComponentContext context) {
153 // Blank @Modified method to catch modifications to the context.
154 // If no @Modified method exists, @Activate is called again
155 // when the context is modified.
156 }
157
tom7ef8ff92014-09-17 13:08:06 -0700158 @Override
159 public Iterable<OpenFlowSwitch> getSwitches() {
160 return connectedSwitches.values();
161 }
162
163 @Override
164 public Iterable<OpenFlowSwitch> getMasterSwitches() {
165 return activeMasterSwitches.values();
166 }
167
168 @Override
169 public Iterable<OpenFlowSwitch> getEqualSwitches() {
170 return activeEqualSwitches.values();
171 }
172
173 @Override
174 public OpenFlowSwitch getSwitch(Dpid dpid) {
175 return connectedSwitches.get(dpid);
176 }
177
178 @Override
179 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
180 return activeMasterSwitches.get(dpid);
181 }
182
183 @Override
184 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
185 return activeEqualSwitches.get(dpid);
186 }
187
188 @Override
189 public void addListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700190 if (!ofSwitchListener.contains(listener)) {
191 this.ofSwitchListener.add(listener);
tom7ef8ff92014-09-17 13:08:06 -0700192 }
193 }
194
195 @Override
196 public void removeListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700197 this.ofSwitchListener.remove(listener);
tom7ef8ff92014-09-17 13:08:06 -0700198 }
199
200 @Override
201 public void addPacketListener(int priority, PacketListener listener) {
202 ofPacketListener.put(priority, listener);
203 }
204
205 @Override
206 public void removePacketListener(PacketListener listener) {
207 ofPacketListener.values().remove(listener);
208 }
209
210 @Override
alshabibeec3a062014-09-17 18:01:26 -0700211 public void addEventListener(OpenFlowEventListener listener) {
212 ofEventListener.add(listener);
213 }
214
215 @Override
216 public void removeEventListener(OpenFlowEventListener listener) {
217 ofEventListener.remove(listener);
218 }
219
220 @Override
tom7ef8ff92014-09-17 13:08:06 -0700221 public void write(Dpid dpid, OFMessage msg) {
222 this.getSwitch(dpid).sendMsg(msg);
223 }
224
225 @Override
226 public void processPacket(Dpid dpid, OFMessage msg) {
sangho6a0bb172015-02-05 12:24:48 -0800227 Collection<OFFlowStatsEntry> flowStats;
228 Collection<OFGroupStatsEntry> groupStats;
229 Collection<OFGroupDescStatsEntry> groupDescStats;
sangho538108b2015-04-08 14:29:20 -0700230 Collection<OFPortStatsEntry> portStats;
sangho6a0bb172015-02-05 12:24:48 -0800231
tom7ef8ff92014-09-17 13:08:06 -0700232 switch (msg.getType()) {
233 case PORT_STATUS:
alshabib8f1cf4a2014-09-17 14:44:48 -0700234 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700235 l.portChanged(dpid, (OFPortStatus) msg);
236 }
237 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700238 case FEATURES_REPLY:
239 for (OpenFlowSwitchListener l : ofSwitchListener) {
240 l.switchChanged(dpid);
241 }
242 break;
tom7ef8ff92014-09-17 13:08:06 -0700243 case PACKET_IN:
244 OpenFlowPacketContext pktCtx = DefaultOpenFlowPacketContext
245 .packetContextFromPacketIn(this.getSwitch(dpid),
246 (OFPacketIn) msg);
247 for (PacketListener p : ofPacketListener.values()) {
248 p.handlePacket(pktCtx);
249 }
250 break;
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800251 // TODO: Consider using separate threadpool for sensitive messages.
252 // ie. Back to back error could cause us to starve.
253 case FLOW_REMOVED:
254 case ERROR:
255 executorMsgs.submit(new OFMessageHandler(dpid, msg));
256 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700257 case STATS_REPLY:
258 OFStatsReply reply = (OFStatsReply) msg;
sangho6a0bb172015-02-05 12:24:48 -0800259 switch (reply.getStatsType()) {
260 case PORT_DESC:
261 for (OpenFlowSwitchListener l : ofSwitchListener) {
262 l.switchChanged(dpid);
263 }
264 break;
265 case FLOW:
266 flowStats = publishFlowStats(dpid, (OFFlowStatsReply) reply);
267 if (flowStats != null) {
268 OFFlowStatsReply.Builder rep =
269 OFFactories.getFactory(msg.getVersion()).buildFlowStatsReply();
270 rep.setEntries(Lists.newLinkedList(flowStats));
271 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
272 }
273 break;
274 case GROUP:
275 groupStats = publishGroupStats(dpid, (OFGroupStatsReply) reply);
276 if (groupStats != null) {
277 OFGroupStatsReply.Builder rep =
278 OFFactories.getFactory(msg.getVersion()).buildGroupStatsReply();
279 rep.setEntries(Lists.newLinkedList(groupStats));
280 rep.setXid(reply.getXid());
281 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
282 }
283 break;
284 case GROUP_DESC:
285 groupDescStats = publishGroupDescStats(dpid,
286 (OFGroupDescStatsReply) reply);
287 if (groupDescStats != null) {
288 OFGroupDescStatsReply.Builder rep =
289 OFFactories.getFactory(msg.getVersion()).buildGroupDescStatsReply();
290 rep.setEntries(Lists.newLinkedList(groupDescStats));
291 rep.setXid(reply.getXid());
292 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
293 }
294 break;
sangho538108b2015-04-08 14:29:20 -0700295 case PORT:
296 executorMsgs.submit(new OFMessageHandler(dpid, reply));
297 break;
sangho6a0bb172015-02-05 12:24:48 -0800298 default:
299 log.warn("Unsupported stats type : {}", reply.getStatsType());
alshabib64def642014-12-02 23:27:37 -0800300 }
301 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700302 case BARRIER_REPLY:
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800303 executorBarrier.submit(new OFMessageHandler(dpid, msg));
alshabib8f1cf4a2014-09-17 14:44:48 -0700304 break;
Marc De Leenheer631ffce2014-10-28 16:29:07 -0700305 case EXPERIMENTER:
306 // Handle optical port stats
307 if (((OFExperimenter) msg).getExperimenter() == 0x748771) {
308 OFCircuitPortStatus circuitPortStatus = (OFCircuitPortStatus) msg;
309 OFPortStatus.Builder portStatus = this.getSwitch(dpid).factory().buildPortStatus();
310 OFPortDesc.Builder portDesc = this.getSwitch(dpid).factory().buildPortDesc();
311 portDesc.setPortNo(circuitPortStatus.getPortNo())
312 .setHwAddr(circuitPortStatus.getHwAddr())
313 .setName(circuitPortStatus.getName())
314 .setConfig(circuitPortStatus.getConfig())
315 .setState(circuitPortStatus.getState());
316 portStatus.setReason(circuitPortStatus.getReason()).setDesc(portDesc.build());
317 for (OpenFlowSwitchListener l : ofSwitchListener) {
318 l.portChanged(dpid, portStatus.build());
319 }
320 } else {
321 log.warn("Handling experimenter type {} not yet implemented",
322 ((OFExperimenter) msg).getExperimenter(), msg);
323 }
324 break;
tom7ef8ff92014-09-17 13:08:06 -0700325 default:
326 log.warn("Handling message type {} not yet implemented {}",
327 msg.getType(), msg);
328 }
329 }
330
sangho6a0bb172015-02-05 12:24:48 -0800331 private synchronized Collection<OFFlowStatsEntry> publishFlowStats(Dpid dpid,
332 OFFlowStatsReply reply) {
alshabib64def642014-12-02 23:27:37 -0800333 //TODO: Get rid of synchronized
sangho6a0bb172015-02-05 12:24:48 -0800334 fullFlowStats.putAll(dpid, reply.getEntries());
alshabib64def642014-12-02 23:27:37 -0800335 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
sangho6a0bb172015-02-05 12:24:48 -0800336 return fullFlowStats.removeAll(dpid);
337 }
338 return null;
339 }
340
341 private synchronized Collection<OFGroupStatsEntry> publishGroupStats(Dpid dpid,
342 OFGroupStatsReply reply) {
343 //TODO: Get rid of synchronized
344 fullGroupStats.putAll(dpid, reply.getEntries());
345 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
346 return fullGroupStats.removeAll(dpid);
347 }
348 return null;
349 }
350
351 private synchronized Collection<OFGroupDescStatsEntry> publishGroupDescStats(Dpid dpid,
352 OFGroupDescStatsReply reply) {
353 //TODO: Get rid of synchronized
354 fullGroupDescStats.putAll(dpid, reply.getEntries());
355 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
356 return fullGroupDescStats.removeAll(dpid);
alshabib64def642014-12-02 23:27:37 -0800357 }
358 return null;
359 }
360
sangho538108b2015-04-08 14:29:20 -0700361 private synchronized Collection<OFPortStatsEntry> publishPortStats(Dpid dpid,
362 OFPortStatsReply reply) {
363 fullPortStats.putAll(dpid, reply.getEntries());
364 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
365 return fullPortStats.removeAll(dpid);
366 }
367 return null;
368 }
369
tom7ef8ff92014-09-17 13:08:06 -0700370 @Override
371 public void setRole(Dpid dpid, RoleState role) {
Yuta HIGUCHI79cbd1c2014-10-02 16:57:57 -0700372 final OpenFlowSwitch sw = getSwitch(dpid);
373 if (sw == null) {
374 log.debug("Switch not connected. Ignoring setRole({}, {})", dpid, role);
375 return;
376 }
377 sw.setRole(role);
tom7ef8ff92014-09-17 13:08:06 -0700378 }
379
380 /**
381 * Implementation of an OpenFlow Agent which is responsible for
382 * keeping track of connected switches and the state in which
383 * they are.
384 */
385 public class OpenFlowSwitchAgent implements OpenFlowAgent {
386
387 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
388 private final Lock switchLock = new ReentrantLock();
389
390 @Override
391 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib9eab22f2014-10-20 17:17:31 -0700392
tom7ef8ff92014-09-17 13:08:06 -0700393 if (connectedSwitches.get(dpid) != null) {
394 log.error("Trying to add connectedSwitch but found a previous "
395 + "value for dpid: {}", dpid);
396 return false;
397 } else {
Yuta HIGUCHIeb3f30b2014-10-22 11:34:49 -0700398 log.info("Added switch {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700399 connectedSwitches.put(dpid, sw);
alshabib8f1cf4a2014-09-17 14:44:48 -0700400 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700401 l.switchAdded(dpid);
402 }
403 return true;
404 }
405 }
406
407 @Override
408 public boolean validActivation(Dpid dpid) {
409 if (connectedSwitches.get(dpid) == null) {
410 log.error("Trying to activate switch but is not in "
411 + "connected switches: dpid {}. Aborting ..",
412 dpid);
413 return false;
414 }
415 if (activeMasterSwitches.get(dpid) != null ||
416 activeEqualSwitches.get(dpid) != null) {
417 log.error("Trying to activate switch but it is already "
418 + "activated: dpid {}. Found in activeMaster: {} "
419 + "Found in activeEqual: {}. Aborting ..", new Object[]{
420 dpid,
421 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
422 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
423 return false;
424 }
425 return true;
426 }
427
428
429 @Override
430 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
431 switchLock.lock();
432 try {
433 if (!validActivation(dpid)) {
434 return false;
435 }
436 activeMasterSwitches.put(dpid, sw);
437 return true;
438 } finally {
439 switchLock.unlock();
440 }
441 }
442
443 @Override
444 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
445 switchLock.lock();
446 try {
447 if (!validActivation(dpid)) {
448 return false;
449 }
450 activeEqualSwitches.put(dpid, sw);
451 log.info("Added Activated EQUAL Switch {}", dpid);
452 return true;
453 } finally {
454 switchLock.unlock();
455 }
456 }
457
458 @Override
459 public void transitionToMasterSwitch(Dpid dpid) {
460 switchLock.lock();
461 try {
462 if (activeMasterSwitches.containsKey(dpid)) {
463 return;
464 }
465 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
466 if (sw == null) {
467 sw = getSwitch(dpid);
468 if (sw == null) {
469 log.error("Transition to master called on sw {}, but switch "
470 + "was not found in controller-cache", dpid);
471 return;
472 }
473 }
474 log.info("Transitioned switch {} to MASTER", dpid);
475 activeMasterSwitches.put(dpid, sw);
476 } finally {
477 switchLock.unlock();
478 }
479 }
480
481
482 @Override
483 public void transitionToEqualSwitch(Dpid dpid) {
484 switchLock.lock();
485 try {
486 if (activeEqualSwitches.containsKey(dpid)) {
487 return;
488 }
489 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
490 if (sw == null) {
491 sw = getSwitch(dpid);
492 if (sw == null) {
493 log.error("Transition to equal called on sw {}, but switch "
494 + "was not found in controller-cache", dpid);
495 return;
496 }
497 }
498 log.info("Transitioned switch {} to EQUAL", dpid);
499 activeEqualSwitches.put(dpid, sw);
500 } finally {
501 switchLock.unlock();
502 }
503
504 }
505
506 @Override
507 public void removeConnectedSwitch(Dpid dpid) {
508 connectedSwitches.remove(dpid);
509 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
510 if (sw == null) {
Ayaka Koshibec4047702014-10-07 14:43:52 -0700511 log.warn("sw was null for {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700512 sw = activeEqualSwitches.remove(dpid);
513 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700514 for (OpenFlowSwitchListener l : ofSwitchListener) {
Ayaka Koshibec4047702014-10-07 14:43:52 -0700515 log.warn("removal for {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700516 l.switchRemoved(dpid);
517 }
518 }
519
520 @Override
521 public void processMessage(Dpid dpid, OFMessage m) {
522 processPacket(dpid, m);
523 }
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700524
525 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700526 public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response) {
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700527 for (OpenFlowSwitchListener l : ofSwitchListener) {
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700528 l.receivedRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700529 }
530 }
tom7ef8ff92014-09-17 13:08:06 -0700531 }
532
alshabib8f1cf4a2014-09-17 14:44:48 -0700533 private final class OFMessageHandler implements Runnable {
534
535 private final OFMessage msg;
536 private final Dpid dpid;
537
538 public OFMessageHandler(Dpid dpid, OFMessage msg) {
539 this.msg = msg;
540 this.dpid = dpid;
541 }
542
543 @Override
544 public void run() {
alshabibeec3a062014-09-17 18:01:26 -0700545 for (OpenFlowEventListener listener : ofEventListener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700546 listener.handleMessage(dpid, msg);
547 }
548 }
549
550 }
551
tom7ef8ff92014-09-17 13:08:06 -0700552}