blob: 416abd3ba57e3b34271a2dba6c42aea0c3edea41 [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;
Thomas Vachuska3358af22015-05-19 18:40:34 -070028import org.onosproject.net.driver.DefaultDriverProviderService;
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;
Jonathan Hartbbd91d42015-02-27 11:18:04 -080064import java.util.Map;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080065import java.util.Set;
66import java.util.concurrent.ConcurrentHashMap;
Jonathan Hart6d44d192015-05-11 18:01:19 -070067import java.util.concurrent.CopyOnWriteArraySet;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080068import 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
Thomas Vachuska3358af22015-05-19 18:40:34 -070085 // References exists merely for sequencing purpose to assure drivers are loaded
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected DefaultDriverProviderService defaultDriverProviderService;
88
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080089 private final ExecutorService executorMsgs =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080090 Executors.newFixedThreadPool(32, groupedThreads("onos/of", "event-stats-%d"));
Pavlin Radoslavov369c6432014-12-03 16:25:14 -080091
92 private final ExecutorService executorBarrier =
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080093 Executors.newFixedThreadPool(4, groupedThreads("onos/of", "event-barrier-%d"));
alshabib8f1cf4a2014-09-17 14:44:48 -070094
tom7ef8ff92014-09-17 13:08:06 -070095 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
Jonathan Hart6d44d192015-05-11 18:01:19 -070096 new ConcurrentHashMap<>();
tom7ef8ff92014-09-17 13:08:06 -070097 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
Jonathan Hart6d44d192015-05-11 18:01:19 -070098 new ConcurrentHashMap<>();
tom7ef8ff92014-09-17 13:08:06 -070099 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
Jonathan Hart6d44d192015-05-11 18:01:19 -0700100 new ConcurrentHashMap<>();
tom7ef8ff92014-09-17 13:08:06 -0700101
102 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
Jonathan Hart6d44d192015-05-11 18:01:19 -0700103 protected Set<OpenFlowSwitchListener> ofSwitchListener = new CopyOnWriteArraySet<>();
tom7ef8ff92014-09-17 13:08:06 -0700104
105 protected Multimap<Integer, PacketListener> ofPacketListener =
106 ArrayListMultimap.create();
107
Jonathan Hart6d44d192015-05-11 18:01:19 -0700108 protected Set<OpenFlowEventListener> ofEventListener = new CopyOnWriteArraySet<>();
tom7ef8ff92014-09-17 13:08:06 -0700109
sangho6a0bb172015-02-05 12:24:48 -0800110 protected Multimap<Dpid, OFFlowStatsEntry> fullFlowStats =
111 ArrayListMultimap.create();
112
113 protected Multimap<Dpid, OFGroupStatsEntry> fullGroupStats =
114 ArrayListMultimap.create();
115
116 protected Multimap<Dpid, OFGroupDescStatsEntry> fullGroupDescStats =
alshabib64def642014-12-02 23:27:37 -0800117 ArrayListMultimap.create();
118
sangho538108b2015-04-08 14:29:20 -0700119 protected Multimap<Dpid, OFPortStatsEntry> fullPortStats =
120 ArrayListMultimap.create();
121
tom7ef8ff92014-09-17 13:08:06 -0700122 private final Controller ctrl = new Controller();
123
124 @Activate
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800125 public void activate(ComponentContext context) {
126 Map<String, String> properties = readComponentConfiguration(context);
127 ctrl.setConfigParams(properties);
alshabibb452fd72015-04-22 20:46:20 -0700128 ctrl.start(agent, driverService);
tom7ef8ff92014-09-17 13:08:06 -0700129 }
130
131 @Deactivate
132 public void deactivate() {
133 ctrl.stop();
134 }
135
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800136 /**
137 * Extracts properties from the component configuration context.
138 *
139 * @param context the component context
140 */
141 private Map<String, String> readComponentConfiguration(ComponentContext context) {
142 Dictionary<?, ?> properties = context.getProperties();
143 Map<String, String> outProperties = new HashMap<>();
144 try {
145 String strDpid = (String) properties.get("corsaDpid");
146 if (strDpid != null) {
147 outProperties.put("corsaDpid", strDpid);
148 }
149 } catch (ClassCastException e) {
150 return outProperties;
151 }
152 return outProperties;
153 }
154
155 @Modified
156 public void modified(ComponentContext context) {
157 // Blank @Modified method to catch modifications to the context.
158 // If no @Modified method exists, @Activate is called again
159 // when the context is modified.
160 }
161
tom7ef8ff92014-09-17 13:08:06 -0700162 @Override
163 public Iterable<OpenFlowSwitch> getSwitches() {
164 return connectedSwitches.values();
165 }
166
167 @Override
168 public Iterable<OpenFlowSwitch> getMasterSwitches() {
169 return activeMasterSwitches.values();
170 }
171
172 @Override
173 public Iterable<OpenFlowSwitch> getEqualSwitches() {
174 return activeEqualSwitches.values();
175 }
176
177 @Override
178 public OpenFlowSwitch getSwitch(Dpid dpid) {
179 return connectedSwitches.get(dpid);
180 }
181
182 @Override
183 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
184 return activeMasterSwitches.get(dpid);
185 }
186
187 @Override
188 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
189 return activeEqualSwitches.get(dpid);
190 }
191
192 @Override
193 public void addListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700194 if (!ofSwitchListener.contains(listener)) {
195 this.ofSwitchListener.add(listener);
tom7ef8ff92014-09-17 13:08:06 -0700196 }
197 }
198
199 @Override
200 public void removeListener(OpenFlowSwitchListener listener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700201 this.ofSwitchListener.remove(listener);
tom7ef8ff92014-09-17 13:08:06 -0700202 }
203
204 @Override
205 public void addPacketListener(int priority, PacketListener listener) {
206 ofPacketListener.put(priority, listener);
207 }
208
209 @Override
210 public void removePacketListener(PacketListener listener) {
211 ofPacketListener.values().remove(listener);
212 }
213
214 @Override
alshabibeec3a062014-09-17 18:01:26 -0700215 public void addEventListener(OpenFlowEventListener listener) {
216 ofEventListener.add(listener);
217 }
218
219 @Override
220 public void removeEventListener(OpenFlowEventListener listener) {
221 ofEventListener.remove(listener);
222 }
223
224 @Override
tom7ef8ff92014-09-17 13:08:06 -0700225 public void write(Dpid dpid, OFMessage msg) {
226 this.getSwitch(dpid).sendMsg(msg);
227 }
228
229 @Override
230 public void processPacket(Dpid dpid, OFMessage msg) {
sangho6a0bb172015-02-05 12:24:48 -0800231 Collection<OFFlowStatsEntry> flowStats;
232 Collection<OFGroupStatsEntry> groupStats;
233 Collection<OFGroupDescStatsEntry> groupDescStats;
sangho538108b2015-04-08 14:29:20 -0700234 Collection<OFPortStatsEntry> portStats;
sangho6a0bb172015-02-05 12:24:48 -0800235
tom7ef8ff92014-09-17 13:08:06 -0700236 switch (msg.getType()) {
237 case PORT_STATUS:
alshabib8f1cf4a2014-09-17 14:44:48 -0700238 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700239 l.portChanged(dpid, (OFPortStatus) msg);
240 }
241 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700242 case FEATURES_REPLY:
243 for (OpenFlowSwitchListener l : ofSwitchListener) {
244 l.switchChanged(dpid);
245 }
246 break;
tom7ef8ff92014-09-17 13:08:06 -0700247 case PACKET_IN:
248 OpenFlowPacketContext pktCtx = DefaultOpenFlowPacketContext
249 .packetContextFromPacketIn(this.getSwitch(dpid),
250 (OFPacketIn) msg);
251 for (PacketListener p : ofPacketListener.values()) {
252 p.handlePacket(pktCtx);
253 }
254 break;
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800255 // TODO: Consider using separate threadpool for sensitive messages.
256 // ie. Back to back error could cause us to starve.
257 case FLOW_REMOVED:
258 case ERROR:
259 executorMsgs.submit(new OFMessageHandler(dpid, msg));
260 break;
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700261 case STATS_REPLY:
262 OFStatsReply reply = (OFStatsReply) msg;
sangho6a0bb172015-02-05 12:24:48 -0800263 switch (reply.getStatsType()) {
264 case PORT_DESC:
265 for (OpenFlowSwitchListener l : ofSwitchListener) {
266 l.switchChanged(dpid);
267 }
268 break;
269 case FLOW:
270 flowStats = publishFlowStats(dpid, (OFFlowStatsReply) reply);
271 if (flowStats != null) {
272 OFFlowStatsReply.Builder rep =
273 OFFactories.getFactory(msg.getVersion()).buildFlowStatsReply();
274 rep.setEntries(Lists.newLinkedList(flowStats));
275 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
276 }
277 break;
278 case GROUP:
279 groupStats = publishGroupStats(dpid, (OFGroupStatsReply) reply);
280 if (groupStats != null) {
281 OFGroupStatsReply.Builder rep =
282 OFFactories.getFactory(msg.getVersion()).buildGroupStatsReply();
283 rep.setEntries(Lists.newLinkedList(groupStats));
284 rep.setXid(reply.getXid());
285 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
286 }
287 break;
288 case GROUP_DESC:
289 groupDescStats = publishGroupDescStats(dpid,
290 (OFGroupDescStatsReply) reply);
291 if (groupDescStats != null) {
292 OFGroupDescStatsReply.Builder rep =
293 OFFactories.getFactory(msg.getVersion()).buildGroupDescStatsReply();
294 rep.setEntries(Lists.newLinkedList(groupDescStats));
295 rep.setXid(reply.getXid());
296 executorMsgs.submit(new OFMessageHandler(dpid, rep.build()));
297 }
298 break;
sangho538108b2015-04-08 14:29:20 -0700299 case PORT:
300 executorMsgs.submit(new OFMessageHandler(dpid, reply));
301 break;
sangho6a0bb172015-02-05 12:24:48 -0800302 default:
303 log.warn("Unsupported stats type : {}", reply.getStatsType());
alshabib64def642014-12-02 23:27:37 -0800304 }
305 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700306 case BARRIER_REPLY:
Pavlin Radoslavov369c6432014-12-03 16:25:14 -0800307 executorBarrier.submit(new OFMessageHandler(dpid, msg));
alshabib8f1cf4a2014-09-17 14:44:48 -0700308 break;
Marc De Leenheer631ffce2014-10-28 16:29:07 -0700309 case EXPERIMENTER:
310 // Handle optical port stats
311 if (((OFExperimenter) msg).getExperimenter() == 0x748771) {
312 OFCircuitPortStatus circuitPortStatus = (OFCircuitPortStatus) msg;
313 OFPortStatus.Builder portStatus = this.getSwitch(dpid).factory().buildPortStatus();
314 OFPortDesc.Builder portDesc = this.getSwitch(dpid).factory().buildPortDesc();
315 portDesc.setPortNo(circuitPortStatus.getPortNo())
316 .setHwAddr(circuitPortStatus.getHwAddr())
317 .setName(circuitPortStatus.getName())
318 .setConfig(circuitPortStatus.getConfig())
319 .setState(circuitPortStatus.getState());
320 portStatus.setReason(circuitPortStatus.getReason()).setDesc(portDesc.build());
321 for (OpenFlowSwitchListener l : ofSwitchListener) {
322 l.portChanged(dpid, portStatus.build());
323 }
324 } else {
325 log.warn("Handling experimenter type {} not yet implemented",
326 ((OFExperimenter) msg).getExperimenter(), msg);
327 }
328 break;
tom7ef8ff92014-09-17 13:08:06 -0700329 default:
330 log.warn("Handling message type {} not yet implemented {}",
331 msg.getType(), msg);
332 }
333 }
334
sangho6a0bb172015-02-05 12:24:48 -0800335 private synchronized Collection<OFFlowStatsEntry> publishFlowStats(Dpid dpid,
336 OFFlowStatsReply reply) {
alshabib64def642014-12-02 23:27:37 -0800337 //TODO: Get rid of synchronized
sangho6a0bb172015-02-05 12:24:48 -0800338 fullFlowStats.putAll(dpid, reply.getEntries());
alshabib64def642014-12-02 23:27:37 -0800339 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
sangho6a0bb172015-02-05 12:24:48 -0800340 return fullFlowStats.removeAll(dpid);
341 }
342 return null;
343 }
344
345 private synchronized Collection<OFGroupStatsEntry> publishGroupStats(Dpid dpid,
346 OFGroupStatsReply reply) {
347 //TODO: Get rid of synchronized
348 fullGroupStats.putAll(dpid, reply.getEntries());
349 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
350 return fullGroupStats.removeAll(dpid);
351 }
352 return null;
353 }
354
355 private synchronized Collection<OFGroupDescStatsEntry> publishGroupDescStats(Dpid dpid,
356 OFGroupDescStatsReply reply) {
357 //TODO: Get rid of synchronized
358 fullGroupDescStats.putAll(dpid, reply.getEntries());
359 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
360 return fullGroupDescStats.removeAll(dpid);
alshabib64def642014-12-02 23:27:37 -0800361 }
362 return null;
363 }
364
sangho538108b2015-04-08 14:29:20 -0700365 private synchronized Collection<OFPortStatsEntry> publishPortStats(Dpid dpid,
366 OFPortStatsReply reply) {
367 fullPortStats.putAll(dpid, reply.getEntries());
368 if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
369 return fullPortStats.removeAll(dpid);
370 }
371 return null;
372 }
373
tom7ef8ff92014-09-17 13:08:06 -0700374 @Override
375 public void setRole(Dpid dpid, RoleState role) {
Yuta HIGUCHI79cbd1c2014-10-02 16:57:57 -0700376 final OpenFlowSwitch sw = getSwitch(dpid);
377 if (sw == null) {
378 log.debug("Switch not connected. Ignoring setRole({}, {})", dpid, role);
379 return;
380 }
381 sw.setRole(role);
tom7ef8ff92014-09-17 13:08:06 -0700382 }
383
384 /**
385 * Implementation of an OpenFlow Agent which is responsible for
386 * keeping track of connected switches and the state in which
387 * they are.
388 */
389 public class OpenFlowSwitchAgent implements OpenFlowAgent {
390
391 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
392 private final Lock switchLock = new ReentrantLock();
393
394 @Override
395 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib9eab22f2014-10-20 17:17:31 -0700396
tom7ef8ff92014-09-17 13:08:06 -0700397 if (connectedSwitches.get(dpid) != null) {
398 log.error("Trying to add connectedSwitch but found a previous "
399 + "value for dpid: {}", dpid);
400 return false;
401 } else {
Yuta HIGUCHIeb3f30b2014-10-22 11:34:49 -0700402 log.info("Added switch {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700403 connectedSwitches.put(dpid, sw);
alshabib8f1cf4a2014-09-17 14:44:48 -0700404 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700405 l.switchAdded(dpid);
406 }
407 return true;
408 }
409 }
410
411 @Override
412 public boolean validActivation(Dpid dpid) {
413 if (connectedSwitches.get(dpid) == null) {
414 log.error("Trying to activate switch but is not in "
415 + "connected switches: dpid {}. Aborting ..",
416 dpid);
417 return false;
418 }
419 if (activeMasterSwitches.get(dpid) != null ||
420 activeEqualSwitches.get(dpid) != null) {
421 log.error("Trying to activate switch but it is already "
422 + "activated: dpid {}. Found in activeMaster: {} "
423 + "Found in activeEqual: {}. Aborting ..", new Object[]{
424 dpid,
425 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
426 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
427 return false;
428 }
429 return true;
430 }
431
432
433 @Override
434 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
435 switchLock.lock();
436 try {
437 if (!validActivation(dpid)) {
438 return false;
439 }
440 activeMasterSwitches.put(dpid, sw);
441 return true;
442 } finally {
443 switchLock.unlock();
444 }
445 }
446
447 @Override
448 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
449 switchLock.lock();
450 try {
451 if (!validActivation(dpid)) {
452 return false;
453 }
454 activeEqualSwitches.put(dpid, sw);
455 log.info("Added Activated EQUAL Switch {}", dpid);
456 return true;
457 } finally {
458 switchLock.unlock();
459 }
460 }
461
462 @Override
463 public void transitionToMasterSwitch(Dpid dpid) {
464 switchLock.lock();
465 try {
466 if (activeMasterSwitches.containsKey(dpid)) {
467 return;
468 }
469 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
470 if (sw == null) {
471 sw = getSwitch(dpid);
472 if (sw == null) {
473 log.error("Transition to master called on sw {}, but switch "
474 + "was not found in controller-cache", dpid);
475 return;
476 }
477 }
478 log.info("Transitioned switch {} to MASTER", dpid);
479 activeMasterSwitches.put(dpid, sw);
480 } finally {
481 switchLock.unlock();
482 }
483 }
484
485
486 @Override
487 public void transitionToEqualSwitch(Dpid dpid) {
488 switchLock.lock();
489 try {
490 if (activeEqualSwitches.containsKey(dpid)) {
491 return;
492 }
493 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
494 if (sw == null) {
495 sw = getSwitch(dpid);
496 if (sw == null) {
497 log.error("Transition to equal called on sw {}, but switch "
498 + "was not found in controller-cache", dpid);
499 return;
500 }
501 }
502 log.info("Transitioned switch {} to EQUAL", dpid);
503 activeEqualSwitches.put(dpid, sw);
504 } finally {
505 switchLock.unlock();
506 }
507
508 }
509
510 @Override
511 public void removeConnectedSwitch(Dpid dpid) {
512 connectedSwitches.remove(dpid);
513 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
514 if (sw == null) {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700515 log.debug("sw was null for {}", dpid);
tom7ef8ff92014-09-17 13:08:06 -0700516 sw = activeEqualSwitches.remove(dpid);
517 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700518 for (OpenFlowSwitchListener l : ofSwitchListener) {
tom7ef8ff92014-09-17 13:08:06 -0700519 l.switchRemoved(dpid);
520 }
521 }
522
523 @Override
524 public void processMessage(Dpid dpid, OFMessage m) {
525 processPacket(dpid, m);
526 }
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700527
528 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700529 public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response) {
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700530 for (OpenFlowSwitchListener l : ofSwitchListener) {
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700531 l.receivedRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700532 }
533 }
tom7ef8ff92014-09-17 13:08:06 -0700534 }
535
alshabib8f1cf4a2014-09-17 14:44:48 -0700536 private final class OFMessageHandler implements Runnable {
537
538 private final OFMessage msg;
539 private final Dpid dpid;
540
541 public OFMessageHandler(Dpid dpid, OFMessage msg) {
542 this.msg = msg;
543 this.dpid = dpid;
544 }
545
546 @Override
547 public void run() {
alshabibeec3a062014-09-17 18:01:26 -0700548 for (OpenFlowEventListener listener : ofEventListener) {
alshabib8f1cf4a2014-09-17 14:44:48 -0700549 listener.handleMessage(dpid, msg);
550 }
551 }
552
553 }
554
tom7ef8ff92014-09-17 13:08:06 -0700555}