blob: ae3638172e523b139f78b0b3bad813e01c9f972c [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
216 public abstract void startDriverHandshake();
217
218 @Override
219 public abstract boolean isDriverHandshakeComplete();
220
221 @Override
222 public abstract void processDriverHandshakeMessage(OFMessage m);
223
224 @Override
225 public void setRole(RoleState role) {
226 try {
227 log.info("Sending role {} to switch {}", role, getStringId());
228 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
229 this.role = role;
230 }
231 } catch (IOException e) {
232 log.error("Unable to write to switch {}.", this.dpid);
233 }
234 }
235
236 // Role Handling
237
238 @Override
239 public void handleRole(OFMessage m) throws SwitchStateException {
240 RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
241 RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
242 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
243 if (rri.getRole() == RoleState.MASTER) {
244 this.transitionToMasterSwitch();
245 } else if (rri.getRole() == RoleState.EQUAL ||
246 rri.getRole() == RoleState.MASTER) {
247 this.transitionToEqualSwitch();
248 }
249 }
250 }
251
252 @Override
253 public void handleNiciraRole(OFMessage m) throws SwitchStateException {
254 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
255 if (r == null) {
256 // The message wasn't really a Nicira role reply. We just
257 // dispatch it to the OFMessage listeners in this case.
258 this.handleMessage(m);
259 }
260
261 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
262 new RoleReplyInfo(r, null, m.getXid()));
263 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
264 if (r == RoleState.MASTER) {
265 this.transitionToMasterSwitch();
266 } else if (r == RoleState.EQUAL ||
267 r == RoleState.SLAVE) {
268 this.transitionToEqualSwitch();
269 }
270 }
271 }
272
273 @Override
274 public boolean handleRoleError(OFErrorMsg error) {
275 try {
276 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
277 } catch (SwitchStateException e) {
278 this.disconnectSwitch();
279 }
280 return true;
281 }
282
283 @Override
284 public void reassertRole() {
285 if (this.getRole() == RoleState.MASTER) {
286 this.setRole(RoleState.MASTER);
287 }
288 }
289
290 @Override
291 public final void setAgent(OpenFlowAgent ag) {
292 if (this.agent == null) {
293 this.agent = ag;
294 }
295 }
296
297 @Override
298 public final void setRoleHandler(RoleHandler roleHandler) {
299 if (this.roleMan == null) {
300 this.roleMan = roleHandler;
301 }
302 }
303
304 @Override
305 public void setSwitchDescription(OFDescStatsReply d) {
306 this.desc = d;
307 }
308
309 @Override
310 public int getNextTransactionId() {
311 return this.xidCounter.getAndIncrement();
312 }
313
314 @Override
315 public List<OFPortDesc> getPorts() {
316 return Collections.unmodifiableList(ports.getEntries());
317 }
318
319 @Override
320 public String manfacturerDescription() {
321 return this.desc.getMfrDesc();
322 }
323
324
325 @Override
326 public String datapathDescription() {
327 return this.desc.getDpDesc();
328 }
329
330
331 @Override
332 public String hardwareDescription() {
333 return this.desc.getHwDesc();
334 }
335
336 @Override
337 public String softwareDescription() {
338 return this.desc.getSwDesc();
339 }
340
341 @Override
342 public String serialNumber() {
343 return this.desc.getSerialNum();
344 }
345
346}