blob: 69ddc71a8ce69b6c821942e2230128d7c1adbce2 [file] [log] [blame]
tom7ef8ff92014-09-17 13:08:06 -07001/**
2 * Copyright 2011, Big Switch Networks, Inc.
3 * Originally created by David Erickson, Stanford University
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 **/
17
tom9c94c5b2014-09-17 13:14:42 -070018package org.onlab.onos.openflow.controller.driver;
tom7ef8ff92014-09-17 13:08:06 -070019
20import java.io.IOException;
21import java.util.Collections;
22import java.util.List;
23import java.util.concurrent.atomic.AtomicInteger;
24
25import org.jboss.netty.channel.Channel;
tom9c94c5b2014-09-17 13:14:42 -070026import org.onlab.onos.openflow.controller.Dpid;
27import org.onlab.onos.openflow.controller.RoleState;
tom7ef8ff92014-09-17 13:08:06 -070028import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
29import org.projectfloodlight.openflow.protocol.OFErrorMsg;
30import org.projectfloodlight.openflow.protocol.OFExperimenter;
31import org.projectfloodlight.openflow.protocol.OFFactories;
32import org.projectfloodlight.openflow.protocol.OFFactory;
33import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
34import org.projectfloodlight.openflow.protocol.OFMessage;
35import org.projectfloodlight.openflow.protocol.OFPortDesc;
36import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
37import org.projectfloodlight.openflow.protocol.OFRoleReply;
38import org.projectfloodlight.openflow.protocol.OFVersion;
39import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
42/**
43 * An abstract representation of an OpenFlow switch. Can be extended by others
44 * to serve as a base for their vendor specific representation of a switch.
45 */
46public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
47
48 private static Logger log =
49 LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
50
51 protected Channel channel;
52
53 private boolean connected;
54 protected boolean startDriverHandshakeCalled = false;
55 private final Dpid dpid;
56 private OpenFlowAgent agent;
57 private final AtomicInteger xidCounter = new AtomicInteger(0);
58
59 private OFVersion ofVersion;
60
61 protected OFPortDescStatsReply ports;
62
63 protected boolean tableFull;
64
65 private RoleHandler roleMan;
66
67 protected RoleState role;
68
69 protected OFFeaturesReply features;
70 protected OFDescStatsReply desc;
71
72 /**
73 * Given a dpid build this switch.
74 * @param dp the dpid
75 */
76 protected AbstractOpenFlowSwitch(Dpid dp) {
77 this.dpid = dp;
78 }
79
80 public AbstractOpenFlowSwitch(Dpid dpid, OFDescStatsReply desc) {
81 this.dpid = dpid;
82 this.desc = desc;
83 }
84
85 //************************
86 // Channel related
87 //************************
88
89 @Override
90 public final void disconnectSwitch() {
91 this.channel.close();
92 }
93
94 @Override
95 public final void sendMsg(OFMessage m) {
alshabib339a3d92014-09-26 17:54:32 -070096 if (role == RoleState.MASTER) {
97 this.write(m);
98 }
tom7ef8ff92014-09-17 13:08:06 -070099 }
100
101 @Override
102 public final void sendMsg(List<OFMessage> msgs) {
alshabib339a3d92014-09-26 17:54:32 -0700103 if (role == RoleState.MASTER) {
104 this.write(msgs);
105 }
tom7ef8ff92014-09-17 13:08:06 -0700106 }
107
108 @Override
109 public abstract void write(OFMessage msg);
110
111 @Override
112 public abstract void write(List<OFMessage> msgs);
113
114 @Override
115 public final boolean isConnected() {
116 return this.connected;
117 }
118
119 @Override
120 public final void setConnected(boolean connected) {
121 this.connected = connected;
122 };
123
124 @Override
125 public final void setChannel(Channel channel) {
126 this.channel = channel;
127 };
128
129 //************************
130 // Switch features related
131 //************************
132
133 @Override
134 public final long getId() {
135 return this.dpid.value();
136 };
137
138 @Override
139 public final String getStringId() {
140 return this.dpid.toString();
141 }
142
143 @Override
144 public final void setOFVersion(OFVersion ofV) {
145 this.ofVersion = ofV;
146 }
147
148 @Override
149 public void setTableFull(boolean full) {
150 this.tableFull = full;
151 }
152
153 @Override
154 public void setFeaturesReply(OFFeaturesReply featuresReply) {
155 this.features = featuresReply;
156 }
157
158 @Override
159 public abstract Boolean supportNxRole();
160
161 //************************
162 // Message handling
163 //************************
164 /**
165 * Handle the message coming from the dataplane.
166 *
167 * @param m the actual message
168 */
169 @Override
170 public final void handleMessage(OFMessage m) {
alshabib339a3d92014-09-26 17:54:32 -0700171 if (this.role == RoleState.MASTER) {
172 this.agent.processMessage(dpid, m);
173 }
tom7ef8ff92014-09-17 13:08:06 -0700174 }
175
176 @Override
177 public RoleState getRole() {
178 return role;
179 };
180
181 @Override
182 public final boolean connectSwitch() {
183 return this.agent.addConnectedSwitch(dpid, this);
184 }
185
186 @Override
187 public final boolean activateMasterSwitch() {
188 return this.agent.addActivatedMasterSwitch(dpid, this);
189 }
190
191 @Override
192 public final boolean activateEqualSwitch() {
193 return this.agent.addActivatedEqualSwitch(dpid, this);
194 }
195
196 @Override
197 public final void transitionToEqualSwitch() {
198 this.agent.transitionToEqualSwitch(dpid);
199 }
200
201 @Override
202 public final void transitionToMasterSwitch() {
203 this.agent.transitionToMasterSwitch(dpid);
204 }
205
206 @Override
207 public final void removeConnectedSwitch() {
208 this.agent.removeConnectedSwitch(dpid);
209 }
210
211 @Override
212 public OFFactory factory() {
213 return OFFactories.getFactory(ofVersion);
214 }
215
216 @Override
217 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
218 this.ports = portDescReply;
219 }
220
221 @Override
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700222 public void returnRoleAssertFailure(RoleState role) {
223 this.agent.returnRoleAssertFailed(dpid, role);
224 }
225
226 @Override
tom7ef8ff92014-09-17 13:08:06 -0700227 public abstract void startDriverHandshake();
228
229 @Override
230 public abstract boolean isDriverHandshakeComplete();
231
232 @Override
233 public abstract void processDriverHandshakeMessage(OFMessage m);
234
alshabib339a3d92014-09-26 17:54:32 -0700235
236 // Role Handling
237
tom7ef8ff92014-09-17 13:08:06 -0700238 @Override
239 public void setRole(RoleState role) {
240 try {
tom7ef8ff92014-09-17 13:08:06 -0700241 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
alshabib339a3d92014-09-26 17:54:32 -0700242 log.info("Sending role {} to switch {}", role, getStringId());
243 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
244 this.role = role;
245 }
tom7ef8ff92014-09-17 13:08:06 -0700246 }
247 } catch (IOException e) {
248 log.error("Unable to write to switch {}.", this.dpid);
249 }
250 }
251
alshabib339a3d92014-09-26 17:54:32 -0700252 @Override
253 public void reassertRole() {
254 if (this.getRole() == RoleState.MASTER) {
255 log.warn("Received permission error from switch {} while " +
256 "being master. Reasserting master role.",
257 this.getStringId());
258 this.setRole(RoleState.MASTER);
259 }
260 }
261
262
tom7ef8ff92014-09-17 13:08:06 -0700263
264 @Override
265 public void handleRole(OFMessage m) throws SwitchStateException {
266 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
267 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
268 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
269 if (rri.getRole() == RoleState.MASTER) {
alshabib339a3d92014-09-26 17:54:32 -0700270 this.role = rri.getRole();
tom7ef8ff92014-09-17 13:08:06 -0700271 this.transitionToMasterSwitch();
272 } else if (rri.getRole() == RoleState.EQUAL ||
alshabib339a3d92014-09-26 17:54:32 -0700273 rri.getRole() == RoleState.SLAVE) {
tom7ef8ff92014-09-17 13:08:06 -0700274 this.transitionToEqualSwitch();
275 }
alshabib339a3d92014-09-26 17:54:32 -0700276 } else {
277 return;
278 //TODO: tell people that we failed.
tom7ef8ff92014-09-17 13:08:06 -0700279 }
280 }
281
282 @Override
283 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
284 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
285 if (r == null) {
286 // The message wasn't really a Nicira role reply. We just
287 // dispatch it to the OFMessage listeners in this case.
288 this.handleMessage(m);
289 }
290
291 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
292 new RoleReplyInfo(r, null, m.getXid()));
293 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
294 if (r == RoleState.MASTER) {
alshabib339a3d92014-09-26 17:54:32 -0700295 this.role = r;
tom7ef8ff92014-09-17 13:08:06 -0700296 this.transitionToMasterSwitch();
297 } else if (r == RoleState.EQUAL ||
298 r == RoleState.SLAVE) {
299 this.transitionToEqualSwitch();
300 }
alshabib339a3d92014-09-26 17:54:32 -0700301 } else {
302 return;
303 //TODO: tell people that we failed.
tom7ef8ff92014-09-17 13:08:06 -0700304 }
305 }
306
307 @Override
308 public boolean handleRoleError(OFErrorMsg error) {
309 try {
310 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
311 } catch (SwitchStateException e) {
312 this.disconnectSwitch();
313 }
314 return true;
315 }
316
alshabib339a3d92014-09-26 17:54:32 -0700317
tom7ef8ff92014-09-17 13:08:06 -0700318
319 @Override
320 public final void setAgent(OpenFlowAgent ag) {
321 if (this.agent == null) {
322 this.agent = ag;
323 }
324 }
325
326 @Override
327 public final void setRoleHandler(RoleHandler roleHandler) {
328 if (this.roleMan == null) {
329 this.roleMan = roleHandler;
330 }
331 }
332
333 @Override
334 public void setSwitchDescription(OFDescStatsReply d) {
335 this.desc = d;
336 }
337
338 @Override
339 public int getNextTransactionId() {
340 return this.xidCounter.getAndIncrement();
341 }
342
343 @Override
344 public List<OFPortDesc> getPorts() {
345 return Collections.unmodifiableList(ports.getEntries());
346 }
347
348 @Override
349 public String manfacturerDescription() {
350 return this.desc.getMfrDesc();
351 }
352
353
354 @Override
355 public String datapathDescription() {
356 return this.desc.getDpDesc();
357 }
358
359
360 @Override
361 public String hardwareDescription() {
362 return this.desc.getHwDesc();
363 }
364
365 @Override
366 public String softwareDescription() {
367 return this.desc.getSwDesc();
368 }
369
370 @Override
371 public String serialNumber() {
372 return this.desc.getSerialNum();
373 }
374
375}