blob: a877a668e299efd9b22c3d890ec3af4a08b4c7e9 [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
tom7ef8ff92014-09-17 13:08:06 -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
tom7ef8ff92014-09-17 13:08:06 -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 */
tom7ef8ff92014-09-17 13:08:06 -070016
Brian O'Connorabafb502014-12-02 22:26:20 -080017package org.onosproject.openflow.controller.driver;
tom7ef8ff92014-09-17 13:08:06 -070018
Jian Li152b8852015-12-07 14:47:25 -080019import static org.onlab.util.Tools.groupedThreads;
20
Brian O'Connore755caa2015-11-16 16:43:09 -080021import com.google.common.collect.Lists;
tom7ef8ff92014-09-17 13:08:06 -070022import org.jboss.netty.channel.Channel;
Ray Milkeye53f1712015-01-16 09:17:16 -080023import org.onlab.packet.IpAddress;
Marc De Leenheerb9311372015-07-09 11:36:49 -070024import org.onosproject.net.Device;
alshabibb452fd72015-04-22 20:46:20 -070025import org.onosproject.net.driver.AbstractHandlerBehaviour;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.openflow.controller.Dpid;
Jian Li152b8852015-12-07 14:47:25 -080027import org.onosproject.openflow.controller.OpenFlowEventListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.openflow.controller.RoleState;
Jian Li152b8852015-12-07 14:47:25 -080029
tom7ef8ff92014-09-17 13:08:06 -070030import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070031import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
tom7ef8ff92014-09-17 13:08:06 -070032import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
tom7ef8ff92014-09-17 13:08:06 -070033import org.projectfloodlight.openflow.protocol.OFVersion;
Jian Li152b8852015-12-07 14:47:25 -080034import org.projectfloodlight.openflow.protocol.OFMessage;
35import org.projectfloodlight.openflow.protocol.OFType;
36import org.projectfloodlight.openflow.protocol.OFFactories;
37import org.projectfloodlight.openflow.protocol.OFPortDesc;
38import org.projectfloodlight.openflow.protocol.OFExperimenter;
39import org.projectfloodlight.openflow.protocol.OFErrorMsg;
40import org.projectfloodlight.openflow.protocol.OFRoleRequest;
41import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleRequest;
42import org.projectfloodlight.openflow.protocol.OFPortStatus;
43import org.projectfloodlight.openflow.protocol.OFFactory;
44import org.projectfloodlight.openflow.protocol.OFRoleReply;
45
tom7ef8ff92014-09-17 13:08:06 -070046import org.slf4j.Logger;
47import org.slf4j.LoggerFactory;
48
Thomas Vachuska1c681d72015-05-18 14:58:53 -070049import java.io.IOException;
50import java.net.InetSocketAddress;
51import java.net.SocketAddress;
52import java.util.ArrayList;
53import java.util.Collections;
54import java.util.List;
Jian Li152b8852015-12-07 14:47:25 -080055import java.util.Set;
56import java.util.concurrent.CopyOnWriteArraySet;
57import java.util.concurrent.ExecutorService;
58import java.util.concurrent.Executors;
Thomas Vachuska1c681d72015-05-18 14:58:53 -070059import java.util.concurrent.atomic.AtomicInteger;
Brian O'Connore755caa2015-11-16 16:43:09 -080060import java.util.concurrent.atomic.AtomicReference;
Thomas Vachuska1c681d72015-05-18 14:58:53 -070061import java.util.stream.Collectors;
62
tom7ef8ff92014-09-17 13:08:06 -070063/**
64 * An abstract representation of an OpenFlow switch. Can be extended by others
65 * to serve as a base for their vendor specific representation of a switch.
66 */
alshabibb452fd72015-04-22 20:46:20 -070067public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
68 implements OpenFlowSwitchDriver {
tom7ef8ff92014-09-17 13:08:06 -070069
Yuta HIGUCHIf5416d82014-10-24 21:17:40 -070070 protected final Logger log = LoggerFactory.getLogger(getClass());
tom7ef8ff92014-09-17 13:08:06 -070071
alshabibb452fd72015-04-22 20:46:20 -070072 private Channel channel;
Ray Milkeye53f1712015-01-16 09:17:16 -080073 protected String channelId;
tom7ef8ff92014-09-17 13:08:06 -070074
75 private boolean connected;
76 protected boolean startDriverHandshakeCalled = false;
alshabibb452fd72015-04-22 20:46:20 -070077 private Dpid dpid;
tom7ef8ff92014-09-17 13:08:06 -070078 private OpenFlowAgent agent;
79 private final AtomicInteger xidCounter = new AtomicInteger(0);
80
81 private OFVersion ofVersion;
82
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070083 protected List<OFPortDescStatsReply> ports = new ArrayList<>();
tom7ef8ff92014-09-17 13:08:06 -070084
85 protected boolean tableFull;
86
87 private RoleHandler roleMan;
88
Brian O'Connore755caa2015-11-16 16:43:09 -080089 // TODO this is accessed from multiple threads, but volatile may have performance implications
90 protected volatile RoleState role;
tom7ef8ff92014-09-17 13:08:06 -070091
92 protected OFFeaturesReply features;
93 protected OFDescStatsReply desc;
94
Jian Li152b8852015-12-07 14:47:25 -080095 protected Set<OpenFlowEventListener> ofEventListener = new CopyOnWriteArraySet<>();
96
97 protected ExecutorService executorMsgs =
98 Executors.newFixedThreadPool(2, groupedThreads("onos/of", "ctrl-msg-stats-%d"));
99
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800100 // messagesPendingMastership is used as synchronization variable for
101 // all mastership related changes. In this block, mastership (including
102 // role update) will have either occurred or not.
Brian O'Connore755caa2015-11-16 16:43:09 -0800103 private final AtomicReference<List<OFMessage>> messagesPendingMastership
104 = new AtomicReference<>();
Charles Chan5b7ec342015-10-18 20:55:41 -0700105
alshabibb452fd72015-04-22 20:46:20 -0700106 @Override
107 public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
tom7ef8ff92014-09-17 13:08:06 -0700108 this.dpid = dpid;
109 this.desc = desc;
alshabibb452fd72015-04-22 20:46:20 -0700110 this.ofVersion = ofv;
tom7ef8ff92014-09-17 13:08:06 -0700111 }
112
113 //************************
114 // Channel related
115 //************************
116
117 @Override
118 public final void disconnectSwitch() {
Charles Chanecfdfb72015-11-24 19:05:50 -0800119 setConnected(false);
tom7ef8ff92014-09-17 13:08:06 -0700120 this.channel.close();
121 }
122
123 @Override
Charles Chan5b7ec342015-10-18 20:55:41 -0700124 public void sendMsg(OFMessage msg) {
125 this.sendMsg(Collections.singletonList(msg));
tom7ef8ff92014-09-17 13:08:06 -0700126 }
127
128 @Override
129 public final void sendMsg(List<OFMessage> msgs) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800130 /*
131 It is possible that in this block, we transition to SLAVE/EQUAL.
132 If this is the case, the supplied messages will race with the
133 RoleRequest message, and they could be rejected by the switch.
134 In the interest of performance, we will not protect this block with
135 a synchronization primitive, because the message would have just been
136 dropped anyway.
137 */
138 if (role == RoleState.MASTER) {
139 // fast path send when we are master
140
141 sendMsgsOnChannel(msgs);
142 return;
143 }
144 // check to see if mastership transition is in progress
145 synchronized (messagesPendingMastership) {
146 /*
147 messagesPendingMastership is used as synchronization variable for
148 all mastership related changes. In this block, mastership (including
149 role update) will have either occurred or not.
150 */
151 if (role == RoleState.MASTER) {
152 // transition to MASTER complete, send messages
153 sendMsgsOnChannel(msgs);
154 return;
155 }
156
157 List<OFMessage> messages = messagesPendingMastership.get();
158 if (messages != null) {
159 // we are transitioning to MASTER, so add messages to queue
160 messages.addAll(msgs);
161 log.debug("Enqueue message for switch {}. queue size after is {}",
162 dpid, messages.size());
163 } else {
164 // not transitioning to MASTER
165 log.warn("Dropping message for switch {} (role: {}, connected: {}): {}",
166 dpid, role, channel.isConnected(), msgs);
167 }
168 }
Jian Li152b8852015-12-07 14:47:25 -0800169
170 // listen to outgoing control messages
171 msgs.forEach(m -> {
172 if (m.getType() == OFType.PACKET_OUT ||
173 m.getType() == OFType.FLOW_MOD ||
174 m.getType() == OFType.STATS_REQUEST) {
175 executorMsgs.submit(new OFMessageHandler(dpid, m));
176 }
177 });
Brian O'Connore755caa2015-11-16 16:43:09 -0800178 }
179
180 private void sendMsgsOnChannel(List<OFMessage> msgs) {
181 if (channel.isConnected()) {
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700182 channel.write(msgs);
Charles Chan5b7ec342015-10-18 20:55:41 -0700183 } else {
Brian O'Connore755caa2015-11-16 16:43:09 -0800184 log.warn("Dropping messages for switch {} because channel is not connected: {}",
185 dpid, msgs);
alshabib339a3d92014-09-26 17:54:32 -0700186 }
tom7ef8ff92014-09-17 13:08:06 -0700187 }
188
189 @Override
alshabibb452fd72015-04-22 20:46:20 -0700190 public final void sendRoleRequest(OFMessage msg) {
191 if (msg instanceof OFRoleRequest ||
192 msg instanceof OFNiciraControllerRoleRequest) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800193 sendMsgsOnChannel(Collections.singletonList(msg));
alshabibb452fd72015-04-22 20:46:20 -0700194 return;
195 }
196 throw new IllegalArgumentException("Someone is trying to send " +
197 "a non role request message");
198 }
tom7ef8ff92014-09-17 13:08:06 -0700199
Ayaka Koshibe3c240772015-05-20 16:23:40 -0700200 @Override
alshabiba2df7b2a2015-05-06 13:57:10 -0700201 public final void sendHandshakeMessage(OFMessage message) {
202 if (!this.isDriverHandshakeComplete()) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800203 sendMsgsOnChannel(Collections.singletonList(message));
alshabiba2df7b2a2015-05-06 13:57:10 -0700204 }
205 }
206
tom7ef8ff92014-09-17 13:08:06 -0700207 @Override
208 public final boolean isConnected() {
209 return this.connected;
210 }
211
212 @Override
213 public final void setConnected(boolean connected) {
214 this.connected = connected;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700215 }
tom7ef8ff92014-09-17 13:08:06 -0700216
217 @Override
218 public final void setChannel(Channel channel) {
219 this.channel = channel;
Ray Milkeye53f1712015-01-16 09:17:16 -0800220 final SocketAddress address = channel.getRemoteAddress();
221 if (address instanceof InetSocketAddress) {
222 final InetSocketAddress inetAddress = (InetSocketAddress) address;
223 final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress());
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700224 if (ipAddress.isIp4()) {
Ray Milkeye53f1712015-01-16 09:17:16 -0800225 channelId = ipAddress.toString() + ':' + inetAddress.getPort();
226 } else {
227 channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort();
228 }
229 }
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700230 }
tom7ef8ff92014-09-17 13:08:06 -0700231
Ray Milkeye53f1712015-01-16 09:17:16 -0800232 @Override
233 public String channelId() {
234 return channelId;
235 }
236
tom7ef8ff92014-09-17 13:08:06 -0700237 //************************
238 // Switch features related
239 //************************
240
241 @Override
242 public final long getId() {
243 return this.dpid.value();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700244 }
tom7ef8ff92014-09-17 13:08:06 -0700245
246 @Override
247 public final String getStringId() {
248 return this.dpid.toString();
249 }
250
251 @Override
252 public final void setOFVersion(OFVersion ofV) {
253 this.ofVersion = ofV;
254 }
255
256 @Override
257 public void setTableFull(boolean full) {
258 this.tableFull = full;
259 }
260
261 @Override
262 public void setFeaturesReply(OFFeaturesReply featuresReply) {
263 this.features = featuresReply;
264 }
265
266 @Override
267 public abstract Boolean supportNxRole();
268
269 //************************
270 // Message handling
271 //************************
272 /**
273 * Handle the message coming from the dataplane.
274 *
275 * @param m the actual message
276 */
277 @Override
278 public final void handleMessage(OFMessage m) {
Thomas Vachuska39274462014-12-02 13:23:50 -0800279 if (this.role == RoleState.MASTER || m instanceof OFPortStatus) {
alshabib339a3d92014-09-26 17:54:32 -0700280 this.agent.processMessage(dpid, m);
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800281 } else {
282 log.trace("Dropping received message {}, was not MASTER", m);
alshabib339a3d92014-09-26 17:54:32 -0700283 }
tom7ef8ff92014-09-17 13:08:06 -0700284 }
285
286 @Override
287 public RoleState getRole() {
288 return role;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700289 }
tom7ef8ff92014-09-17 13:08:06 -0700290
291 @Override
292 public final boolean connectSwitch() {
293 return this.agent.addConnectedSwitch(dpid, this);
294 }
295
296 @Override
297 public final boolean activateMasterSwitch() {
298 return this.agent.addActivatedMasterSwitch(dpid, this);
299 }
300
301 @Override
302 public final boolean activateEqualSwitch() {
303 return this.agent.addActivatedEqualSwitch(dpid, this);
304 }
305
306 @Override
307 public final void transitionToEqualSwitch() {
308 this.agent.transitionToEqualSwitch(dpid);
309 }
310
311 @Override
312 public final void transitionToMasterSwitch() {
313 this.agent.transitionToMasterSwitch(dpid);
Brian O'Connore755caa2015-11-16 16:43:09 -0800314 synchronized (messagesPendingMastership) {
315 List<OFMessage> messages = messagesPendingMastership.get();
316 if (messages != null) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800317 // Cannot use sendMsg here. It will only append to pending list.
318 sendMsgsOnChannel(messages);
Brian O'Connore755caa2015-11-16 16:43:09 -0800319 log.debug("Sending {} pending messages to switch {}",
320 messages.size(), dpid);
321 messagesPendingMastership.set(null);
322 }
323 // perform role transition after clearing messages queue
324 this.role = RoleState.MASTER;
Charles Chan5b7ec342015-10-18 20:55:41 -0700325 }
tom7ef8ff92014-09-17 13:08:06 -0700326 }
327
328 @Override
329 public final void removeConnectedSwitch() {
330 this.agent.removeConnectedSwitch(dpid);
331 }
332
333 @Override
Jian Li152b8852015-12-07 14:47:25 -0800334 public void addEventListener(OpenFlowEventListener listener) {
335 ofEventListener.add(listener);
336 }
337
338 @Override
339 public void removeEventListener(OpenFlowEventListener listener) {
340 ofEventListener.remove(listener);
341 }
342
343 @Override
tom7ef8ff92014-09-17 13:08:06 -0700344 public OFFactory factory() {
345 return OFFactories.getFactory(ofVersion);
346 }
347
348 @Override
349 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700350 this.ports.add(portDescReply);
351 }
352
353 @Override
354 public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
355 this.ports.addAll(portDescReplies);
tom7ef8ff92014-09-17 13:08:06 -0700356 }
357
358 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700359 public void returnRoleReply(RoleState requested, RoleState response) {
360 this.agent.returnRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700361 }
362
363 @Override
tom7ef8ff92014-09-17 13:08:06 -0700364 public abstract void startDriverHandshake();
365
366 @Override
367 public abstract boolean isDriverHandshakeComplete();
368
369 @Override
370 public abstract void processDriverHandshakeMessage(OFMessage m);
371
alshabib339a3d92014-09-26 17:54:32 -0700372
373 // Role Handling
374
tom7ef8ff92014-09-17 13:08:06 -0700375 @Override
376 public void setRole(RoleState role) {
377 try {
Brian O'Connore755caa2015-11-16 16:43:09 -0800378 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
379 // perform role transition to SLAVE/EQUAL before sending role request
380 this.role = role;
381 }
tom7ef8ff92014-09-17 13:08:06 -0700382 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
Madan Jampanif2af7712015-05-29 18:43:52 -0700383 log.debug("Sending role {} to switch {}", role, getStringId());
Brian O'Connore755caa2015-11-16 16:43:09 -0800384 if (role == RoleState.MASTER) {
385 synchronized (messagesPendingMastership) {
386 if (messagesPendingMastership.get() == null) {
387 log.debug("Initializing new message queue for switch {}", dpid);
388 /*
389 The presence of messagesPendingMastership indicates that
390 a switch is currently transitioning to MASTER, but
391 is still awaiting role reply from switch.
392 */
393 messagesPendingMastership.set(Lists.newArrayList());
394 }
Charles Chan5b7ec342015-10-18 20:55:41 -0700395 }
alshabib339a3d92014-09-26 17:54:32 -0700396 }
Brian O'Connore755caa2015-11-16 16:43:09 -0800397 } else if (role == RoleState.MASTER) {
398 // role request not support; transition switch to MASTER
alshabib7814e9f2014-09-30 11:52:12 -0700399 this.role = role;
tom7ef8ff92014-09-17 13:08:06 -0700400 }
401 } catch (IOException e) {
402 log.error("Unable to write to switch {}.", this.dpid);
403 }
404 }
405
alshabib339a3d92014-09-26 17:54:32 -0700406 @Override
407 public void reassertRole() {
Brian O'Connore755caa2015-11-16 16:43:09 -0800408 // TODO should messages be sent directly or queue during reassertion?
alshabib339a3d92014-09-26 17:54:32 -0700409 if (this.getRole() == RoleState.MASTER) {
410 log.warn("Received permission error from switch {} while " +
411 "being master. Reasserting master role.",
412 this.getStringId());
413 this.setRole(RoleState.MASTER);
414 }
415 }
416
tom7ef8ff92014-09-17 13:08:06 -0700417 @Override
418 public void handleRole(OFMessage m) throws SwitchStateException {
419 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
420 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
421 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
422 if (rri.getRole() == RoleState.MASTER) {
423 this.transitionToMasterSwitch();
424 } else if (rri.getRole() == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800425 rri.getRole() == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700426 this.transitionToEqualSwitch();
427 }
alshabib339a3d92014-09-26 17:54:32 -0700428 } else {
alshabib4785eec2014-12-04 16:45:45 -0800429 log.warn("Failed to set role for {}", this.getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700430 }
431 }
432
433 @Override
434 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
435 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
436 if (r == null) {
437 // The message wasn't really a Nicira role reply. We just
438 // dispatch it to the OFMessage listeners in this case.
439 this.handleMessage(m);
alshabibdfc7afb2014-10-21 20:13:27 -0700440 return;
tom7ef8ff92014-09-17 13:08:06 -0700441 }
442
443 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
444 new RoleReplyInfo(r, null, m.getXid()));
445 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
446 if (r == RoleState.MASTER) {
447 this.transitionToMasterSwitch();
448 } else if (r == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800449 r == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700450 this.transitionToEqualSwitch();
451 }
alshabib339a3d92014-09-26 17:54:32 -0700452 } else {
alshabibdfc7afb2014-10-21 20:13:27 -0700453 this.disconnectSwitch();
tom7ef8ff92014-09-17 13:08:06 -0700454 }
455 }
456
457 @Override
458 public boolean handleRoleError(OFErrorMsg error) {
459 try {
460 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
461 } catch (SwitchStateException e) {
462 this.disconnectSwitch();
463 }
464 return true;
465 }
466
tom7ef8ff92014-09-17 13:08:06 -0700467 @Override
468 public final void setAgent(OpenFlowAgent ag) {
469 if (this.agent == null) {
470 this.agent = ag;
471 }
472 }
473
474 @Override
475 public final void setRoleHandler(RoleHandler roleHandler) {
476 if (this.roleMan == null) {
477 this.roleMan = roleHandler;
478 }
479 }
480
481 @Override
482 public void setSwitchDescription(OFDescStatsReply d) {
483 this.desc = d;
484 }
485
486 @Override
487 public int getNextTransactionId() {
488 return this.xidCounter.getAndIncrement();
489 }
490
491 @Override
492 public List<OFPortDesc> getPorts() {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700493 return this.ports.stream()
Brian O'Connore755caa2015-11-16 16:43:09 -0800494 .flatMap(portReply -> portReply.getEntries().stream())
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700495 .collect(Collectors.toList());
tom7ef8ff92014-09-17 13:08:06 -0700496 }
497
498 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800499 public String manufacturerDescription() {
tom7ef8ff92014-09-17 13:08:06 -0700500 return this.desc.getMfrDesc();
501 }
502
tom7ef8ff92014-09-17 13:08:06 -0700503 @Override
504 public String datapathDescription() {
505 return this.desc.getDpDesc();
506 }
507
tom7ef8ff92014-09-17 13:08:06 -0700508 @Override
509 public String hardwareDescription() {
510 return this.desc.getHwDesc();
511 }
512
513 @Override
514 public String softwareDescription() {
515 return this.desc.getSwDesc();
516 }
517
518 @Override
519 public String serialNumber() {
520 return this.desc.getSerialNum();
521 }
522
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700523 @Override
Marc De Leenheerb9311372015-07-09 11:36:49 -0700524 public Device.Type deviceType() {
525 return Device.Type.SWITCH;
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700526 }
527
alshabibb452fd72015-04-22 20:46:20 -0700528 @Override
529 public String toString() {
530 return this.getClass().getName() + " [" + ((channel != null)
531 ? channel.getRemoteAddress() : "?")
532 + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
533 }
Jian Li152b8852015-12-07 14:47:25 -0800534
535 /**
536 * OpenFlow message handler for outgoing control messages.
537 */
538 protected final class OFMessageHandler implements Runnable {
539
540 protected final OFMessage msg;
541 protected final Dpid dpid;
542
543 public OFMessageHandler(Dpid dpid, OFMessage msg) {
544 this.msg = msg;
545 this.dpid = dpid;
546 }
547
548 @Override
549 public void run() {
550 for (OpenFlowEventListener listener : ofEventListener) {
551 listener.handleMessage(dpid, msg);
552 }
553 }
554 }
tom7ef8ff92014-09-17 13:08:06 -0700555}