blob: 0ba3bd9730afe0dda2b51e0ba0c42a86409f4ecb [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 HIGUCHIf83c8cf2017-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 HIGUCHIf83c8cf2017-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 HIGUCHIf83c8cf2017-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 HIGUCHIf83c8cf2017-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 HIGUCHIf83c8cf2017-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 HIGUCHIf83c8cf2017-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 HIGUCHIf83c8cf2017-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
Ray Milkey7f98ba62018-09-05 16:14:08 -070086 private List<OFPortDescStatsReply> ports = Lists.newCopyOnWriteArrayList();
tom7ef8ff92014-09-17 13:08:06 -070087
Ray Milkey7f98ba62018-09-05 16:14:08 -070088 private boolean tableFull;
tom7ef8ff92014-09-17 13:08:06 -070089
90 private RoleHandler roleMan;
91
Brian O'Connore755caa2015-11-16 16:43:09 -080092 // TODO this is accessed from multiple threads, but volatile may have performance implications
93 protected volatile RoleState role;
tom7ef8ff92014-09-17 13:08:06 -070094
Ray Milkey7f98ba62018-09-05 16:14:08 -070095 private OFFeaturesReply features;
tom7ef8ff92014-09-17 13:08:06 -070096
Ray Milkey7f98ba62018-09-05 16:14:08 -070097 private OFDescStatsReply desc;
98
99 private OFMeterFeaturesStatsReply meterfeatures;
Jordi Ortiz91477b82016-11-29 15:22:50 +0100100
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800101 // messagesPendingMastership is used as synchronization variable for
102 // all mastership related changes. In this block, mastership (including
103 // role update) will have either occurred or not.
Brian O'Connore755caa2015-11-16 16:43:09 -0800104 private final AtomicReference<List<OFMessage>> messagesPendingMastership
105 = new AtomicReference<>();
Charles Chan5b7ec342015-10-18 20:55:41 -0700106
alshabibb452fd72015-04-22 20:46:20 -0700107 @Override
108 public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
tom7ef8ff92014-09-17 13:08:06 -0700109 this.dpid = dpid;
110 this.desc = desc;
111 }
112
113 //************************
114 // Channel related
115 //************************
116
117 @Override
118 public final void disconnectSwitch() {
Charles Chanecfdfb72015-11-24 19:05:50 -0800119 setConnected(false);
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700120 this.channel.closeSession();
tom7ef8ff92014-09-17 13:08:06 -0700121 }
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 */
Jian Lia78cdb22016-04-21 13:03:58 -0700138
Brian O'Connore755caa2015-11-16 16:43:09 -0800139 if (role == RoleState.MASTER) {
140 // fast path send when we are master
Brian O'Connore755caa2015-11-16 16:43:09 -0800141 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
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700165 log.warn("Dropping message for switch {} (role: {}, active: {}): {}",
166 dpid, role, channel.isActive(), msgs);
Brian O'Connore755caa2015-11-16 16:43:09 -0800167 }
168 }
Jian Li11111972016-04-01 23:49:00 -0700169 }
Jian Li152b8852015-12-07 14:47:25 -0800170
Brian O'Connore755caa2015-11-16 16:43:09 -0800171 private void sendMsgsOnChannel(List<OFMessage> msgs) {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700172 if (channel.sendMsg(msgs)) {
Jian Lia78cdb22016-04-21 13:03:58 -0700173 agent.processDownstreamMessage(dpid, msgs);
Charles Chan5b7ec342015-10-18 20:55:41 -0700174 } else {
Brian O'Connore755caa2015-11-16 16:43:09 -0800175 log.warn("Dropping messages for switch {} because channel is not connected: {}",
176 dpid, msgs);
alshabib339a3d92014-09-26 17:54:32 -0700177 }
tom7ef8ff92014-09-17 13:08:06 -0700178 }
179
180 @Override
alshabibb452fd72015-04-22 20:46:20 -0700181 public final void sendRoleRequest(OFMessage msg) {
182 if (msg instanceof OFRoleRequest ||
183 msg instanceof OFNiciraControllerRoleRequest) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800184 sendMsgsOnChannel(Collections.singletonList(msg));
alshabibb452fd72015-04-22 20:46:20 -0700185 return;
186 }
187 throw new IllegalArgumentException("Someone is trying to send " +
188 "a non role request message");
189 }
tom7ef8ff92014-09-17 13:08:06 -0700190
Ayaka Koshibe3c240772015-05-20 16:23:40 -0700191 @Override
Marc De Leenheerc662d322016-02-18 16:05:10 -0800192 public final void
193 sendHandshakeMessage(OFMessage message) {
alshabiba2df7b2a2015-05-06 13:57:10 -0700194 if (!this.isDriverHandshakeComplete()) {
Brian O'Connore755caa2015-11-16 16:43:09 -0800195 sendMsgsOnChannel(Collections.singletonList(message));
alshabiba2df7b2a2015-05-06 13:57:10 -0700196 }
197 }
198
tom7ef8ff92014-09-17 13:08:06 -0700199 @Override
200 public final boolean isConnected() {
201 return this.connected;
202 }
203
204 @Override
205 public final void setConnected(boolean connected) {
206 this.connected = connected;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700207 }
tom7ef8ff92014-09-17 13:08:06 -0700208
209 @Override
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700210 public final void setChannel(OpenFlowSession channel) {
tom7ef8ff92014-09-17 13:08:06 -0700211 this.channel = channel;
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700212 channelId = channel.sessionInfo().toString();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700213 }
tom7ef8ff92014-09-17 13:08:06 -0700214
Ray Milkeye53f1712015-01-16 09:17:16 -0800215 @Override
216 public String channelId() {
217 return channelId;
218 }
219
tom7ef8ff92014-09-17 13:08:06 -0700220 //************************
221 // Switch features related
222 //************************
223
224 @Override
225 public final long getId() {
226 return this.dpid.value();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700227 }
tom7ef8ff92014-09-17 13:08:06 -0700228
229 @Override
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700230 public Dpid getDpid() {
231 return this.dpid;
232 }
233
234 @Override
tom7ef8ff92014-09-17 13:08:06 -0700235 public final String getStringId() {
236 return this.dpid.toString();
237 }
238
239 @Override
240 public final void setOFVersion(OFVersion ofV) {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700241 this.ofFactory = OFFactories.getFactory(ofV);
tom7ef8ff92014-09-17 13:08:06 -0700242 }
243
244 @Override
245 public void setTableFull(boolean full) {
246 this.tableFull = full;
247 }
248
249 @Override
250 public void setFeaturesReply(OFFeaturesReply featuresReply) {
251 this.features = featuresReply;
Yuta HIGUCHIf83c8cf2017-12-17 14:33:49 -0800252 if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
253 // before OF 1.3, feature reply contains OFPortDescs
254 replacePortDescsWith(featuresReply.getPorts());
255 }
tom7ef8ff92014-09-17 13:08:06 -0700256 }
257
258 @Override
Jordi Ortiz91477b82016-11-29 15:22:50 +0100259 public void setMeterFeaturesReply(OFMeterFeaturesStatsReply meterFeaturesReply) {
260 meterfeatures = meterFeaturesReply;
261 }
262
263 @Override
tom7ef8ff92014-09-17 13:08:06 -0700264 public abstract Boolean supportNxRole();
265
266 //************************
267 // Message handling
268 //************************
269 /**
270 * Handle the message coming from the dataplane.
271 *
272 * @param m the actual message
273 */
274 @Override
275 public final void handleMessage(OFMessage m) {
Thomas Vachuska39274462014-12-02 13:23:50 -0800276 if (this.role == RoleState.MASTER || m instanceof OFPortStatus) {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700277 try {
Yuta HIGUCHIf83c8cf2017-12-17 14:33:49 -0800278 // TODO revisit states other than ports should
279 // also ignore role state.
280 if (m.getType() == OFType.PORT_STATUS) {
281 OFPortStatus portStatus = (OFPortStatus) m;
282 if (portStatus.getReason() == OFPortReason.DELETE) {
283 portDescs.remove(portStatus.getDesc().getPortNo());
284 } else {
285 portDescs.put(portStatus.getDesc().getPortNo(), portStatus.getDesc());
286 }
287 }
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700288 this.agent.processMessage(dpid, m);
289 } catch (Exception e) {
Ray Milkey31b00482019-02-07 08:06:28 -0800290 log.warn("Unhandled exception processing {}@{}:{}", m, dpid, e.getMessage());
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700291 }
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800292 } else {
293 log.trace("Dropping received message {}, was not MASTER", m);
alshabib339a3d92014-09-26 17:54:32 -0700294 }
tom7ef8ff92014-09-17 13:08:06 -0700295 }
296
297 @Override
298 public RoleState getRole() {
299 return role;
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700300 }
tom7ef8ff92014-09-17 13:08:06 -0700301
302 @Override
303 public final boolean connectSwitch() {
304 return this.agent.addConnectedSwitch(dpid, this);
305 }
306
307 @Override
308 public final boolean activateMasterSwitch() {
309 return this.agent.addActivatedMasterSwitch(dpid, this);
310 }
311
312 @Override
313 public final boolean activateEqualSwitch() {
314 return this.agent.addActivatedEqualSwitch(dpid, this);
315 }
316
317 @Override
318 public final void transitionToEqualSwitch() {
319 this.agent.transitionToEqualSwitch(dpid);
320 }
321
322 @Override
323 public final void transitionToMasterSwitch() {
324 this.agent.transitionToMasterSwitch(dpid);
Brian O'Connore755caa2015-11-16 16:43:09 -0800325 synchronized (messagesPendingMastership) {
326 List<OFMessage> messages = messagesPendingMastership.get();
Jonathan Hart39e20232018-01-29 16:02:41 -0800327 if (messages != null && !messages.isEmpty()) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800328 // Cannot use sendMsg here. It will only append to pending list.
329 sendMsgsOnChannel(messages);
Brian O'Connore755caa2015-11-16 16:43:09 -0800330 log.debug("Sending {} pending messages to switch {}",
331 messages.size(), dpid);
332 messagesPendingMastership.set(null);
333 }
334 // perform role transition after clearing messages queue
335 this.role = RoleState.MASTER;
Charles Chan5b7ec342015-10-18 20:55:41 -0700336 }
tom7ef8ff92014-09-17 13:08:06 -0700337 }
338
339 @Override
340 public final void removeConnectedSwitch() {
341 this.agent.removeConnectedSwitch(dpid);
342 }
343
344 @Override
345 public OFFactory factory() {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700346 return ofFactory;
tom7ef8ff92014-09-17 13:08:06 -0700347 }
348
349 @Override
350 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
Yuta HIGUCHIf83c8cf2017-12-17 14:33:49 -0800351 portDescReply.getEntries().forEach(pd -> portDescs.put(pd.getPortNo(), pd));
352
353 // maintaining only for backward compatibility, to be removed
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700354 this.ports.add(portDescReply);
355 }
356
Yuta HIGUCHIf83c8cf2017-12-17 14:33:49 -0800357 protected void replacePortDescsWith(Collection<OFPortDesc> allPorts) {
358 Map<OFPort, OFPortDesc> ports = new ConcurrentHashMap<>(allPorts.size());
359 allPorts.forEach(pd -> ports.put(pd.getPortNo(), pd));
360 // replace all
361 this.portDescs = ports;
362 }
363
364 protected Map<OFPort, OFPortDesc> portDescs() {
365 return portDescs;
366 }
367
368 // only called once during handshake WAIT_DESCRIPTION_STAT_REPLY
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700369 @Override
370 public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
Yuta HIGUCHIf83c8cf2017-12-17 14:33:49 -0800371 replacePortDescsWith(portDescReplies.stream()
372 .map(OFPortDescStatsReply::getEntries)
373 .flatMap(List::stream)
374 .collect(Collectors.toList()));
375
376 // maintaining only for backward compatibility, to be removed
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700377 this.ports.addAll(portDescReplies);
tom7ef8ff92014-09-17 13:08:06 -0700378 }
379
380 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700381 public void returnRoleReply(RoleState requested, RoleState response) {
382 this.agent.returnRoleReply(dpid, requested, response);
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700383 }
384
385 @Override
tom7ef8ff92014-09-17 13:08:06 -0700386 public abstract void startDriverHandshake();
387
388 @Override
389 public abstract boolean isDriverHandshakeComplete();
390
391 @Override
392 public abstract void processDriverHandshakeMessage(OFMessage m);
393
alshabib339a3d92014-09-26 17:54:32 -0700394
395 // Role Handling
396
tom7ef8ff92014-09-17 13:08:06 -0700397 @Override
398 public void setRole(RoleState role) {
399 try {
Brian O'Connore755caa2015-11-16 16:43:09 -0800400 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
401 // perform role transition to SLAVE/EQUAL before sending role request
402 this.role = role;
403 }
tom7ef8ff92014-09-17 13:08:06 -0700404 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
Madan Jampanif2af7712015-05-29 18:43:52 -0700405 log.debug("Sending role {} to switch {}", role, getStringId());
Brian O'Connore755caa2015-11-16 16:43:09 -0800406 if (role == RoleState.MASTER) {
407 synchronized (messagesPendingMastership) {
408 if (messagesPendingMastership.get() == null) {
409 log.debug("Initializing new message queue for switch {}", dpid);
410 /*
411 The presence of messagesPendingMastership indicates that
412 a switch is currently transitioning to MASTER, but
413 is still awaiting role reply from switch.
414 */
415 messagesPendingMastership.set(Lists.newArrayList());
416 }
Charles Chan5b7ec342015-10-18 20:55:41 -0700417 }
alshabib339a3d92014-09-26 17:54:32 -0700418 }
Brian O'Connore755caa2015-11-16 16:43:09 -0800419 } else if (role == RoleState.MASTER) {
420 // role request not support; transition switch to MASTER
alshabib7814e9f2014-09-30 11:52:12 -0700421 this.role = role;
tom7ef8ff92014-09-17 13:08:06 -0700422 }
423 } catch (IOException e) {
424 log.error("Unable to write to switch {}.", this.dpid);
425 }
426 }
427
alshabib339a3d92014-09-26 17:54:32 -0700428 @Override
429 public void reassertRole() {
Brian O'Connore755caa2015-11-16 16:43:09 -0800430 // TODO should messages be sent directly or queue during reassertion?
alshabib339a3d92014-09-26 17:54:32 -0700431 if (this.getRole() == RoleState.MASTER) {
432 log.warn("Received permission error from switch {} while " +
433 "being master. Reasserting master role.",
434 this.getStringId());
435 this.setRole(RoleState.MASTER);
436 }
437 }
438
tom7ef8ff92014-09-17 13:08:06 -0700439 @Override
440 public void handleRole(OFMessage m) throws SwitchStateException {
441 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
442 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
443 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
444 if (rri.getRole() == RoleState.MASTER) {
445 this.transitionToMasterSwitch();
446 } else if (rri.getRole() == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800447 rri.getRole() == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700448 this.transitionToEqualSwitch();
449 }
alshabib339a3d92014-09-26 17:54:32 -0700450 } else {
alshabib4785eec2014-12-04 16:45:45 -0800451 log.warn("Failed to set role for {}", this.getStringId());
tom7ef8ff92014-09-17 13:08:06 -0700452 }
453 }
454
455 @Override
456 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
457 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
458 if (r == null) {
459 // The message wasn't really a Nicira role reply. We just
460 // dispatch it to the OFMessage listeners in this case.
461 this.handleMessage(m);
alshabibdfc7afb2014-10-21 20:13:27 -0700462 return;
tom7ef8ff92014-09-17 13:08:06 -0700463 }
464
465 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
466 new RoleReplyInfo(r, null, m.getXid()));
467 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
468 if (r == RoleState.MASTER) {
469 this.transitionToMasterSwitch();
470 } else if (r == RoleState.EQUAL ||
Brian O'Connore755caa2015-11-16 16:43:09 -0800471 r == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700472 this.transitionToEqualSwitch();
473 }
alshabib339a3d92014-09-26 17:54:32 -0700474 } else {
alshabibdfc7afb2014-10-21 20:13:27 -0700475 this.disconnectSwitch();
tom7ef8ff92014-09-17 13:08:06 -0700476 }
477 }
478
479 @Override
480 public boolean handleRoleError(OFErrorMsg error) {
481 try {
482 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
483 } catch (SwitchStateException e) {
484 this.disconnectSwitch();
485 }
486 return true;
487 }
488
tom7ef8ff92014-09-17 13:08:06 -0700489 @Override
490 public final void setAgent(OpenFlowAgent ag) {
491 if (this.agent == null) {
492 this.agent = ag;
493 }
494 }
495
496 @Override
497 public final void setRoleHandler(RoleHandler roleHandler) {
498 if (this.roleMan == null) {
499 this.roleMan = roleHandler;
500 }
501 }
502
503 @Override
504 public void setSwitchDescription(OFDescStatsReply d) {
505 this.desc = d;
506 }
507
508 @Override
509 public int getNextTransactionId() {
510 return this.xidCounter.getAndIncrement();
511 }
512
513 @Override
514 public List<OFPortDesc> getPorts() {
Yuta HIGUCHIf83c8cf2017-12-17 14:33:49 -0800515 return ImmutableList.copyOf(portDescs.values());
tom7ef8ff92014-09-17 13:08:06 -0700516 }
517
518 @Override
Jordi Ortizaa8de492016-12-01 00:21:36 +0100519 public OFMeterFeatures getMeterFeatures() {
520 if (this.meterfeatures != null) {
521 return this.meterfeatures.getFeatures();
522 } else {
523 return null;
524 }
525 }
526
527 @Override
Laszlo Pappedadbe22017-12-14 20:05:49 +0000528 public OFFeaturesReply features() {
529 return this.features;
530 }
531
532 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800533 public String manufacturerDescription() {
tom7ef8ff92014-09-17 13:08:06 -0700534 return this.desc.getMfrDesc();
535 }
536
tom7ef8ff92014-09-17 13:08:06 -0700537 @Override
538 public String datapathDescription() {
539 return this.desc.getDpDesc();
540 }
541
tom7ef8ff92014-09-17 13:08:06 -0700542 @Override
543 public String hardwareDescription() {
544 return this.desc.getHwDesc();
545 }
546
547 @Override
548 public String softwareDescription() {
549 return this.desc.getSwDesc();
550 }
551
552 @Override
553 public String serialNumber() {
554 return this.desc.getSerialNum();
555 }
556
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700557 @Override
Marc De Leenheerb9311372015-07-09 11:36:49 -0700558 public Device.Type deviceType() {
559 return Device.Type.SWITCH;
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700560 }
561
alshabibb452fd72015-04-22 20:46:20 -0700562 @Override
563 public String toString() {
Yuta HIGUCHI6ee6b8c2017-05-09 14:44:30 -0700564 return MoreObjects.toStringHelper(getClass())
565 .add("session", channel.sessionInfo())
566 .add("dpid", dpid)
567 .toString();
alshabibb452fd72015-04-22 20:46:20 -0700568 }
tom7ef8ff92014-09-17 13:08:06 -0700569}