blob: 534daa0fb5a06116d2efe9b0c553e4c906f8c30c [file] [log] [blame]
alshabib54ebd9c2014-08-27 18:38:41 -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
18package org.onlab.onos.of.controller.impl.internal;
19
20import java.io.IOException;
alshabibd777b202014-08-28 17:52:55 -070021import java.util.Collections;
alshabib54ebd9c2014-08-27 18:38:41 -070022import java.util.List;
alshabibd777b202014-08-28 17:52:55 -070023import java.util.concurrent.atomic.AtomicInteger;
alshabib54ebd9c2014-08-27 18:38:41 -070024
25import org.jboss.netty.channel.Channel;
26import org.onlab.onos.of.controller.Dpid;
27import org.onlab.onos.of.controller.OpenFlowSwitch;
28import org.onlab.onos.of.controller.RoleState;
29import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
30import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleRecvStatus;
31import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleReplyInfo;
alshabibd777b202014-08-28 17:52:55 -070032import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
alshabib54ebd9c2014-08-27 18:38:41 -070033import org.projectfloodlight.openflow.protocol.OFErrorMsg;
34import org.projectfloodlight.openflow.protocol.OFExperimenter;
35import org.projectfloodlight.openflow.protocol.OFFactories;
36import org.projectfloodlight.openflow.protocol.OFFactory;
37import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
38import org.projectfloodlight.openflow.protocol.OFMessage;
alshabibd777b202014-08-28 17:52:55 -070039import org.projectfloodlight.openflow.protocol.OFPortDesc;
alshabib54ebd9c2014-08-27 18:38:41 -070040import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
41import org.projectfloodlight.openflow.protocol.OFRoleReply;
42import org.projectfloodlight.openflow.protocol.OFVersion;
43import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
46
47public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
48
49 private static Logger log =
50 LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
51
alshabibd777b202014-08-28 17:52:55 -070052 protected Channel channel;
53 protected boolean startDriverHandshakeCalled = false;
54
alshabib54ebd9c2014-08-27 18:38:41 -070055 private boolean connected;
56 private Dpid dpid;
57 private OpenFlowSwitchAgent agent;
alshabibd777b202014-08-28 17:52:55 -070058 private AtomicInteger xidCounter = new AtomicInteger(0);
alshabib54ebd9c2014-08-27 18:38:41 -070059
60 private OFVersion ofVersion;
61
62 protected OFPortDescStatsReply ports;
63
64 protected boolean tableFull;
65
66 private final RoleManager roleMan = new RoleManager(this);
67
alshabibd777b202014-08-28 17:52:55 -070068 protected RoleState role;
69
70 protected OFFeaturesReply features;
71
72 protected AbstractOpenFlowSwitch(Dpid dp) {
73 this.dpid = dp;
alshabib54ebd9c2014-08-27 18:38:41 -070074 }
75
76 //************************
77 // Channel related
78 //************************
79
80 /**
81 * Disconnects the switch by closing the TCP connection. Results in a call
82 * to the channel handler's channelDisconnected method for cleanup
83 * @throws IOException
84 */
85 public final void disconnectSwitch() {
86 this.channel.close();
87 }
88
89 /**
90 * Writes to the OFMessage to the output stream.
91 *
92 * @param m the message to be written
93 */
alshabibd777b202014-08-28 17:52:55 -070094 public abstract void sendMsg(OFMessage m);
alshabib54ebd9c2014-08-27 18:38:41 -070095
96 /**
97 * Writes to the OFMessage list to the output stream.
98 *
99 * @param msgs the messages to be written
100 */
alshabibd777b202014-08-28 17:52:55 -0700101 public void write(List<OFMessage> msgs) {
102 this.channel.write(msgs);
103 }
alshabib54ebd9c2014-08-27 18:38:41 -0700104
105
106 /**
107 * Checks if the switch is still connected.
108 * Only call while holding processMessageLock
109 *
110 * @return whether the switch is still disconnected
111 */
112 public final boolean isConnected() {
113 return this.connected;
114 }
115
116 /**
117 * Sets whether the switch is connected.
118 * Only call while holding modifySwitchLock
119 *
120 * @param connected whether the switch is connected
121 */
122 final void setConnected(boolean connected) {
123 this.connected = connected;
124 };
125
126 /**
127 * Sets the Netty Channel this switch instance is associated with.
128 * <p>
129 * Called immediately after instantiation
130 *
131 * @param channel the channel
132 */
133 public final void setChannel(Channel channel) {
134 this.channel = channel;
135 };
136
137 //************************
138 // Switch features related
139 //************************
140
141 /**
142 * Gets the datapathId of the switch.
143 *
144 * @return the switch buffers
145 */
146 public final long getId() {
147 return this.dpid.value();
148 };
149
150 /**
151 * Gets a string version of the ID for this switch.
152 *
153 * @return string version of the ID
154 */
155 public final String getStringId() {
156 return this.dpid.toString();
157 }
158
159 public final void setOFVersion(OFVersion ofV) {
160 this.ofVersion = ofV;
161 }
162
163 void setTableFull(boolean full) {
164 this.tableFull = full;
165 }
166
alshabibd777b202014-08-28 17:52:55 -0700167 public void setFeaturesReply(OFFeaturesReply featuresReply) {
168 this.features = featuresReply;
169 }
alshabib54ebd9c2014-08-27 18:38:41 -0700170
171 /**
172 * Let peoeple know if you support Nicira style role requests.
173 *
174 * @return support Nicira roles or not.
175 */
176 public abstract Boolean supportNxRole();
177
178 //************************
179 // Message handling
180 //************************
181 /**
182 * Handle the message coming from the dataplane.
183 *
184 * @param m the actual message
185 */
186 public final void handleMessage(OFMessage m) {
187 this.agent.processMessage(m);
188 }
189
alshabibd777b202014-08-28 17:52:55 -0700190 public RoleState getRole() {
191 return role;
192 };
alshabib54ebd9c2014-08-27 18:38:41 -0700193
194 final boolean addConnectedSwitch() {
195 return this.agent.addConnectedSwitch(this.getId(), this);
196 }
197
198 final boolean addActivatedMasterSwitch() {
199 return this.agent.addActivatedMasterSwitch(this.getId(), this);
200 }
201
202 final boolean addActivatedEqualSwitch() {
203 return this.agent.addActivatedEqualSwitch(this.getId(), this);
204 }
205
206 final void transitionToEqualSwitch() {
207 this.agent.transitionToEqualSwitch(this.getId());
208 }
209
210 final void transitionToMasterSwitch() {
211 this.agent.transitionToMasterSwitch(this.getId());
212 }
213
214 final void removeConnectedSwitch() {
215 this.agent.removeConnectedSwitch(this.getId());
216 }
217
218 protected OFFactory factory() {
219 return OFFactories.getFactory(ofVersion);
220 }
221
222 public void setPortDescReply(OFPortDescStatsReply portDescReply) {
223 this.ports = portDescReply;
224 }
225
226 public abstract void startDriverHandshake();
227
228 public abstract boolean isDriverHandshakeComplete();
229
230 public abstract void processDriverHandshakeMessage(OFMessage m);
231
232 public void setRole(RoleState role) {
233 try {
alshabibd777b202014-08-28 17:52:55 -0700234 if (this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE)) {
235 this.role = role;
236 }
alshabib54ebd9c2014-08-27 18:38:41 -0700237 } catch (IOException e) {
238 log.error("Unable to write to switch {}.", this.dpid);
239 }
240 }
241
242 // Role Handling
243
244 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 void handleNiciraRole(OFMessage m) throws SwitchStateException {
alshabibd777b202014-08-28 17:52:55 -0700258 RoleState r = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
259 if (r == null) {
260 // The message wasn't really a Nicira role reply. We just
261 // dispatch it to the OFMessage listeners in this case.
262 this.handleMessage(m);
263 }
alshabib54ebd9c2014-08-27 18:38:41 -0700264
alshabibd777b202014-08-28 17:52:55 -0700265 RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
266 new RoleReplyInfo(r, null, m.getXid()));
267 if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
268 if (r == RoleState.MASTER) {
269 this.transitionToMasterSwitch();
270 } else if (r == RoleState.EQUAL ||
271 r == RoleState.SLAVE) {
272 this.transitionToEqualSwitch();
273 }
274 }
alshabib54ebd9c2014-08-27 18:38:41 -0700275 }
276
277 boolean handleRoleError(OFErrorMsg error) {
278 try {
279 return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
280 } catch (SwitchStateException e) {
281 this.disconnectSwitch();
282 }
283 return true;
284 }
285
286 void reassertRole() {
287 if (this.getRole() == RoleState.MASTER) {
288 this.setRole(RoleState.MASTER);
289 }
290 }
291
292 void setAgent(OpenFlowSwitchAgent ag) {
293 this.agent = ag;
294 }
295
alshabibd777b202014-08-28 17:52:55 -0700296 public void setSwitchDescription(OFDescStatsReply desc) {
297 // TODO Auto-generated method stub
298 }
alshabib54ebd9c2014-08-27 18:38:41 -0700299
alshabibd777b202014-08-28 17:52:55 -0700300 protected int getNextTransactionId() {
301 return this.xidCounter.getAndIncrement();
302 }
303
304 protected List<OFPortDesc> getPorts() {
305 return Collections.unmodifiableList(ports.getEntries());
306 }
alshabib54ebd9c2014-08-27 18:38:41 -0700307
308}