blob: c3d6f4479b67a0d56f074355b6c14aa97123b79d [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present 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 Li11111972016-04-01 23:49:00 -0700167 }
Jian Li152b8852015-12-07 14:47:25 -0800168
Jian Li11111972016-04-01 23:49:00 -0700169 private void countOutgoingMsg(List<OFMessage> msgs) {
Jian Li28247b52016-01-07 17:24:15 -0800170 // listen to outgoing control messages only if listeners are registered
171 if (ofOutgoingMsgListener.size() != 0) {
172 msgs.forEach(m -> {
173 if (m.getType() == OFType.PACKET_OUT ||
174 m.getType() == OFType.FLOW_MOD ||
175 m.getType() == OFType.STATS_REQUEST) {
Andrea Campanelladda93562016-03-02 11:08:12 -0800176 executorMsgs.execute(new OFMessageHandler(dpid, m));
Jian Li28247b52016-01-07 17:24:15 -0800177 }
178 });
179 }
Brian O'Connore755caa2015-11-16 16:43:09 -0800180 }
181
182 private void sendMsgsOnChannel(List<OFMessage> msgs) {
183 if (channel.isConnected()) {
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700184 channel.write(msgs);
Jian Li11111972016-04-01 23:49:00 -0700185 countOutgoingMsg(msgs);
Charles Chan5b7ec342015-10-18 20:55:41 -0700186 } else {
Brian O'Connore755caa2015-11-16 16:43:09 -0800187 log.warn("Dropping messages for switch {} because channel is not connected: {}",
188 dpid, msgs);
alshabib339a3d92014-09-26 17:54:32 -0700189 }
tom7ef8ff92014-09-17 13:08:06 -0700190 }
191
192 @Override
alshabibb452fd72015-04-22 20:46:20 -0700193 public final void sendRoleRequest(OFMessage msg) {
194 if (msg instanceof OFRoleRequest ||
195 msg instanceof OFNiciraControllerRoleRequest) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800196 sendMsgsOnChannel(Collections.singletonList(msg));
alshabibb452fd72015-04-22 20:46:20 -0700197 return;
198 }
199 throw new IllegalArgumentException("Someone is trying to send " +
200 "a non role request message");
201 }
tom7ef8ff92014-09-17 13:08:06 -0700202
Ayaka Koshibe3c240772015-05-20 16:23:40 -0700203 @Override
Marc De Leenheerc662d322016-02-18 16:05:10 -0800204 public final void
205 sendHandshakeMessage(OFMessage message) {
alshabiba2df7b2a2015-05-06 13:57:10 -0700206 if (!this.isDriverHandshakeComplete()) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800207 sendMsgsOnChannel(Collections.singletonList(message));
alshabiba2df7b2a2015-05-06 13:57:10 -0700208 }
209 }
210
tom7ef8ff92014-09-17 13:08:06 -0700211 @Override
212 public final boolean isConnected() {
213 return this.connected;
214 }
215
216 @Override
217 public final void setConnected(boolean connected) {
218 this.connected = connected;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700219 }
tom7ef8ff92014-09-17 13:08:06 -0700220
221 @Override
222 public final void setChannel(Channel channel) {
223 this.channel = channel;
Ray Milkeye53f1712015-01-16 09:17:16 -0800224 final SocketAddress address = channel.getRemoteAddress();
225 if (address instanceof InetSocketAddress) {
226 final InetSocketAddress inetAddress = (InetSocketAddress) address;
227 final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress());
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700228 if (ipAddress.isIp4()) {
Ray Milkeye53f1712015-01-16 09:17:16 -0800229 channelId = ipAddress.toString() + ':' + inetAddress.getPort();
230 } else {
231 channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort();
232 }
233 }
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700234 }
tom7ef8ff92014-09-17 13:08:06 -0700235
Ray Milkeye53f1712015-01-16 09:17:16 -0800236 @Override
237 public String channelId() {
238 return channelId;
239 }
240
tom7ef8ff92014-09-17 13:08:06 -0700241 //************************
242 // Switch features related
243 //************************
244
245 @Override
246 public final long getId() {
247 return this.dpid.value();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700248 }
tom7ef8ff92014-09-17 13:08:06 -0700249
250 @Override
251 public final String getStringId() {
252 return this.dpid.toString();
253 }
254
255 @Override
256 public final void setOFVersion(OFVersion ofV) {
257 this.ofVersion = ofV;
258 }
259
260 @Override
261 public void setTableFull(boolean full) {
262 this.tableFull = full;
263 }
264
265 @Override
266 public void setFeaturesReply(OFFeaturesReply featuresReply) {
267 this.features = featuresReply;
268 }
269
270 @Override
271 public abstract Boolean supportNxRole();
272
273 //************************
274 // Message handling
275 //************************
276 /**
277 * Handle the message coming from the dataplane.
278 *
279 * @param m the actual message
280 */
281 @Override
282 public final void handleMessage(OFMessage m) {
Thomas Vachuska39274462014-12-02 13:23:50 -0800283 if (this.role == RoleState.MASTER || m instanceof OFPortStatus) {
alshabib339a3d92014-09-26 17:54:32 -0700284 this.agent.processMessage(dpid, m);
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800285 } else {
286 log.trace("Dropping received message {}, was not MASTER", m);
alshabib339a3d92014-09-26 17:54:32 -0700287 }
tom7ef8ff92014-09-17 13:08:06 -0700288 }
289
290 @Override
291 public RoleState getRole() {
292 return role;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700293 }
tom7ef8ff92014-09-17 13:08:06 -0700294
295 @Override
296 public final boolean connectSwitch() {
297 return this.agent.addConnectedSwitch(dpid, this);
298 }
299
300 @Override
301 public final boolean activateMasterSwitch() {
302 return this.agent.addActivatedMasterSwitch(dpid, this);
303 }
304
305 @Override
306 public final boolean activateEqualSwitch() {
307 return this.agent.addActivatedEqualSwitch(dpid, this);
308 }
309
310 @Override
311 public final void transitionToEqualSwitch() {
312 this.agent.transitionToEqualSwitch(dpid);
313 }
314
315 @Override
316 public final void transitionToMasterSwitch() {
317 this.agent.transitionToMasterSwitch(dpid);
Brian O'Connore755caa2015-11-16 16:43:09 -0800318 synchronized (messagesPendingMastership) {
319 List<OFMessage> messages = messagesPendingMastership.get();
320 if (messages != null) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800321 // Cannot use sendMsg here. It will only append to pending list.
322 sendMsgsOnChannel(messages);
Brian O'Connore755caa2015-11-16 16:43:09 -0800323 log.debug("Sending {} pending messages to switch {}",
324 messages.size(), dpid);
325 messagesPendingMastership.set(null);
326 }
327 // perform role transition after clearing messages queue
328 this.role = RoleState.MASTER;
Charles Chan5b7ec342015-10-18 20:55:41 -0700329 }
tom7ef8ff92014-09-17 13:08:06 -0700330 }
331
332 @Override
333 public final void removeConnectedSwitch() {
334 this.agent.removeConnectedSwitch(dpid);
335 }
336
337 @Override
Jian Li152b8852015-12-07 14:47:25 -0800338 public void addEventListener(OpenFlowEventListener listener) {
Jian Li28247b52016-01-07 17:24:15 -0800339 ofOutgoingMsgListener.add(listener);
Jian Li152b8852015-12-07 14:47:25 -0800340 }
341
342 @Override
343 public void removeEventListener(OpenFlowEventListener listener) {
Jian Li28247b52016-01-07 17:24:15 -0800344 ofOutgoingMsgListener.remove(listener);
Jian Li152b8852015-12-07 14:47:25 -0800345 }
346
347 @Override
tom7ef8ff92014-09-17 13:08:06 -0700348 public OFFactory factory() {
349 return OFFactories.getFactory(ofVersion);
350 }
351
352 @Override
353 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700354 this.ports.add(portDescReply);
355 }
356
357 @Override
358 public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
359 this.ports.addAll(portDescReplies);
tom7ef8ff92014-09-17 13:08:06 -0700360 }
361
362 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700363 public void returnRoleReply(RoleState requested, RoleState response) {
364 this.agent.returnRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700365 }
366
367 @Override
tom7ef8ff92014-09-17 13:08:06 -0700368 public abstract void startDriverHandshake();
369
370 @Override
371 public abstract boolean isDriverHandshakeComplete();
372
373 @Override
374 public abstract void processDriverHandshakeMessage(OFMessage m);
375
alshabib339a3d92014-09-26 17:54:32 -0700376
377 // Role Handling
378
tom7ef8ff92014-09-17 13:08:06 -0700379 @Override
380 public void setRole(RoleState role) {
381 try {
Brian O'Connore755caa2015-11-16 16:43:09 -0800382 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
383 // perform role transition to SLAVE/EQUAL before sending role request
384 this.role = role;
385 }
tom7ef8ff92014-09-17 13:08:06 -0700386 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
Madan Jampanif2af7712015-05-29 18:43:52 -0700387 log.debug("Sending role {} to switch {}", role, getStringId());
Brian O'Connore755caa2015-11-16 16:43:09 -0800388 if (role == RoleState.MASTER) {
389 synchronized (messagesPendingMastership) {
390 if (messagesPendingMastership.get() == null) {
391 log.debug("Initializing new message queue for switch {}", dpid);
392 /*
393 The presence of messagesPendingMastership indicates that
394 a switch is currently transitioning to MASTER, but
395 is still awaiting role reply from switch.
396 */
397 messagesPendingMastership.set(Lists.newArrayList());
398 }
Charles Chan5b7ec342015-10-18 20:55:41 -0700399 }
alshabib339a3d92014-09-26 17:54:32 -0700400 }
Brian O'Connore755caa2015-11-16 16:43:09 -0800401 } else if (role == RoleState.MASTER) {
402 // role request not support; transition switch to MASTER
alshabib7814e9f2014-09-30 11:52:12 -0700403 this.role = role;
tom7ef8ff92014-09-17 13:08:06 -0700404 }
405 } catch (IOException e) {
406 log.error("Unable to write to switch {}.", this.dpid);
407 }
408 }
409
alshabib339a3d92014-09-26 17:54:32 -0700410 @Override
411 public void reassertRole() {
Brian O'Connore755caa2015-11-16 16:43:09 -0800412 // TODO should messages be sent directly or queue during reassertion?
alshabib339a3d92014-09-26 17:54:32 -0700413 if (this.getRole() == RoleState.MASTER) {
414 log.warn("Received permission error from switch {} while " +
415 "being master. Reasserting master role.",
416 this.getStringId());
417 this.setRole(RoleState.MASTER);
418 }
419 }
420
tom7ef8ff92014-09-17 13:08:06 -0700421 @Override
422 public void handleRole(OFMessage m) throws SwitchStateException {
423 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
424 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
425 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
426 if (rri.getRole() == RoleState.MASTER) {
427 this.transitionToMasterSwitch();
428 } else if (rri.getRole() == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800429 rri.getRole() == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700430 this.transitionToEqualSwitch();
431 }
alshabib339a3d92014-09-26 17:54:32 -0700432 } else {
alshabib4785eec2014-12-04 16:45:45 -0800433 log.warn("Failed to set role for {}", this.getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700434 }
435 }
436
437 @Override
438 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
439 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
440 if (r == null) {
441 // The message wasn't really a Nicira role reply. We just
442 // dispatch it to the OFMessage listeners in this case.
443 this.handleMessage(m);
alshabibdfc7afb2014-10-21 20:13:27 -0700444 return;
tom7ef8ff92014-09-17 13:08:06 -0700445 }
446
447 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
448 new RoleReplyInfo(r, null, m.getXid()));
449 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
450 if (r == RoleState.MASTER) {
451 this.transitionToMasterSwitch();
452 } else if (r == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800453 r == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700454 this.transitionToEqualSwitch();
455 }
alshabib339a3d92014-09-26 17:54:32 -0700456 } else {
alshabibdfc7afb2014-10-21 20:13:27 -0700457 this.disconnectSwitch();
tom7ef8ff92014-09-17 13:08:06 -0700458 }
459 }
460
461 @Override
462 public boolean handleRoleError(OFErrorMsg error) {
463 try {
464 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
465 } catch (SwitchStateException e) {
466 this.disconnectSwitch();
467 }
468 return true;
469 }
470
tom7ef8ff92014-09-17 13:08:06 -0700471 @Override
472 public final void setAgent(OpenFlowAgent ag) {
473 if (this.agent == null) {
474 this.agent = ag;
475 }
476 }
477
478 @Override
479 public final void setRoleHandler(RoleHandler roleHandler) {
480 if (this.roleMan == null) {
481 this.roleMan = roleHandler;
482 }
483 }
484
485 @Override
486 public void setSwitchDescription(OFDescStatsReply d) {
487 this.desc = d;
488 }
489
490 @Override
491 public int getNextTransactionId() {
492 return this.xidCounter.getAndIncrement();
493 }
494
495 @Override
496 public List<OFPortDesc> getPorts() {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700497 return this.ports.stream()
Brian O'Connore755caa2015-11-16 16:43:09 -0800498 .flatMap(portReply -> portReply.getEntries().stream())
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700499 .collect(Collectors.toList());
tom7ef8ff92014-09-17 13:08:06 -0700500 }
501
502 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800503 public String manufacturerDescription() {
tom7ef8ff92014-09-17 13:08:06 -0700504 return this.desc.getMfrDesc();
505 }
506
tom7ef8ff92014-09-17 13:08:06 -0700507 @Override
508 public String datapathDescription() {
509 return this.desc.getDpDesc();
510 }
511
tom7ef8ff92014-09-17 13:08:06 -0700512 @Override
513 public String hardwareDescription() {
514 return this.desc.getHwDesc();
515 }
516
517 @Override
518 public String softwareDescription() {
519 return this.desc.getSwDesc();
520 }
521
522 @Override
523 public String serialNumber() {
524 return this.desc.getSerialNum();
525 }
526
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700527 @Override
Marc De Leenheerb9311372015-07-09 11:36:49 -0700528 public Device.Type deviceType() {
529 return Device.Type.SWITCH;
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700530 }
531
alshabibb452fd72015-04-22 20:46:20 -0700532 @Override
533 public String toString() {
534 return this.getClass().getName() + " [" + ((channel != null)
535 ? channel.getRemoteAddress() : "?")
536 + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
537 }
Jian Li152b8852015-12-07 14:47:25 -0800538
539 /**
540 * OpenFlow message handler for outgoing control messages.
541 */
542 protected final class OFMessageHandler implements Runnable {
543
544 protected final OFMessage msg;
545 protected final Dpid dpid;
546
547 public OFMessageHandler(Dpid dpid, OFMessage msg) {
548 this.msg = msg;
549 this.dpid = dpid;
550 }
551
552 @Override
553 public void run() {
Jian Li28247b52016-01-07 17:24:15 -0800554 for (OpenFlowEventListener listener : ofOutgoingMsgListener) {
Jian Li152b8852015-12-07 14:47:25 -0800555 listener.handleMessage(dpid, msg);
556 }
557 }
558 }
tom7ef8ff92014-09-17 13:08:06 -0700559}