blob: 1613303b25bf4aca2d2e26cf38c9cd28aa2ca943 [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
Brian O'Connore755caa2015-11-16 16:43:09 -080019import com.google.common.collect.Lists;
tom7ef8ff92014-09-17 13:08:06 -070020import org.jboss.netty.channel.Channel;
Ray Milkeye53f1712015-01-16 09:17:16 -080021import org.onlab.packet.IpAddress;
Marc De Leenheerb9311372015-07-09 11:36:49 -070022import org.onosproject.net.Device;
alshabibb452fd72015-04-22 20:46:20 -070023import org.onosproject.net.driver.AbstractHandlerBehaviour;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.openflow.controller.Dpid;
Jian Li152b8852015-12-07 14:47:25 -080025import org.onosproject.openflow.controller.OpenFlowEventListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.openflow.controller.RoleState;
tom7ef8ff92014-09-17 13:08:06 -070027import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
Jian Li152b8852015-12-07 14:47:25 -080028import org.projectfloodlight.openflow.protocol.OFErrorMsg;
Marc De Leenheerc662d322016-02-18 16:05:10 -080029import org.projectfloodlight.openflow.protocol.OFExperimenter;
30import org.projectfloodlight.openflow.protocol.OFFactories;
Jian Li152b8852015-12-07 14:47:25 -080031import org.projectfloodlight.openflow.protocol.OFFactory;
Marc De Leenheerc662d322016-02-18 16:05:10 -080032import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
33import org.projectfloodlight.openflow.protocol.OFMessage;
34import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleRequest;
35import org.projectfloodlight.openflow.protocol.OFPortDesc;
36import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
37import org.projectfloodlight.openflow.protocol.OFPortStatus;
Jian Li152b8852015-12-07 14:47:25 -080038import org.projectfloodlight.openflow.protocol.OFRoleReply;
Marc De Leenheerc662d322016-02-18 16:05:10 -080039import org.projectfloodlight.openflow.protocol.OFRoleRequest;
40import org.projectfloodlight.openflow.protocol.OFType;
41import org.projectfloodlight.openflow.protocol.OFVersion;
tom7ef8ff92014-09-17 13:08:06 -070042import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
Thomas Vachuska1c681d72015-05-18 14:58:53 -070045import java.io.IOException;
46import java.net.InetSocketAddress;
47import java.net.SocketAddress;
48import java.util.ArrayList;
49import java.util.Collections;
50import java.util.List;
Jian Li152b8852015-12-07 14:47:25 -080051import java.util.Set;
52import java.util.concurrent.CopyOnWriteArraySet;
53import java.util.concurrent.ExecutorService;
54import java.util.concurrent.Executors;
Thomas Vachuska1c681d72015-05-18 14:58:53 -070055import java.util.concurrent.atomic.AtomicInteger;
Brian O'Connore755caa2015-11-16 16:43:09 -080056import java.util.concurrent.atomic.AtomicReference;
Thomas Vachuska1c681d72015-05-18 14:58:53 -070057import java.util.stream.Collectors;
58
Marc De Leenheerc662d322016-02-18 16:05:10 -080059import static org.onlab.util.Tools.groupedThreads;
60
tom7ef8ff92014-09-17 13:08:06 -070061/**
62 * An abstract representation of an OpenFlow switch. Can be extended by others
63 * to serve as a base for their vendor specific representation of a switch.
64 */
alshabibb452fd72015-04-22 20:46:20 -070065public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
66 implements OpenFlowSwitchDriver {
tom7ef8ff92014-09-17 13:08:06 -070067
Yuta HIGUCHIf5416d82014-10-24 21:17:40 -070068 protected final Logger log = LoggerFactory.getLogger(getClass());
tom7ef8ff92014-09-17 13:08:06 -070069
alshabibb452fd72015-04-22 20:46:20 -070070 private Channel channel;
Ray Milkeye53f1712015-01-16 09:17:16 -080071 protected String channelId;
tom7ef8ff92014-09-17 13:08:06 -070072
73 private boolean connected;
74 protected boolean startDriverHandshakeCalled = false;
alshabibb452fd72015-04-22 20:46:20 -070075 private Dpid dpid;
tom7ef8ff92014-09-17 13:08:06 -070076 private OpenFlowAgent agent;
77 private final AtomicInteger xidCounter = new AtomicInteger(0);
78
79 private OFVersion ofVersion;
80
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070081 protected List<OFPortDescStatsReply> ports = new ArrayList<>();
tom7ef8ff92014-09-17 13:08:06 -070082
83 protected boolean tableFull;
84
85 private RoleHandler roleMan;
86
Brian O'Connore755caa2015-11-16 16:43:09 -080087 // TODO this is accessed from multiple threads, but volatile may have performance implications
88 protected volatile RoleState role;
tom7ef8ff92014-09-17 13:08:06 -070089
90 protected OFFeaturesReply features;
91 protected OFDescStatsReply desc;
92
Jian Li28247b52016-01-07 17:24:15 -080093 protected Set<OpenFlowEventListener> ofOutgoingMsgListener = new CopyOnWriteArraySet<>();
Jian Li152b8852015-12-07 14:47:25 -080094
95 protected ExecutorService executorMsgs =
Andrea Campanelladda93562016-03-02 11:08:12 -080096 Executors.newCachedThreadPool(groupedThreads("onos/of", "event-outgoing-msg-stats-%d", log));
Jian Li152b8852015-12-07 14:47:25 -080097
HIGUCHI Yuta1979f552015-12-28 21:24:26 -080098 // messagesPendingMastership is used as synchronization variable for
99 // all mastership related changes. In this block, mastership (including
100 // role update) will have either occurred or not.
Brian O'Connore755caa2015-11-16 16:43:09 -0800101 private final AtomicReference<List<OFMessage>> messagesPendingMastership
102 = new AtomicReference<>();
Charles Chan5b7ec342015-10-18 20:55:41 -0700103
alshabibb452fd72015-04-22 20:46:20 -0700104 @Override
105 public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
tom7ef8ff92014-09-17 13:08:06 -0700106 this.dpid = dpid;
107 this.desc = desc;
alshabibb452fd72015-04-22 20:46:20 -0700108 this.ofVersion = ofv;
tom7ef8ff92014-09-17 13:08:06 -0700109 }
110
111 //************************
112 // Channel related
113 //************************
114
115 @Override
116 public final void disconnectSwitch() {
Charles Chanecfdfb72015-11-24 19:05:50 -0800117 setConnected(false);
tom7ef8ff92014-09-17 13:08:06 -0700118 this.channel.close();
119 }
120
121 @Override
Charles Chan5b7ec342015-10-18 20:55:41 -0700122 public void sendMsg(OFMessage msg) {
123 this.sendMsg(Collections.singletonList(msg));
tom7ef8ff92014-09-17 13:08:06 -0700124 }
125
126 @Override
127 public final void sendMsg(List<OFMessage> msgs) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800128 /*
129 It is possible that in this block, we transition to SLAVE/EQUAL.
130 If this is the case, the supplied messages will race with the
131 RoleRequest message, and they could be rejected by the switch.
132 In the interest of performance, we will not protect this block with
133 a synchronization primitive, because the message would have just been
134 dropped anyway.
135 */
136 if (role == RoleState.MASTER) {
137 // fast path send when we are master
138
139 sendMsgsOnChannel(msgs);
140 return;
141 }
142 // check to see if mastership transition is in progress
143 synchronized (messagesPendingMastership) {
144 /*
145 messagesPendingMastership is used as synchronization variable for
146 all mastership related changes. In this block, mastership (including
147 role update) will have either occurred or not.
148 */
149 if (role == RoleState.MASTER) {
150 // transition to MASTER complete, send messages
151 sendMsgsOnChannel(msgs);
152 return;
153 }
154
155 List<OFMessage> messages = messagesPendingMastership.get();
156 if (messages != null) {
157 // we are transitioning to MASTER, so add messages to queue
158 messages.addAll(msgs);
159 log.debug("Enqueue message for switch {}. queue size after is {}",
160 dpid, messages.size());
161 } else {
162 // not transitioning to MASTER
163 log.warn("Dropping message for switch {} (role: {}, connected: {}): {}",
164 dpid, role, channel.isConnected(), msgs);
165 }
166 }
Jian Li152b8852015-12-07 14:47:25 -0800167
Jian Li28247b52016-01-07 17:24:15 -0800168 // listen to outgoing control messages only if listeners are registered
169 if (ofOutgoingMsgListener.size() != 0) {
170 msgs.forEach(m -> {
171 if (m.getType() == OFType.PACKET_OUT ||
172 m.getType() == OFType.FLOW_MOD ||
173 m.getType() == OFType.STATS_REQUEST) {
Andrea Campanelladda93562016-03-02 11:08:12 -0800174 executorMsgs.execute(new OFMessageHandler(dpid, m));
Jian Li28247b52016-01-07 17:24:15 -0800175 }
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
Marc De Leenheerc662d322016-02-18 16:05:10 -0800201 public final void
202 sendHandshakeMessage(OFMessage message) {
alshabiba2df7b2a2015-05-06 13:57:10 -0700203 if (!this.isDriverHandshakeComplete()) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800204 sendMsgsOnChannel(Collections.singletonList(message));
alshabiba2df7b2a2015-05-06 13:57:10 -0700205 }
206 }
207
tom7ef8ff92014-09-17 13:08:06 -0700208 @Override
209 public final boolean isConnected() {
210 return this.connected;
211 }
212
213 @Override
214 public final void setConnected(boolean connected) {
215 this.connected = connected;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700216 }
tom7ef8ff92014-09-17 13:08:06 -0700217
218 @Override
219 public final void setChannel(Channel channel) {
220 this.channel = channel;
Ray Milkeye53f1712015-01-16 09:17:16 -0800221 final SocketAddress address = channel.getRemoteAddress();
222 if (address instanceof InetSocketAddress) {
223 final InetSocketAddress inetAddress = (InetSocketAddress) address;
224 final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress());
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700225 if (ipAddress.isIp4()) {
Ray Milkeye53f1712015-01-16 09:17:16 -0800226 channelId = ipAddress.toString() + ':' + inetAddress.getPort();
227 } else {
228 channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort();
229 }
230 }
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700231 }
tom7ef8ff92014-09-17 13:08:06 -0700232
Ray Milkeye53f1712015-01-16 09:17:16 -0800233 @Override
234 public String channelId() {
235 return channelId;
236 }
237
tom7ef8ff92014-09-17 13:08:06 -0700238 //************************
239 // Switch features related
240 //************************
241
242 @Override
243 public final long getId() {
244 return this.dpid.value();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700245 }
tom7ef8ff92014-09-17 13:08:06 -0700246
247 @Override
248 public final String getStringId() {
249 return this.dpid.toString();
250 }
251
252 @Override
253 public final void setOFVersion(OFVersion ofV) {
254 this.ofVersion = ofV;
255 }
256
257 @Override
258 public void setTableFull(boolean full) {
259 this.tableFull = full;
260 }
261
262 @Override
263 public void setFeaturesReply(OFFeaturesReply featuresReply) {
264 this.features = featuresReply;
265 }
266
267 @Override
268 public abstract Boolean supportNxRole();
269
270 //************************
271 // Message handling
272 //************************
273 /**
274 * Handle the message coming from the dataplane.
275 *
276 * @param m the actual message
277 */
278 @Override
279 public final void handleMessage(OFMessage m) {
Thomas Vachuska39274462014-12-02 13:23:50 -0800280 if (this.role == RoleState.MASTER || m instanceof OFPortStatus) {
alshabib339a3d92014-09-26 17:54:32 -0700281 this.agent.processMessage(dpid, m);
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800282 } else {
283 log.trace("Dropping received message {}, was not MASTER", m);
alshabib339a3d92014-09-26 17:54:32 -0700284 }
tom7ef8ff92014-09-17 13:08:06 -0700285 }
286
287 @Override
288 public RoleState getRole() {
289 return role;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700290 }
tom7ef8ff92014-09-17 13:08:06 -0700291
292 @Override
293 public final boolean connectSwitch() {
294 return this.agent.addConnectedSwitch(dpid, this);
295 }
296
297 @Override
298 public final boolean activateMasterSwitch() {
299 return this.agent.addActivatedMasterSwitch(dpid, this);
300 }
301
302 @Override
303 public final boolean activateEqualSwitch() {
304 return this.agent.addActivatedEqualSwitch(dpid, this);
305 }
306
307 @Override
308 public final void transitionToEqualSwitch() {
309 this.agent.transitionToEqualSwitch(dpid);
310 }
311
312 @Override
313 public final void transitionToMasterSwitch() {
314 this.agent.transitionToMasterSwitch(dpid);
Brian O'Connore755caa2015-11-16 16:43:09 -0800315 synchronized (messagesPendingMastership) {
316 List<OFMessage> messages = messagesPendingMastership.get();
317 if (messages != null) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800318 // Cannot use sendMsg here. It will only append to pending list.
319 sendMsgsOnChannel(messages);
Brian O'Connore755caa2015-11-16 16:43:09 -0800320 log.debug("Sending {} pending messages to switch {}",
321 messages.size(), dpid);
322 messagesPendingMastership.set(null);
323 }
324 // perform role transition after clearing messages queue
325 this.role = RoleState.MASTER;
Charles Chan5b7ec342015-10-18 20:55:41 -0700326 }
tom7ef8ff92014-09-17 13:08:06 -0700327 }
328
329 @Override
330 public final void removeConnectedSwitch() {
331 this.agent.removeConnectedSwitch(dpid);
332 }
333
334 @Override
Jian Li152b8852015-12-07 14:47:25 -0800335 public void addEventListener(OpenFlowEventListener listener) {
Jian Li28247b52016-01-07 17:24:15 -0800336 ofOutgoingMsgListener.add(listener);
Jian Li152b8852015-12-07 14:47:25 -0800337 }
338
339 @Override
340 public void removeEventListener(OpenFlowEventListener listener) {
Jian Li28247b52016-01-07 17:24:15 -0800341 ofOutgoingMsgListener.remove(listener);
Jian Li152b8852015-12-07 14:47:25 -0800342 }
343
344 @Override
tom7ef8ff92014-09-17 13:08:06 -0700345 public OFFactory factory() {
346 return OFFactories.getFactory(ofVersion);
347 }
348
349 @Override
350 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700351 this.ports.add(portDescReply);
352 }
353
354 @Override
355 public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
356 this.ports.addAll(portDescReplies);
tom7ef8ff92014-09-17 13:08:06 -0700357 }
358
359 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700360 public void returnRoleReply(RoleState requested, RoleState response) {
361 this.agent.returnRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700362 }
363
364 @Override
tom7ef8ff92014-09-17 13:08:06 -0700365 public abstract void startDriverHandshake();
366
367 @Override
368 public abstract boolean isDriverHandshakeComplete();
369
370 @Override
371 public abstract void processDriverHandshakeMessage(OFMessage m);
372
alshabib339a3d92014-09-26 17:54:32 -0700373
374 // Role Handling
375
tom7ef8ff92014-09-17 13:08:06 -0700376 @Override
377 public void setRole(RoleState role) {
378 try {
Brian O'Connore755caa2015-11-16 16:43:09 -0800379 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
380 // perform role transition to SLAVE/EQUAL before sending role request
381 this.role = role;
382 }
tom7ef8ff92014-09-17 13:08:06 -0700383 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
Madan Jampanif2af7712015-05-29 18:43:52 -0700384 log.debug("Sending role {} to switch {}", role, getStringId());
Brian O'Connore755caa2015-11-16 16:43:09 -0800385 if (role == RoleState.MASTER) {
386 synchronized (messagesPendingMastership) {
387 if (messagesPendingMastership.get() == null) {
388 log.debug("Initializing new message queue for switch {}", dpid);
389 /*
390 The presence of messagesPendingMastership indicates that
391 a switch is currently transitioning to MASTER, but
392 is still awaiting role reply from switch.
393 */
394 messagesPendingMastership.set(Lists.newArrayList());
395 }
Charles Chan5b7ec342015-10-18 20:55:41 -0700396 }
alshabib339a3d92014-09-26 17:54:32 -0700397 }
Brian O'Connore755caa2015-11-16 16:43:09 -0800398 } else if (role == RoleState.MASTER) {
399 // role request not support; transition switch to MASTER
alshabib7814e9f2014-09-30 11:52:12 -0700400 this.role = role;
tom7ef8ff92014-09-17 13:08:06 -0700401 }
402 } catch (IOException e) {
403 log.error("Unable to write to switch {}.", this.dpid);
404 }
405 }
406
alshabib339a3d92014-09-26 17:54:32 -0700407 @Override
408 public void reassertRole() {
Brian O'Connore755caa2015-11-16 16:43:09 -0800409 // TODO should messages be sent directly or queue during reassertion?
alshabib339a3d92014-09-26 17:54:32 -0700410 if (this.getRole() == RoleState.MASTER) {
411 log.warn("Received permission error from switch {} while " +
412 "being master. Reasserting master role.",
413 this.getStringId());
414 this.setRole(RoleState.MASTER);
415 }
416 }
417
tom7ef8ff92014-09-17 13:08:06 -0700418 @Override
419 public void handleRole(OFMessage m) throws SwitchStateException {
420 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
421 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
422 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
423 if (rri.getRole() == RoleState.MASTER) {
424 this.transitionToMasterSwitch();
425 } else if (rri.getRole() == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800426 rri.getRole() == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700427 this.transitionToEqualSwitch();
428 }
alshabib339a3d92014-09-26 17:54:32 -0700429 } else {
alshabib4785eec2014-12-04 16:45:45 -0800430 log.warn("Failed to set role for {}", this.getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700431 }
432 }
433
434 @Override
435 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
436 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
437 if (r == null) {
438 // The message wasn't really a Nicira role reply. We just
439 // dispatch it to the OFMessage listeners in this case.
440 this.handleMessage(m);
alshabibdfc7afb2014-10-21 20:13:27 -0700441 return;
tom7ef8ff92014-09-17 13:08:06 -0700442 }
443
444 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
445 new RoleReplyInfo(r, null, m.getXid()));
446 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
447 if (r == RoleState.MASTER) {
448 this.transitionToMasterSwitch();
449 } else if (r == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800450 r == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700451 this.transitionToEqualSwitch();
452 }
alshabib339a3d92014-09-26 17:54:32 -0700453 } else {
alshabibdfc7afb2014-10-21 20:13:27 -0700454 this.disconnectSwitch();
tom7ef8ff92014-09-17 13:08:06 -0700455 }
456 }
457
458 @Override
459 public boolean handleRoleError(OFErrorMsg error) {
460 try {
461 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
462 } catch (SwitchStateException e) {
463 this.disconnectSwitch();
464 }
465 return true;
466 }
467
tom7ef8ff92014-09-17 13:08:06 -0700468 @Override
469 public final void setAgent(OpenFlowAgent ag) {
470 if (this.agent == null) {
471 this.agent = ag;
472 }
473 }
474
475 @Override
476 public final void setRoleHandler(RoleHandler roleHandler) {
477 if (this.roleMan == null) {
478 this.roleMan = roleHandler;
479 }
480 }
481
482 @Override
483 public void setSwitchDescription(OFDescStatsReply d) {
484 this.desc = d;
485 }
486
487 @Override
488 public int getNextTransactionId() {
489 return this.xidCounter.getAndIncrement();
490 }
491
492 @Override
493 public List<OFPortDesc> getPorts() {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700494 return this.ports.stream()
Brian O'Connore755caa2015-11-16 16:43:09 -0800495 .flatMap(portReply -> portReply.getEntries().stream())
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700496 .collect(Collectors.toList());
tom7ef8ff92014-09-17 13:08:06 -0700497 }
498
499 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800500 public String manufacturerDescription() {
tom7ef8ff92014-09-17 13:08:06 -0700501 return this.desc.getMfrDesc();
502 }
503
tom7ef8ff92014-09-17 13:08:06 -0700504 @Override
505 public String datapathDescription() {
506 return this.desc.getDpDesc();
507 }
508
tom7ef8ff92014-09-17 13:08:06 -0700509 @Override
510 public String hardwareDescription() {
511 return this.desc.getHwDesc();
512 }
513
514 @Override
515 public String softwareDescription() {
516 return this.desc.getSwDesc();
517 }
518
519 @Override
520 public String serialNumber() {
521 return this.desc.getSerialNum();
522 }
523
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700524 @Override
Marc De Leenheerb9311372015-07-09 11:36:49 -0700525 public Device.Type deviceType() {
526 return Device.Type.SWITCH;
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700527 }
528
alshabibb452fd72015-04-22 20:46:20 -0700529 @Override
530 public String toString() {
531 return this.getClass().getName() + " [" + ((channel != null)
532 ? channel.getRemoteAddress() : "?")
533 + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
534 }
Jian Li152b8852015-12-07 14:47:25 -0800535
536 /**
537 * OpenFlow message handler for outgoing control messages.
538 */
539 protected final class OFMessageHandler implements Runnable {
540
541 protected final OFMessage msg;
542 protected final Dpid dpid;
543
544 public OFMessageHandler(Dpid dpid, OFMessage msg) {
545 this.msg = msg;
546 this.dpid = dpid;
547 }
548
549 @Override
550 public void run() {
Jian Li28247b52016-01-07 17:24:15 -0800551 for (OpenFlowEventListener listener : ofOutgoingMsgListener) {
Jian Li152b8852015-12-07 14:47:25 -0800552 listener.handleMessage(dpid, msg);
553 }
554 }
555 }
tom7ef8ff92014-09-17 13:08:06 -0700556}