blob: 8fcf789ffed7d3c1c7c7012b6daeca8b39e15454 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 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;
tom7ef8ff92014-09-17 13:08:06 -070026import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
28import org.onosproject.openflow.controller.Dpid;
29import org.onosproject.openflow.controller.OpenFlowController;
30import org.onosproject.openflow.controller.OpenFlowEventListener;
31import org.onosproject.openflow.controller.OpenFlowPacketContext;
32import org.onosproject.openflow.controller.OpenFlowSwitch;
33import org.onosproject.openflow.controller.OpenFlowSwitchListener;
34import org.onosproject.openflow.controller.PacketListener;
35import org.onosproject.openflow.controller.RoleState;
36import org.onosproject.openflow.controller.driver.OpenFlowAgent;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080037import org.osgi.service.component.ComponentContext;
Marc De Leenheer631ffce2014-10-28 16:29:07 -070038import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
39import org.projectfloodlight.openflow.protocol.OFExperimenter;
alshabib64def642014-12-02 23:27:37 -080040import org.projectfloodlight.openflow.protocol.OFFactories;
41import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
42import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
sangho6a0bb172015-02-05 12:24:48 -080043import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
44import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
45import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
46import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070047import org.projectfloodlight.openflow.protocol.OFMessage;
48import org.projectfloodlight.openflow.protocol.OFPacketIn;
Marc De Leenheer631ffce2014-10-28 16:29:07 -070049import org.projectfloodlight.openflow.protocol.OFPortDesc;
sangho538108b2015-04-08 14:29:20 -070050import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
51import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070052import org.projectfloodlight.openflow.protocol.OFPortStatus;
Ayaka Koshibe38594c22014-10-22 13:36:12 -070053import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib64def642014-12-02 23:27:37 -080054import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
tom7ef8ff92014-09-17 13:08:06 -070055import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
57
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080058import java.util.Collection;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080059import java.util.Dictionary;
60import java.util.HashMap;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080061import java.util.HashSet;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080062import java.util.Map;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080063import java.util.Set;
64import java.util.concurrent.ConcurrentHashMap;
65import java.util.concurrent.ExecutorService;
66import java.util.concurrent.Executors;
67import java.util.concurrent.locks.Lock;
68import java.util.concurrent.locks.ReentrantLock;
69
70import static org.onlab.util.Tools.groupedThreads;
tom7ef8ff92014-09-17 13:08:06 -070071
72@Component(immediate = true)
73@Service
74public class OpenFlowControllerImpl implements OpenFlowController {
75
76 private static final Logger log =
77 LoggerFactory.getLogger(OpenFlowControllerImpl.class);
78
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080079 private final ExecutorService executorMsgs =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080080 Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d"));
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080081
82 private final ExecutorService executorBarrier =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080083 Executors.newFixedThreadPool(4, groupedThreads("onos/of", "event-barrier-%d"));
alshabib8f1cf4a2014-09-17 14:44:48 -070084
tom7ef8ff92014-09-17 13:08:06 -070085 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
86 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
87 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
88 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
89 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
90 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
91
92 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
alshabib8f1cf4a2014-09-17 14:44:48 -070093 protected Set<OpenFlowSwitchListener> ofSwitchListener = new HashSet<>();
tom7ef8ff92014-09-17 13:08:06 -070094
95 protected Multimap<Integer, PacketListener> ofPacketListener =
96 ArrayListMultimap.create();
97
alshabibeec3a062014-09-17 18:01:26 -070098 protected Set<OpenFlowEventListener> ofEventListener = Sets.newHashSet();
tom7ef8ff92014-09-17 13:08:06 -070099
sangho6a0bb172015-02-05 12:24:48 -0800100 protected Multimap<Dpid, OFFlowStatsEntry> fullFlowStats =
101 ArrayListMultimap.create();
102
103 protected Multimap<Dpid, OFGroupStatsEntry> fullGroupStats =
104 ArrayListMultimap.create();
105
106 protected Multimap<Dpid, OFGroupDescStatsEntry> fullGroupDescStats =
alshabib64def642014-12-02 23:27:37 -0800107 ArrayListMultimap.create();
108
sangho538108b2015-04-08 14:29:20 -0700109 protected Multimap<Dpid, OFPortStatsEntry> fullPortStats =
110 ArrayListMultimap.create();
111
tom7ef8ff92014-09-17 13:08:06 -0700112 private final Controller ctrl = new Controller();
113
114 @Activate
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800115 public void activate(ComponentContext context) {
116 Map<String, String> properties = readComponentConfiguration(context);
117 ctrl.setConfigParams(properties);
tom7ef8ff92014-09-17 13:08:06 -0700118 ctrl.start(agent);
119 }
120
121 @Deactivate
122 public void deactivate() {
123 ctrl.stop();
124 }
125
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800126 /**
127 * Extracts properties from the component configuration context.
128 *
129 * @param context the component context
130 */
131 private Map<String, String> readComponentConfiguration(ComponentContext context) {
132 Dictionary<?, ?> properties = context.getProperties();
133 Map<String, String> outProperties = new HashMap<>();
134 try {
135 String strDpid = (String) properties.get("corsaDpid");
136 if (strDpid != null) {
137 outProperties.put("corsaDpid", strDpid);
138 }
139 } catch (ClassCastException e) {
140 return outProperties;
141 }
142 return outProperties;
143 }
144
145 @Modified
146 public void modified(ComponentContext context) {
147 // Blank @Modified method to catch modifications to the context.
148 // If no @Modified method exists, @Activate is called again
149 // when the context is modified.
150 }
151
tom7ef8ff92014-09-17 13:08:06 -0700152 @Override
153 public Iterable<OpenFlowSwitch> getSwitches() {
154 return connectedSwitches.values();
155 }
156
157 @Override
158 public Iterable<OpenFlowSwitch> getMasterSwitches() {
159 return activeMasterSwitches.values();
160 }
161
162 @Override
163 public Iterable<OpenFlowSwitch> getEqualSwitches() {
164 return activeEqualSwitches.values();
165 }
166
167 @Override
168 public OpenFlowSwitch getSwitch(Dpid dpid) {
169 return connectedSwitches.get(dpid);
170 }
171
172 @Override
173 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
174 return activeMasterSwitches.get(dpid);
175 }
176
177 @Override
178 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
179 return activeEqualSwitches.get(dpid);
180 }
181
182 @Override
183 public void addListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700184 if (!ofSwitchListener.contains(listener)) {
185 this.ofSwitchListener.add(listener);
tom7ef8ff92014-09-17 13:08:06 -0700186 }
187 }
188
189 @Override
190 public void removeListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700191 this.ofSwitchListener.remove(listener);
tom7ef8ff92014-09-17 13:08:06 -0700192 }
193
194 @Override
195 public void addPacketListener(int priority, PacketListener listener) {
196 ofPacketListener.put(priority, listener);
197 }
198
199 @Override
200 public void removePacketListener(PacketListener listener) {
201 ofPacketListener.values().remove(listener);
202 }
203
204 @Override
alshabibeec3a062014-09-17 18:01:26 -0700205 public void addEventListener(OpenFlowEventListener listener) {
206 ofEventListener.add(listener);
207 }
208
209 @Override
210 public void removeEventListener(OpenFlowEventListener listener) {
211 ofEventListener.remove(listener);
212 }
213
214 @Override
tom7ef8ff92014-09-17 13:08:06 -0700215 public void write(Dpid dpid, OFMessage msg) {
216 this.getSwitch(dpid).sendMsg(msg);
217 }
218
219 @Override
220 public void processPacket(Dpid dpid, OFMessage msg) {
sangho6a0bb172015-02-05 12:24:48 -0800221 Collection<OFFlowStatsEntry> flowStats;
222 Collection<OFGroupStatsEntry> groupStats;
223 Collection<OFGroupDescStatsEntry> groupDescStats;
sangho538108b2015-04-08 14:29:20 -0700224 Collection<OFPortStatsEntry> portStats;
sangho6a0bb172015-02-05 12:24:48 -0800225
tom7ef8ff92014-09-17 13:08:06 -0700226 switch (msg.getType()) {
227 case PORT_STATUS:
alshabib8f1cf4a2014-09-17 14:44:48 -0700228 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700229 l.portChanged(dpid, (OFPortStatus) msg);
230 }
231 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700232 case FEATURES_REPLY:
233 for (OpenFlowSwitchListener l : ofSwitchListener) {
234 l.switchChanged(dpid);
235 }
236 break;
tom7ef8ff92014-09-17 13:08:06 -0700237 case PACKET_IN:
238 OpenFlowPacketContext pktCtx = DefaultOpenFlowPacketContext
239 .packetContextFromPacketIn(this.getSwitch(dpid),
240 (OFPacketIn) msg);
241 for (PacketListener p : ofPacketListener.values()) {
242 p.handlePacket(pktCtx);
243 }
244 break;
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800245 // TODO: Consider using separate threadpool for sensitive messages.
246 // ie. Back to back error could cause us to starve.
247 case FLOW_REMOVED:
248 case ERROR:
249 executorMsgs.submit(new OFMessageHandler(dpid, msg));
250 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700251 case STATS_REPLY:
252 OFStatsReply reply = (OFStatsReply) msg;
sangho6a0bb172015-02-05 12:24:48 -0800253 switch (reply.getStatsType()) {
254 case PORT_DESC:
255 for (OpenFlowSwitchListener l : ofSwitchListener) {
256 l.switchChanged(dpid);
257 }
258 break;
259 case FLOW:
260 flowStats = publishFlowStats(dpid, (OFFlowStatsReply) reply);
261 if (flowStats != null) {
262 OFFlowStatsReply.Builder rep =
263 OFFactories.getFactory(msg.getVersion()).buildFlowStatsReply();
264 rep.setEntries(Lists.newLinkedList(flowStats));
265 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
266 }
267 break;
268 case GROUP:
269 groupStats = publishGroupStats(dpid, (OFGroupStatsReply) reply);
270 if (groupStats != null) {
271 OFGroupStatsReply.Builder rep =
272 OFFactories.getFactory(msg.getVersion()).buildGroupStatsReply();
273 rep.setEntries(Lists.newLinkedList(groupStats));
274 rep.setXid(reply.getXid());
275 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
276 }
277 break;
278 case GROUP_DESC:
279 groupDescStats = publishGroupDescStats(dpid,
280 (OFGroupDescStatsReply) reply);
281 if (groupDescStats != null) {
282 OFGroupDescStatsReply.Builder rep =
283 OFFactories.getFactory(msg.getVersion()).buildGroupDescStatsReply();
284 rep.setEntries(Lists.newLinkedList(groupDescStats));
285 rep.setXid(reply.getXid());
286 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
287 }
288 break;
sangho538108b2015-04-08 14:29:20 -0700289 case PORT:
290 executorMsgs.submit(new OFMessageHandler(dpid, reply));
291 break;
sangho6a0bb172015-02-05 12:24:48 -0800292 default:
293 log.warn("Unsupported stats type : {}", reply.getStatsType());
alshabib64def642014-12-02 23:27:37 -0800294 }
295 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700296 case BARRIER_REPLY:
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800297 executorBarrier.submit(new OFMessageHandler(dpid, msg));
alshabib8f1cf4a2014-09-17 14:44:48 -0700298 break;
Marc De Leenheer631ffce2014-10-28 16:29:07 -0700299 case EXPERIMENTER:
300 // Handle optical port stats
301 if (((OFExperimenter) msg).getExperimenter() == 0x748771) {
302 OFCircuitPortStatus circuitPortStatus = (OFCircuitPortStatus) msg;
303 OFPortStatus.Builder portStatus = this.getSwitch(dpid).factory().buildPortStatus();
304 OFPortDesc.Builder portDesc = this.getSwitch(dpid).factory().buildPortDesc();
305 portDesc.setPortNo(circuitPortStatus.getPortNo())
306 .setHwAddr(circuitPortStatus.getHwAddr())
307 .setName(circuitPortStatus.getName())
308 .setConfig(circuitPortStatus.getConfig())
309 .setState(circuitPortStatus.getState());
310 portStatus.setReason(circuitPortStatus.getReason()).setDesc(portDesc.build());
311 for (OpenFlowSwitchListener l : ofSwitchListener) {
312 l.portChanged(dpid, portStatus.build());
313 }
314 } else {
315 log.warn("Handling experimenter type {} not yet implemented",
316 ((OFExperimenter) msg).getExperimenter(), msg);
317 }
318 break;
tom7ef8ff92014-09-17 13:08:06 -0700319 default:
320 log.warn("Handling message type {} not yet implemented {}",
321 msg.getType(), msg);
322 }
323 }
324
sangho6a0bb172015-02-05 12:24:48 -0800325 private synchronized Collection<OFFlowStatsEntry> publishFlowStats(Dpid dpid,
326 OFFlowStatsReply reply) {
alshabib64def642014-12-02 23:27:37 -0800327 //TODO: Get rid of synchronized
sangho6a0bb172015-02-05 12:24:48 -0800328 fullFlowStats.putAll(dpid, reply.getEntries());
alshabib64def642014-12-02 23:27:37 -0800329 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
sangho6a0bb172015-02-05 12:24:48 -0800330 return fullFlowStats.removeAll(dpid);
331 }
332 return null;
333 }
334
335 private synchronized Collection<OFGroupStatsEntry> publishGroupStats(Dpid dpid,
336 OFGroupStatsReply reply) {
337 //TODO: Get rid of synchronized
338 fullGroupStats.putAll(dpid, reply.getEntries());
339 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
340 return fullGroupStats.removeAll(dpid);
341 }
342 return null;
343 }
344
345 private synchronized Collection<OFGroupDescStatsEntry> publishGroupDescStats(Dpid dpid,
346 OFGroupDescStatsReply reply) {
347 //TODO: Get rid of synchronized
348 fullGroupDescStats.putAll(dpid, reply.getEntries());
349 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
350 return fullGroupDescStats.removeAll(dpid);
alshabib64def642014-12-02 23:27:37 -0800351 }
352 return null;
353 }
354
sangho538108b2015-04-08 14:29:20 -0700355 private synchronized Collection<OFPortStatsEntry> publishPortStats(Dpid dpid,
356 OFPortStatsReply reply) {
357 fullPortStats.putAll(dpid, reply.getEntries());
358 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
359 return fullPortStats.removeAll(dpid);
360 }
361 return null;
362 }
363
tom7ef8ff92014-09-17 13:08:06 -0700364 @Override
365 public void setRole(Dpid dpid, RoleState role) {
Yuta HIGUCHI79cbd1c2014-10-02 16:57:57 -0700366 final OpenFlowSwitch sw = getSwitch(dpid);
367 if (sw == null) {
368 log.debug("Switch not connected. Ignoring setRole({}, {})", dpid, role);
369 return;
370 }
371 sw.setRole(role);
tom7ef8ff92014-09-17 13:08:06 -0700372 }
373
374 /**
375 * Implementation of an OpenFlow Agent which is responsible for
376 * keeping track of connected switches and the state in which
377 * they are.
378 */
379 public class OpenFlowSwitchAgent implements OpenFlowAgent {
380
381 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
382 private final Lock switchLock = new ReentrantLock();
383
384 @Override
385 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib9eab22f2014-10-20 17:17:31 -0700386
tom7ef8ff92014-09-17 13:08:06 -0700387 if (connectedSwitches.get(dpid) != null) {
388 log.error("Trying to add connectedSwitch but found a previous "
389 + "value for dpid: {}", dpid);
390 return false;
391 } else {
Yuta HIGUCHIeb3f30b2014-10-22 11:34:49 -0700392 log.info("Added switch {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700393 connectedSwitches.put(dpid, sw);
alshabib8f1cf4a2014-09-17 14:44:48 -0700394 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700395 l.switchAdded(dpid);
396 }
397 return true;
398 }
399 }
400
401 @Override
402 public boolean validActivation(Dpid dpid) {
403 if (connectedSwitches.get(dpid) == null) {
404 log.error("Trying to activate switch but is not in "
405 + "connected switches: dpid {}. Aborting ..",
406 dpid);
407 return false;
408 }
409 if (activeMasterSwitches.get(dpid) != null ||
410 activeEqualSwitches.get(dpid) != null) {
411 log.error("Trying to activate switch but it is already "
412 + "activated: dpid {}. Found in activeMaster: {} "
413 + "Found in activeEqual: {}. Aborting ..", new Object[]{
414 dpid,
415 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
416 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
417 return false;
418 }
419 return true;
420 }
421
422
423 @Override
424 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
425 switchLock.lock();
426 try {
427 if (!validActivation(dpid)) {
428 return false;
429 }
430 activeMasterSwitches.put(dpid, sw);
431 return true;
432 } finally {
433 switchLock.unlock();
434 }
435 }
436
437 @Override
438 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
439 switchLock.lock();
440 try {
441 if (!validActivation(dpid)) {
442 return false;
443 }
444 activeEqualSwitches.put(dpid, sw);
445 log.info("Added Activated EQUAL Switch {}", dpid);
446 return true;
447 } finally {
448 switchLock.unlock();
449 }
450 }
451
452 @Override
453 public void transitionToMasterSwitch(Dpid dpid) {
454 switchLock.lock();
455 try {
456 if (activeMasterSwitches.containsKey(dpid)) {
457 return;
458 }
459 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
460 if (sw == null) {
461 sw = getSwitch(dpid);
462 if (sw == null) {
463 log.error("Transition to master called on sw {}, but switch "
464 + "was not found in controller-cache", dpid);
465 return;
466 }
467 }
468 log.info("Transitioned switch {} to MASTER", dpid);
469 activeMasterSwitches.put(dpid, sw);
470 } finally {
471 switchLock.unlock();
472 }
473 }
474
475
476 @Override
477 public void transitionToEqualSwitch(Dpid dpid) {
478 switchLock.lock();
479 try {
480 if (activeEqualSwitches.containsKey(dpid)) {
481 return;
482 }
483 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
484 if (sw == null) {
485 sw = getSwitch(dpid);
486 if (sw == null) {
487 log.error("Transition to equal called on sw {}, but switch "
488 + "was not found in controller-cache", dpid);
489 return;
490 }
491 }
492 log.info("Transitioned switch {} to EQUAL", dpid);
493 activeEqualSwitches.put(dpid, sw);
494 } finally {
495 switchLock.unlock();
496 }
497
498 }
499
500 @Override
501 public void removeConnectedSwitch(Dpid dpid) {
502 connectedSwitches.remove(dpid);
503 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
504 if (sw == null) {
Ayaka Koshibec4047702014-10-07 14:43:52 -0700505 log.warn("sw was null for {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700506 sw = activeEqualSwitches.remove(dpid);
507 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700508 for (OpenFlowSwitchListener l : ofSwitchListener) {
Ayaka Koshibec4047702014-10-07 14:43:52 -0700509 log.warn("removal for {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700510 l.switchRemoved(dpid);
511 }
512 }
513
514 @Override
515 public void processMessage(Dpid dpid, OFMessage m) {
516 processPacket(dpid, m);
517 }
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700518
519 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700520 public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response) {
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700521 for (OpenFlowSwitchListener l : ofSwitchListener) {
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700522 l.receivedRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700523 }
524 }
tom7ef8ff92014-09-17 13:08:06 -0700525 }
526
alshabib8f1cf4a2014-09-17 14:44:48 -0700527 private final class OFMessageHandler implements Runnable {
528
529 private final OFMessage msg;
530 private final Dpid dpid;
531
532 public OFMessageHandler(Dpid dpid, OFMessage msg) {
533 this.msg = msg;
534 this.dpid = dpid;
535 }
536
537 @Override
538 public void run() {
alshabibeec3a062014-09-17 18:01:26 -0700539 for (OpenFlowEventListener listener : ofEventListener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700540 listener.handleMessage(dpid, msg);
541 }
542 }
543
544 }
545
tom7ef8ff92014-09-17 13:08:06 -0700546}