blob: d0bb7da747afee14b20927096b8bd3b1feac4393 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -070019import com.google.common.base.MoreObjects;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080020import com.google.common.collect.ImmutableList;
Brian O'Connore755caa2015-11-16 16:43:09 -080021import com.google.common.collect.Lists;
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -070022
Marc De Leenheerb9311372015-07-09 11:36:49 -070023import org.onosproject.net.Device;
alshabibb452fd72015-04-22 20:46:20 -070024import org.onosproject.net.driver.AbstractHandlerBehaviour;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.openflow.controller.Dpid;
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -070026import org.onosproject.openflow.controller.OpenFlowSession;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.openflow.controller.RoleState;
tom7ef8ff92014-09-17 13:08:06 -070028import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
Jian Li152b8852015-12-07 14:47:25 -080029import org.projectfloodlight.openflow.protocol.OFErrorMsg;
Marc De Leenheerc662d322016-02-18 16:05:10 -080030import org.projectfloodlight.openflow.protocol.OFExperimenter;
31import org.projectfloodlight.openflow.protocol.OFFactories;
Jian Li152b8852015-12-07 14:47:25 -080032import org.projectfloodlight.openflow.protocol.OFFactory;
Marc De Leenheerc662d322016-02-18 16:05:10 -080033import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
34import org.projectfloodlight.openflow.protocol.OFMessage;
Jordi Ortizaa8de492016-12-01 00:21:36 +010035import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
Jordi Ortiz91477b82016-11-29 15:22:50 +010036import org.projectfloodlight.openflow.protocol.OFMeterFeaturesStatsReply;
Marc De Leenheerc662d322016-02-18 16:05:10 -080037import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleRequest;
38import org.projectfloodlight.openflow.protocol.OFPortDesc;
39import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080040import org.projectfloodlight.openflow.protocol.OFPortReason;
Marc De Leenheerc662d322016-02-18 16:05:10 -080041import org.projectfloodlight.openflow.protocol.OFPortStatus;
Jian Li152b8852015-12-07 14:47:25 -080042import org.projectfloodlight.openflow.protocol.OFRoleReply;
Marc De Leenheerc662d322016-02-18 16:05:10 -080043import org.projectfloodlight.openflow.protocol.OFRoleRequest;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080044import org.projectfloodlight.openflow.protocol.OFType;
Marc De Leenheerc662d322016-02-18 16:05:10 -080045import org.projectfloodlight.openflow.protocol.OFVersion;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080046import org.projectfloodlight.openflow.types.OFPort;
tom7ef8ff92014-09-17 13:08:06 -070047import org.slf4j.Logger;
48import org.slf4j.LoggerFactory;
49
Thomas Vachuska1c681d72015-05-18 14:58:53 -070050import java.io.IOException;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080051import java.util.Collection;
Thomas Vachuska1c681d72015-05-18 14:58:53 -070052import java.util.Collections;
53import java.util.List;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080054import java.util.Map;
55import java.util.concurrent.ConcurrentHashMap;
Thomas Vachuska1c681d72015-05-18 14:58:53 -070056import java.util.concurrent.atomic.AtomicInteger;
Brian O'Connore755caa2015-11-16 16:43:09 -080057import java.util.concurrent.atomic.AtomicReference;
Thomas Vachuska1c681d72015-05-18 14:58:53 -070058import java.util.stream.Collectors;
59
tom7ef8ff92014-09-17 13:08:06 -070060/**
61 * An abstract representation of an OpenFlow switch. Can be extended by others
62 * to serve as a base for their vendor specific representation of a switch.
63 */
alshabibb452fd72015-04-22 20:46:20 -070064public abstract class AbstractOpenFlowSwitch extends AbstractHandlerBehaviour
65 implements OpenFlowSwitchDriver {
tom7ef8ff92014-09-17 13:08:06 -070066
Yuta HIGUCHIf5416d82014-10-24 21:17:40 -070067 protected final Logger log = LoggerFactory.getLogger(getClass());
tom7ef8ff92014-09-17 13:08:06 -070068
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -070069 private OpenFlowSession channel;
Ray Milkeye53f1712015-01-16 09:17:16 -080070 protected String channelId;
tom7ef8ff92014-09-17 13:08:06 -070071
72 private boolean connected;
73 protected boolean startDriverHandshakeCalled = false;
alshabibb452fd72015-04-22 20:46:20 -070074 private Dpid dpid;
tom7ef8ff92014-09-17 13:08:06 -070075 private OpenFlowAgent agent;
76 private final AtomicInteger xidCounter = new AtomicInteger(0);
77
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -070078 private OFFactory ofFactory;
tom7ef8ff92014-09-17 13:08:06 -070079
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080080 // known port descriptions maintained by
81 // (all) : OFPortStatus
82 // < OF1.3 : feature reply
83 // >= OF1.3 : multipart stats reply (OFStatsReply:PORT_DESC)
84 private Map<OFPort, OFPortDesc> portDescs = new ConcurrentHashMap<>();
85
86 @Deprecated // in 1.13.0
87 protected List<OFPortDescStatsReply> ports = Lists.newCopyOnWriteArrayList();
tom7ef8ff92014-09-17 13:08:06 -070088
89 protected boolean tableFull;
90
91 private RoleHandler roleMan;
92
Brian O'Connore755caa2015-11-16 16:43:09 -080093 // TODO this is accessed from multiple threads, but volatile may have performance implications
94 protected volatile RoleState role;
tom7ef8ff92014-09-17 13:08:06 -070095
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080096 @Deprecated // in 1.13.0 to be made private after deprecation
tom7ef8ff92014-09-17 13:08:06 -070097 protected OFFeaturesReply features;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -080098 @Deprecated // in 1.13.0 to be made private after deprecation
tom7ef8ff92014-09-17 13:08:06 -070099 protected OFDescStatsReply desc;
100
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -0800101 @Deprecated // in 1.13.0 to be made private after deprecation
Jordi Ortiz91477b82016-11-29 15:22:50 +0100102 protected OFMeterFeaturesStatsReply meterfeatures;
103
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800104 // messagesPendingMastership is used as synchronization variable for
105 // all mastership related changes. In this block, mastership (including
106 // role update) will have either occurred or not.
Brian O'Connore755caa2015-11-16 16:43:09 -0800107 private final AtomicReference<List<OFMessage>> messagesPendingMastership
108 = new AtomicReference<>();
Charles Chan5b7ec342015-10-18 20:55:41 -0700109
alshabibb452fd72015-04-22 20:46:20 -0700110 @Override
111 public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
tom7ef8ff92014-09-17 13:08:06 -0700112 this.dpid = dpid;
113 this.desc = desc;
114 }
115
116 //************************
117 // Channel related
118 //************************
119
120 @Override
121 public final void disconnectSwitch() {
Charles Chanecfdfb72015-11-24 19:05:50 -0800122 setConnected(false);
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700123 this.channel.closeSession();
tom7ef8ff92014-09-17 13:08:06 -0700124 }
125
126 @Override
Charles Chan5b7ec342015-10-18 20:55:41 -0700127 public void sendMsg(OFMessage msg) {
128 this.sendMsg(Collections.singletonList(msg));
tom7ef8ff92014-09-17 13:08:06 -0700129 }
130
131 @Override
132 public final void sendMsg(List<OFMessage> msgs) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800133 /*
134 It is possible that in this block, we transition to SLAVE/EQUAL.
135 If this is the case, the supplied messages will race with the
136 RoleRequest message, and they could be rejected by the switch.
137 In the interest of performance, we will not protect this block with
138 a synchronization primitive, because the message would have just been
139 dropped anyway.
140 */
Jian Lia78cdb22016-04-21 13:03:58 -0700141
Brian O'Connore755caa2015-11-16 16:43:09 -0800142 if (role == RoleState.MASTER) {
143 // fast path send when we are master
Brian O'Connore755caa2015-11-16 16:43:09 -0800144 sendMsgsOnChannel(msgs);
145 return;
146 }
147 // check to see if mastership transition is in progress
148 synchronized (messagesPendingMastership) {
149 /*
150 messagesPendingMastership is used as synchronization variable for
151 all mastership related changes. In this block, mastership (including
152 role update) will have either occurred or not.
153 */
154 if (role == RoleState.MASTER) {
155 // transition to MASTER complete, send messages
156 sendMsgsOnChannel(msgs);
157 return;
158 }
159
160 List<OFMessage> messages = messagesPendingMastership.get();
161 if (messages != null) {
162 // we are transitioning to MASTER, so add messages to queue
163 messages.addAll(msgs);
164 log.debug("Enqueue message for switch {}. queue size after is {}",
165 dpid, messages.size());
166 } else {
167 // not transitioning to MASTER
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700168 log.warn("Dropping message for switch {} (role: {}, active: {}): {}",
169 dpid, role, channel.isActive(), msgs);
Brian O'Connore755caa2015-11-16 16:43:09 -0800170 }
171 }
Jian Li11111972016-04-01 23:49:00 -0700172 }
Jian Li152b8852015-12-07 14:47:25 -0800173
Brian O'Connore755caa2015-11-16 16:43:09 -0800174 private void sendMsgsOnChannel(List<OFMessage> msgs) {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700175 if (channel.sendMsg(msgs)) {
Jian Lia78cdb22016-04-21 13:03:58 -0700176 agent.processDownstreamMessage(dpid, msgs);
Charles Chan5b7ec342015-10-18 20:55:41 -0700177 } else {
Brian O'Connore755caa2015-11-16 16:43:09 -0800178 log.warn("Dropping messages for switch {} because channel is not connected: {}",
179 dpid, msgs);
alshabib339a3d92014-09-26 17:54:32 -0700180 }
tom7ef8ff92014-09-17 13:08:06 -0700181 }
182
183 @Override
alshabibb452fd72015-04-22 20:46:20 -0700184 public final void sendRoleRequest(OFMessage msg) {
185 if (msg instanceof OFRoleRequest ||
186 msg instanceof OFNiciraControllerRoleRequest) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800187 sendMsgsOnChannel(Collections.singletonList(msg));
alshabibb452fd72015-04-22 20:46:20 -0700188 return;
189 }
190 throw new IllegalArgumentException("Someone is trying to send " +
191 "a non role request message");
192 }
tom7ef8ff92014-09-17 13:08:06 -0700193
Ayaka Koshibe3c240772015-05-20 16:23:40 -0700194 @Override
Marc De Leenheerc662d322016-02-18 16:05:10 -0800195 public final void
196 sendHandshakeMessage(OFMessage message) {
alshabiba2df7b2a2015-05-06 13:57:10 -0700197 if (!this.isDriverHandshakeComplete()) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800198 sendMsgsOnChannel(Collections.singletonList(message));
alshabiba2df7b2a2015-05-06 13:57:10 -0700199 }
200 }
201
tom7ef8ff92014-09-17 13:08:06 -0700202 @Override
203 public final boolean isConnected() {
204 return this.connected;
205 }
206
207 @Override
208 public final void setConnected(boolean connected) {
209 this.connected = connected;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700210 }
tom7ef8ff92014-09-17 13:08:06 -0700211
212 @Override
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700213 public final void setChannel(OpenFlowSession channel) {
tom7ef8ff92014-09-17 13:08:06 -0700214 this.channel = channel;
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700215 channelId = channel.sessionInfo().toString();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700216 }
tom7ef8ff92014-09-17 13:08:06 -0700217
Ray Milkeye53f1712015-01-16 09:17:16 -0800218 @Override
219 public String channelId() {
220 return channelId;
221 }
222
tom7ef8ff92014-09-17 13:08:06 -0700223 //************************
224 // Switch features related
225 //************************
226
227 @Override
228 public final long getId() {
229 return this.dpid.value();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700230 }
tom7ef8ff92014-09-17 13:08:06 -0700231
232 @Override
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700233 public Dpid getDpid() {
234 return this.dpid;
235 }
236
237 @Override
tom7ef8ff92014-09-17 13:08:06 -0700238 public final String getStringId() {
239 return this.dpid.toString();
240 }
241
242 @Override
243 public final void setOFVersion(OFVersion ofV) {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700244 this.ofFactory = OFFactories.getFactory(ofV);
tom7ef8ff92014-09-17 13:08:06 -0700245 }
246
247 @Override
248 public void setTableFull(boolean full) {
249 this.tableFull = full;
250 }
251
252 @Override
253 public void setFeaturesReply(OFFeaturesReply featuresReply) {
254 this.features = featuresReply;
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -0800255 if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
256 // before OF 1.3, feature reply contains OFPortDescs
257 replacePortDescsWith(featuresReply.getPorts());
258 }
tom7ef8ff92014-09-17 13:08:06 -0700259 }
260
261 @Override
Jordi Ortiz91477b82016-11-29 15:22:50 +0100262 public void setMeterFeaturesReply(OFMeterFeaturesStatsReply meterFeaturesReply) {
263 meterfeatures = meterFeaturesReply;
264 }
265
266 @Override
tom7ef8ff92014-09-17 13:08:06 -0700267 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) {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700280 try {
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -0800281 // TODO revisit states other than ports should
282 // also ignore role state.
283 if (m.getType() == OFType.PORT_STATUS) {
284 OFPortStatus portStatus = (OFPortStatus) m;
285 if (portStatus.getReason() == OFPortReason.DELETE) {
286 portDescs.remove(portStatus.getDesc().getPortNo());
287 } else {
288 portDescs.put(portStatus.getDesc().getPortNo(), portStatus.getDesc());
289 }
290 }
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700291 this.agent.processMessage(dpid, m);
292 } catch (Exception e) {
293 log.warn("Unhandled exception processing {}@{}", m, dpid, e);
294 }
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800295 } else {
296 log.trace("Dropping received message {}, was not MASTER", m);
alshabib339a3d92014-09-26 17:54:32 -0700297 }
tom7ef8ff92014-09-17 13:08:06 -0700298 }
299
300 @Override
301 public RoleState getRole() {
302 return role;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700303 }
tom7ef8ff92014-09-17 13:08:06 -0700304
305 @Override
306 public final boolean connectSwitch() {
307 return this.agent.addConnectedSwitch(dpid, this);
308 }
309
310 @Override
311 public final boolean activateMasterSwitch() {
312 return this.agent.addActivatedMasterSwitch(dpid, this);
313 }
314
315 @Override
316 public final boolean activateEqualSwitch() {
317 return this.agent.addActivatedEqualSwitch(dpid, this);
318 }
319
320 @Override
321 public final void transitionToEqualSwitch() {
322 this.agent.transitionToEqualSwitch(dpid);
323 }
324
325 @Override
326 public final void transitionToMasterSwitch() {
327 this.agent.transitionToMasterSwitch(dpid);
Brian O'Connore755caa2015-11-16 16:43:09 -0800328 synchronized (messagesPendingMastership) {
329 List<OFMessage> messages = messagesPendingMastership.get();
Jonathan Hart81b724b2018-01-29 16:02:41 -0800330 if (messages != null && !messages.isEmpty()) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800331 // Cannot use sendMsg here. It will only append to pending list.
332 sendMsgsOnChannel(messages);
Brian O'Connore755caa2015-11-16 16:43:09 -0800333 log.debug("Sending {} pending messages to switch {}",
334 messages.size(), dpid);
335 messagesPendingMastership.set(null);
336 }
337 // perform role transition after clearing messages queue
338 this.role = RoleState.MASTER;
Charles Chan5b7ec342015-10-18 20:55:41 -0700339 }
tom7ef8ff92014-09-17 13:08:06 -0700340 }
341
342 @Override
343 public final void removeConnectedSwitch() {
344 this.agent.removeConnectedSwitch(dpid);
345 }
346
347 @Override
348 public OFFactory factory() {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700349 return ofFactory;
tom7ef8ff92014-09-17 13:08:06 -0700350 }
351
352 @Override
353 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -0800354 portDescReply.getEntries().forEach(pd -> portDescs.put(pd.getPortNo(), pd));
355
356 // maintaining only for backward compatibility, to be removed
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700357 this.ports.add(portDescReply);
358 }
359
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -0800360 protected void replacePortDescsWith(Collection<OFPortDesc> allPorts) {
361 Map<OFPort, OFPortDesc> ports = new ConcurrentHashMap<>(allPorts.size());
362 allPorts.forEach(pd -> ports.put(pd.getPortNo(), pd));
363 // replace all
364 this.portDescs = ports;
365 }
366
367 protected Map<OFPort, OFPortDesc> portDescs() {
368 return portDescs;
369 }
370
371 // only called once during handshake WAIT_DESCRIPTION_STAT_REPLY
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700372 @Override
373 public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -0800374 replacePortDescsWith(portDescReplies.stream()
375 .map(OFPortDescStatsReply::getEntries)
376 .flatMap(List::stream)
377 .collect(Collectors.toList()));
378
379 // maintaining only for backward compatibility, to be removed
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700380 this.ports.addAll(portDescReplies);
tom7ef8ff92014-09-17 13:08:06 -0700381 }
382
383 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700384 public void returnRoleReply(RoleState requested, RoleState response) {
385 this.agent.returnRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700386 }
387
388 @Override
tom7ef8ff92014-09-17 13:08:06 -0700389 public abstract void startDriverHandshake();
390
391 @Override
392 public abstract boolean isDriverHandshakeComplete();
393
394 @Override
395 public abstract void processDriverHandshakeMessage(OFMessage m);
396
alshabib339a3d92014-09-26 17:54:32 -0700397
398 // Role Handling
399
tom7ef8ff92014-09-17 13:08:06 -0700400 @Override
401 public void setRole(RoleState role) {
402 try {
Brian O'Connore755caa2015-11-16 16:43:09 -0800403 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
404 // perform role transition to SLAVE/EQUAL before sending role request
405 this.role = role;
406 }
tom7ef8ff92014-09-17 13:08:06 -0700407 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
Madan Jampanif2af7712015-05-29 18:43:52 -0700408 log.debug("Sending role {} to switch {}", role, getStringId());
Brian O'Connore755caa2015-11-16 16:43:09 -0800409 if (role == RoleState.MASTER) {
410 synchronized (messagesPendingMastership) {
411 if (messagesPendingMastership.get() == null) {
412 log.debug("Initializing new message queue for switch {}", dpid);
413 /*
414 The presence of messagesPendingMastership indicates that
415 a switch is currently transitioning to MASTER, but
416 is still awaiting role reply from switch.
417 */
418 messagesPendingMastership.set(Lists.newArrayList());
419 }
Charles Chan5b7ec342015-10-18 20:55:41 -0700420 }
alshabib339a3d92014-09-26 17:54:32 -0700421 }
Brian O'Connore755caa2015-11-16 16:43:09 -0800422 } else if (role == RoleState.MASTER) {
423 // role request not support; transition switch to MASTER
alshabib7814e9f2014-09-30 11:52:12 -0700424 this.role = role;
tom7ef8ff92014-09-17 13:08:06 -0700425 }
426 } catch (IOException e) {
427 log.error("Unable to write to switch {}.", this.dpid);
428 }
429 }
430
alshabib339a3d92014-09-26 17:54:32 -0700431 @Override
432 public void reassertRole() {
Brian O'Connore755caa2015-11-16 16:43:09 -0800433 // TODO should messages be sent directly or queue during reassertion?
alshabib339a3d92014-09-26 17:54:32 -0700434 if (this.getRole() == RoleState.MASTER) {
435 log.warn("Received permission error from switch {} while " +
436 "being master. Reasserting master role.",
437 this.getStringId());
438 this.setRole(RoleState.MASTER);
439 }
440 }
441
tom7ef8ff92014-09-17 13:08:06 -0700442 @Override
443 public void handleRole(OFMessage m) throws SwitchStateException {
444 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
445 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
446 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
447 if (rri.getRole() == RoleState.MASTER) {
448 this.transitionToMasterSwitch();
449 } else if (rri.getRole() == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800450 rri.getRole() == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700451 this.transitionToEqualSwitch();
452 }
alshabib339a3d92014-09-26 17:54:32 -0700453 } else {
alshabib4785eec2014-12-04 16:45:45 -0800454 log.warn("Failed to set role for {}", this.getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700455 }
456 }
457
458 @Override
459 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
460 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
461 if (r == null) {
462 // The message wasn't really a Nicira role reply. We just
463 // dispatch it to the OFMessage listeners in this case.
464 this.handleMessage(m);
alshabibdfc7afb2014-10-21 20:13:27 -0700465 return;
tom7ef8ff92014-09-17 13:08:06 -0700466 }
467
468 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
469 new RoleReplyInfo(r, null, m.getXid()));
470 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
471 if (r == RoleState.MASTER) {
472 this.transitionToMasterSwitch();
473 } else if (r == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800474 r == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700475 this.transitionToEqualSwitch();
476 }
alshabib339a3d92014-09-26 17:54:32 -0700477 } else {
alshabibdfc7afb2014-10-21 20:13:27 -0700478 this.disconnectSwitch();
tom7ef8ff92014-09-17 13:08:06 -0700479 }
480 }
481
482 @Override
483 public boolean handleRoleError(OFErrorMsg error) {
484 try {
485 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
486 } catch (SwitchStateException e) {
487 this.disconnectSwitch();
488 }
489 return true;
490 }
491
tom7ef8ff92014-09-17 13:08:06 -0700492 @Override
493 public final void setAgent(OpenFlowAgent ag) {
494 if (this.agent == null) {
495 this.agent = ag;
496 }
497 }
498
499 @Override
500 public final void setRoleHandler(RoleHandler roleHandler) {
501 if (this.roleMan == null) {
502 this.roleMan = roleHandler;
503 }
504 }
505
506 @Override
507 public void setSwitchDescription(OFDescStatsReply d) {
508 this.desc = d;
509 }
510
511 @Override
512 public int getNextTransactionId() {
513 return this.xidCounter.getAndIncrement();
514 }
515
516 @Override
517 public List<OFPortDesc> getPorts() {
Yuta HIGUCHIbd5d9902017-12-17 14:33:49 -0800518 return ImmutableList.copyOf(portDescs.values());
tom7ef8ff92014-09-17 13:08:06 -0700519 }
520
521 @Override
Jordi Ortizaa8de492016-12-01 00:21:36 +0100522 public OFMeterFeatures getMeterFeatures() {
523 if (this.meterfeatures != null) {
524 return this.meterfeatures.getFeatures();
525 } else {
526 return null;
527 }
528 }
529
530 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800531 public String manufacturerDescription() {
tom7ef8ff92014-09-17 13:08:06 -0700532 return this.desc.getMfrDesc();
533 }
534
tom7ef8ff92014-09-17 13:08:06 -0700535 @Override
536 public String datapathDescription() {
537 return this.desc.getDpDesc();
538 }
539
tom7ef8ff92014-09-17 13:08:06 -0700540 @Override
541 public String hardwareDescription() {
542 return this.desc.getHwDesc();
543 }
544
545 @Override
546 public String softwareDescription() {
547 return this.desc.getSwDesc();
548 }
549
550 @Override
551 public String serialNumber() {
552 return this.desc.getSerialNum();
553 }
554
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700555 @Override
Marc De Leenheerb9311372015-07-09 11:36:49 -0700556 public Device.Type deviceType() {
557 return Device.Type.SWITCH;
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700558 }
559
alshabibb452fd72015-04-22 20:46:20 -0700560 @Override
561 public String toString() {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700562 return MoreObjects.toStringHelper(getClass())
563 .add("session", channel.sessionInfo())
564 .add("dpid", dpid)
565 .toString();
alshabibb452fd72015-04-22 20:46:20 -0700566 }
tom7ef8ff92014-09-17 13:08:06 -0700567}