blob: 393246b3d18d1f2f4f63f58befbc8e116879e203 [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) {
96 this.write(m);
97 }
98
99 @Override
100 public final void sendMsg(List<OFMessage> msgs) {
101 this.write(msgs);
102 }
103
104 @Override
105 public abstract void write(OFMessage msg);
106
107 @Override
108 public abstract void write(List<OFMessage> msgs);
109
110 @Override
111 public final boolean isConnected() {
112 return this.connected;
113 }
114
115 @Override
116 public final void setConnected(boolean connected) {
117 this.connected = connected;
118 };
119
120 @Override
121 public final void setChannel(Channel channel) {
122 this.channel = channel;
123 };
124
125 //************************
126 // Switch features related
127 //************************
128
129 @Override
130 public final long getId() {
131 return this.dpid.value();
132 };
133
134 @Override
135 public final String getStringId() {
136 return this.dpid.toString();
137 }
138
139 @Override
140 public final void setOFVersion(OFVersion ofV) {
141 this.ofVersion = ofV;
142 }
143
144 @Override
145 public void setTableFull(boolean full) {
146 this.tableFull = full;
147 }
148
149 @Override
150 public void setFeaturesReply(OFFeaturesReply featuresReply) {
151 this.features = featuresReply;
152 }
153
154 @Override
155 public abstract Boolean supportNxRole();
156
157 //************************
158 // Message handling
159 //************************
160 /**
161 * Handle the message coming from the dataplane.
162 *
163 * @param m the actual message
164 */
165 @Override
166 public final void handleMessage(OFMessage m) {
167 this.agent.processMessage(dpid, m);
168 }
169
170 @Override
171 public RoleState getRole() {
172 return role;
173 };
174
175 @Override
176 public final boolean connectSwitch() {
177 return this.agent.addConnectedSwitch(dpid, this);
178 }
179
180 @Override
181 public final boolean activateMasterSwitch() {
182 return this.agent.addActivatedMasterSwitch(dpid, this);
183 }
184
185 @Override
186 public final boolean activateEqualSwitch() {
187 return this.agent.addActivatedEqualSwitch(dpid, this);
188 }
189
190 @Override
191 public final void transitionToEqualSwitch() {
192 this.agent.transitionToEqualSwitch(dpid);
193 }
194
195 @Override
196 public final void transitionToMasterSwitch() {
197 this.agent.transitionToMasterSwitch(dpid);
198 }
199
200 @Override
201 public final void removeConnectedSwitch() {
202 this.agent.removeConnectedSwitch(dpid);
203 }
204
205 @Override
206 public OFFactory factory() {
207 return OFFactories.getFactory(ofVersion);
208 }
209
210 @Override
211 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
212 this.ports = portDescReply;
213 }
214
215 @Override
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700216 public void returnRoleAssertFailure(RoleState role) {
217 this.agent.returnRoleAssertFailed(dpid, role);
218 }
219
220 @Override
tom7ef8ff92014-09-17 13:08:06 -0700221 public abstract void startDriverHandshake();
222
223 @Override
224 public abstract boolean isDriverHandshakeComplete();
225
226 @Override
227 public abstract void processDriverHandshakeMessage(OFMessage m);
228
229 @Override
230 public void setRole(RoleState role) {
231 try {
232 log.info("Sending role {} to switch {}", role, getStringId());
233 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
234 this.role = role;
235 }
236 } catch (IOException e) {
237 log.error("Unable to write to switch {}.", this.dpid);
238 }
239 }
240
241 // Role Handling
242
243 @Override
244 public void handleRole(OFMessage m) throws SwitchStateException {
245 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
246 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
247 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
248 if (rri.getRole() == RoleState.MASTER) {
249 this.transitionToMasterSwitch();
250 } else if (rri.getRole() == RoleState.EQUAL ||
251 rri.getRole() == RoleState.MASTER) {
252 this.transitionToEqualSwitch();
253 }
254 }
255 }
256
257 @Override
258 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
259 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
260 if (r == null) {
261 // The message wasn't really a Nicira role reply. We just
262 // dispatch it to the OFMessage listeners in this case.
263 this.handleMessage(m);
264 }
265
266 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
267 new RoleReplyInfo(r, null, m.getXid()));
268 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
269 if (r == RoleState.MASTER) {
270 this.transitionToMasterSwitch();
271 } else if (r == RoleState.EQUAL ||
272 r == RoleState.SLAVE) {
273 this.transitionToEqualSwitch();
274 }
275 }
276 }
277
278 @Override
279 public boolean handleRoleError(OFErrorMsg error) {
280 try {
281 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
282 } catch (SwitchStateException e) {
283 this.disconnectSwitch();
284 }
285 return true;
286 }
287
288 @Override
289 public void reassertRole() {
290 if (this.getRole() == RoleState.MASTER) {
291 this.setRole(RoleState.MASTER);
292 }
293 }
294
295 @Override
296 public final void setAgent(OpenFlowAgent ag) {
297 if (this.agent == null) {
298 this.agent = ag;
299 }
300 }
301
302 @Override
303 public final void setRoleHandler(RoleHandler roleHandler) {
304 if (this.roleMan == null) {
305 this.roleMan = roleHandler;
306 }
307 }
308
309 @Override
310 public void setSwitchDescription(OFDescStatsReply d) {
311 this.desc = d;
312 }
313
314 @Override
315 public int getNextTransactionId() {
316 return this.xidCounter.getAndIncrement();
317 }
318
319 @Override
320 public List<OFPortDesc> getPorts() {
321 return Collections.unmodifiableList(ports.getEntries());
322 }
323
324 @Override
325 public String manfacturerDescription() {
326 return this.desc.getMfrDesc();
327 }
328
329
330 @Override
331 public String datapathDescription() {
332 return this.desc.getDpDesc();
333 }
334
335
336 @Override
337 public String hardwareDescription() {
338 return this.desc.getHwDesc();
339 }
340
341 @Override
342 public String softwareDescription() {
343 return this.desc.getSwDesc();
344 }
345
346 @Override
347 public String serialNumber() {
348 return this.desc.getSerialNum();
349 }
350
351}