tom

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Showing 37 changed files with 778 additions and 1487 deletions
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
63 <configuration> 63 <configuration>
64 <instructions> 64 <instructions>
65 <Export-Package> 65 <Export-Package>
66 - org.projectfloodlight.openflow.* 66 + org.onlab.onos.of.*,org.projectfloodlight.openflow.*
67 </Export-Package> 67 </Export-Package>
68 </instructions> 68 </instructions>
69 </configuration> 69 </configuration>
......
1 -package org.onlab.onos.of.controller;
2 -
3 -/**
4 - * Created by tom on 8/21/14.
5 - */
6 -public interface DeleteMe {
7 -}
1 -package org.onlab.onos.of.controller.impl.util; 1 +package org.onlab.onos.of.controller;
2 2
3 import org.projectfloodlight.openflow.util.HexString; 3 import org.projectfloodlight.openflow.util.HexString;
4 4
......
1 +package org.onlab.onos.of.controller;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFMessage;
4 +
5 +/**
6 + * Abstraction of an OpenFlow controller. Serves as a one stop
7 + * shop for obtaining OpenFlow devices and (un)register listeners
8 + * on OpenFlow events
9 + */
10 +public interface OpenFlowController {
11 +
12 + /**
13 + * Returns all switches known to this OF controller.
14 + * @return Iterable of dpid elements
15 + */
16 + public Iterable<OpenFlowSwitch> getSwitches();
17 +
18 + /**
19 + * Returns all master switches known to this OF controller.
20 + * @return Iterable of dpid elements
21 + */
22 + public Iterable<OpenFlowSwitch> getMasterSwitches();
23 +
24 + /**
25 + * Returns all equal switches known to this OF controller.
26 + * @return Iterable of dpid elements
27 + */
28 + public Iterable<OpenFlowSwitch> getEqualSwitches();
29 +
30 +
31 + /**
32 + * Returns the actual switch for the given Dpid.
33 + * @param dpid the switch to fetch
34 + * @return the interface to this switch
35 + */
36 + public OpenFlowSwitch getSwitch(Dpid dpid);
37 +
38 + /**
39 + * Returns the actual master switch for the given Dpid, if one exists.
40 + * @param dpid the switch to fetch
41 + * @return the interface to this switch
42 + */
43 + public OpenFlowSwitch getMasterSwitch(Dpid dpid);
44 +
45 + /**
46 + * Returns the actual equal switch for the given Dpid, if one exists.
47 + * @param dpid the switch to fetch
48 + * @return the interface to this switch
49 + */
50 + public OpenFlowSwitch getEqualSwitch(Dpid dpid);
51 +
52 + /**
53 + * Register a listener for meta events that occur to OF
54 + * devices.
55 + * @param listener the listener to notify
56 + */
57 + public void addListener(OpenFlowSwitchListener listener);
58 +
59 + /**
60 + * Unregister a listener.
61 + *
62 + * @param listener the listener to unregister
63 + */
64 + public void removeListener(OpenFlowSwitchListener listener);
65 +
66 + /**
67 + * Register a listener for packet events.
68 + * @param priority the importance of this listener, lower values are more important
69 + * @param listener the listener to notify
70 + */
71 + public void addPacketListener(int priority, PacketListener listener);
72 +
73 + /**
74 + * Unregister a listener.
75 + *
76 + * @param listener the listener to unregister
77 + */
78 + public void removePacketListener(PacketListener listener);
79 +
80 + /**
81 + * Send a message to a particular switch.
82 + * @param dpid the switch to send to.
83 + * @param msg the message to send
84 + */
85 + public void write(Dpid dpid, OFMessage msg);
86 +
87 + /**
88 + * Process a message and notify the appropriate listeners.
89 + *
90 + * @param msg the message to process.
91 + */
92 + public void processPacket(OFMessage msg);
93 +
94 + /**
95 + * Sets the role for a given switch.
96 + * @param role the desired role
97 + * @param dpid the switch to set the role for.
98 + */
99 + public void setRole(Dpid dpid, RoleState role);
100 +}
1 +package org.onlab.onos.of.controller;
2 +
3 +import org.projectfloodlight.openflow.protocol.OFMessage;
4 +
5 +/**
6 + * Abstract model of an OpenFlow Switch.
7 + *
8 + */
9 +public interface OpenFlowSwitch {
10 +
11 + /**
12 + * Writes the message to this switch.
13 + *
14 + * @param msg the message to write
15 + */
16 + public void write(OFMessage msg);
17 +
18 + /**
19 + * Handle a message from the switch.
20 + * @param fromSwitch the message to handle
21 + */
22 + public void handleMessage(OFMessage fromSwitch);
23 +}
1 +package org.onlab.onos.of.controller;
2 +
3 +/**
4 + * Meta events that can happen at a switch.
5 + *
6 + */
7 +public enum OpenFlowSwitchEvent {
8 + /**
9 + * The switch connected.
10 + */
11 + SWITCH_CONNECTED,
12 +
13 + /**
14 + * The switch disconnected.
15 + */
16 + SWITCH_DISCONNECTED
17 +}
1 +package org.onlab.onos.of.controller;
2 +
3 +/**
4 + * Allows for providers interested in Switch events to be notified.
5 + */
6 +public interface OpenFlowSwitchListener {
7 +
8 + /**
9 + * Notify that the switch was added.
10 + * @param dpid the switch where the event occurred
11 + */
12 + public void switchAdded(Dpid dpid);
13 +
14 + /**
15 + * Notify that the switch was removed.
16 + * @param dpid the switch where the event occurred.
17 + */
18 + public void switchRemoved(Dpid dpid);
19 +
20 +}
1 +package org.onlab.onos.of.controller;
2 +
3 +import org.projectfloodlight.openflow.types.OFPort;
4 +
5 +/**
6 + * A representation of a packet context which allows any provider
7 + * to view the packet in event but may block the response to the
8 + * event if blocked has been called.
9 + */
10 +public interface PacketContext {
11 +
12 + //TODO: may want to support sending packet out other switches than
13 + // the one it came in on.
14 + /**
15 + * Blocks further responses (ie. send() calls) on this
16 + * packet in event.
17 + */
18 + public void block();
19 +
20 + /**
21 + * Provided build has been called send the packet
22 + * out the switch it came in on.
23 + */
24 + public void send();
25 +
26 + /**
27 + * Build the packet out in response to this packet in event.
28 + * @param outPort the out port to send to packet out of.
29 + */
30 + public void build(OFPort outPort);
31 +
32 + /**
33 + * Build the packet out in response to this packet in event.
34 + * @param ethFrame the actual packet to send out.
35 + * @param outPort the out port to send to packet out of.
36 + */
37 + public void build(Object ethFrame, OFPort outPort);
38 +
39 + /**
40 + * Provided a handle onto the parsed payload.
41 + * @return the parsed form of the payload.
42 + */
43 + public Object parsed();
44 +
45 + /**
46 + * Provide the dpid of the switch where the packet in arrived.
47 + * @return the dpid of the switch.
48 + */
49 + public Dpid dpid();
50 +}
1 +package org.onlab.onos.of.controller;
2 +
3 +/**
4 + * Notifies providers about Packet in events.
5 + */
6 +public interface PacketListener {
7 +
8 + /**
9 + * Handle the packet.
10 + * @param pktCtx the packet context ({@link }
11 + */
12 + public void handlePacket(PacketContext pktCtx);
13 +}
1 -package org.onlab.onos.of.controller.impl; 1 +package org.onlab.onos.of.controller;
2 2
3 import org.projectfloodlight.openflow.protocol.OFControllerRole; 3 import org.projectfloodlight.openflow.protocol.OFControllerRole;
4 4
...@@ -10,27 +10,14 @@ import org.projectfloodlight.openflow.protocol.OFControllerRole; ...@@ -10,27 +10,14 @@ import org.projectfloodlight.openflow.protocol.OFControllerRole;
10 * to the OF1.3 enum, before role messages are sent to the switch. 10 * to the OF1.3 enum, before role messages are sent to the switch.
11 * See sendRoleRequestMessage method in OFSwitchImpl 11 * See sendRoleRequestMessage method in OFSwitchImpl
12 */ 12 */
13 -public enum Role { 13 +public enum RoleState {
14 EQUAL(OFControllerRole.ROLE_EQUAL), 14 EQUAL(OFControllerRole.ROLE_EQUAL),
15 MASTER(OFControllerRole.ROLE_MASTER), 15 MASTER(OFControllerRole.ROLE_MASTER),
16 SLAVE(OFControllerRole.ROLE_SLAVE); 16 SLAVE(OFControllerRole.ROLE_SLAVE);
17 17
18 - private Role(OFControllerRole nxRole) { 18 + private RoleState(OFControllerRole nxRole) {
19 nxRole.ordinal(); 19 nxRole.ordinal();
20 } 20 }
21 - /* 21 +
22 - private static Map<Integer,Role> nxRoleToEnum
23 - = new HashMap<Integer,Role>();
24 - static {
25 - for(Role r: Role.values())
26 - nxRoleToEnum.put(r.toNxRole(), r);
27 - }
28 - public int toNxRole() {
29 - return nxRole;
30 - }
31 - // Return the enum representing the given nxRole or null if no
32 - // such role exists
33 - public static Role fromNxRole(int nxRole) {
34 - return nxRoleToEnum.get(nxRole);
35 - }*/
36 } 22 }
23 +
......
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
38 </properties> 38 </properties>
39 39
40 <dependencies> 40 <dependencies>
41 + <dependency>
42 + <groupId>org.onlab.onos</groupId>
43 + <artifactId>onos-of-api</artifactId>
44 + </dependency>
41 <!-- ONOS's direct dependencies --> 45 <!-- ONOS's direct dependencies -->
42 <dependency> 46 <dependency>
43 <groupId>org.apache.felix</groupId> 47 <groupId>org.apache.felix</groupId>
......
1 -package org.onlab.onos.of.controller.impl.debugcounter;
2 -
3 -public interface IDebugCounter {
4 - /**
5 - * Increments the counter by 1 thread-locally, and immediately flushes to
6 - * the global counter storage. This method should be used for counters that
7 - * are updated outside the OF message processing pipeline.
8 - */
9 - void updateCounterWithFlush();
10 -
11 - /**
12 - * Increments the counter by 1 thread-locally. Flushing to the global
13 - * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
14 - * resulting in higher performance. This method should be used for counters
15 - * updated in the OF message processing pipeline.
16 - */
17 - void updateCounterNoFlush();
18 -
19 - /**
20 - * Increments the counter thread-locally by the 'incr' specified, and immediately
21 - * flushes to the global counter storage. This method should be used for counters
22 - * that are updated outside the OF message processing pipeline.
23 - */
24 - void updateCounterWithFlush(int incr);
25 -
26 - /**
27 - * Increments the counter thread-locally by the 'incr' specified. Flushing to the global
28 - * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
29 - * resulting in higher performance. This method should be used for counters
30 - * updated in the OF message processing pipeline.
31 - */
32 - void updateCounterNoFlush(int incr);
33 -
34 - /**
35 - * Retrieve the value of the counter from the global counter store.
36 - */
37 - long getCounterValue();
38 -}
1 -package org.onlab.onos.of.controller.impl.debugcounter;
2 -
3 -import java.util.Collections;
4 -import java.util.List;
5 -
6 -import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter.DebugCounterInfo;
7 -
8 -//CHECKSTYLE:OFF
9 -public class NullDebugCounter implements IDebugCounterService {
10 -
11 - @Override
12 - public void flushCounters() {
13 -
14 - }
15 -
16 - @Override
17 - public void resetAllCounters() {
18 -
19 - }
20 -
21 - @Override
22 - public void resetAllModuleCounters(String moduleName) {
23 -
24 - }
25 -
26 -
27 - @Override
28 - public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
29 -
30 - }
31 -
32 - @Override
33 - public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
34 -
35 - }
36 -
37 - @Override
38 - public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
39 -
40 - }
41 -
42 - @Override
43 - public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
44 - String counterHierarchy) {
45 - return Collections.emptyList();
46 - }
47 -
48 - @Override
49 - public List<DebugCounterInfo> getAllCounterValues() {
50 - return Collections.emptyList();
51 - }
52 -
53 - @Override
54 - public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
55 - return Collections.emptyList();
56 - }
57 -
58 - @Override
59 - public boolean containsModuleCounterHierarchy(String moduleName,
60 - String counterHierarchy) {
61 - return false;
62 - }
63 -
64 - @Override
65 - public boolean containsModuleName(String moduleName) {
66 - return false;
67 - }
68 -
69 - @Override
70 - public
71 - IDebugCounter
72 - registerCounter(String moduleName, String counterHierarchy,
73 - String counterDescription,
74 - CounterType counterType, String... metaData)
75 - throws MaxCountersRegistered {
76 - return new NullCounterImpl();
77 - }
78 -
79 - @Override
80 - public List<String> getModuleList() {
81 - return Collections.emptyList();
82 - }
83 -
84 - @Override
85 - public List<String> getModuleCounterList(String moduleName) {
86 - return Collections.emptyList();
87 - }
88 -
89 - public static class NullCounterImpl implements IDebugCounter {
90 -
91 - @Override
92 - public void updateCounterWithFlush() {
93 -
94 - }
95 -
96 - @Override
97 - public void updateCounterNoFlush() {
98 -
99 - }
100 -
101 - @Override
102 - public void updateCounterWithFlush(int incr) {
103 - }
104 -
105 - @Override
106 - public void updateCounterNoFlush(int incr) {
107 -
108 - }
109 -
110 - @Override
111 - public long getCounterValue() {
112 - return -1;
113 - }
114 -
115 - }
116 -
117 -}
1 +/**
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 +
18 +package org.onlab.onos.of.controller.impl.internal;
19 +
20 +import java.io.IOException;
21 +import java.util.List;
22 +
23 +import org.jboss.netty.channel.Channel;
24 +import org.onlab.onos.of.controller.Dpid;
25 +import org.onlab.onos.of.controller.OpenFlowSwitch;
26 +import org.onlab.onos.of.controller.RoleState;
27 +import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
28 +import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleRecvStatus;
29 +import org.onlab.onos.of.controller.impl.internal.RoleManager.RoleReplyInfo;
30 +import org.projectfloodlight.openflow.protocol.OFErrorMsg;
31 +import org.projectfloodlight.openflow.protocol.OFExperimenter;
32 +import org.projectfloodlight.openflow.protocol.OFFactories;
33 +import org.projectfloodlight.openflow.protocol.OFFactory;
34 +import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
35 +import org.projectfloodlight.openflow.protocol.OFMessage;
36 +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
37 +import org.projectfloodlight.openflow.protocol.OFRoleReply;
38 +import org.projectfloodlight.openflow.protocol.OFVersion;
39 +import org.slf4j.Logger;
40 +import org.slf4j.LoggerFactory;
41 +
42 +
43 +public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitch {
44 +
45 + private static Logger log =
46 + LoggerFactory.getLogger(AbstractOpenFlowSwitch.class);
47 +
48 + private Channel channel;
49 + private boolean connected;
50 + private Dpid dpid;
51 + private OpenFlowSwitchAgent agent;
52 +
53 + private OFVersion ofVersion;
54 +
55 + protected OFPortDescStatsReply ports;
56 +
57 + protected boolean tableFull;
58 +
59 + private final RoleManager roleMan = new RoleManager(this);
60 +
61 + protected AbstractOpenFlowSwitch(long dpid) {
62 + this.dpid = new Dpid(dpid);
63 + }
64 +
65 + //************************
66 + // Channel related
67 + //************************
68 +
69 + /**
70 + * Disconnects the switch by closing the TCP connection. Results in a call
71 + * to the channel handler's channelDisconnected method for cleanup
72 + * @throws IOException
73 + */
74 + public final void disconnectSwitch() {
75 + this.channel.close();
76 + }
77 +
78 + /**
79 + * Writes to the OFMessage to the output stream.
80 + *
81 + * @param m the message to be written
82 + */
83 + public abstract void write(OFMessage m);
84 +
85 + /**
86 + * Writes to the OFMessage list to the output stream.
87 + *
88 + * @param msgs the messages to be written
89 + */
90 + public abstract void write(List<OFMessage> msgs);
91 +
92 +
93 + /**
94 + * Checks if the switch is still connected.
95 + * Only call while holding processMessageLock
96 + *
97 + * @return whether the switch is still disconnected
98 + */
99 + public final boolean isConnected() {
100 + return this.connected;
101 + }
102 +
103 + /**
104 + * Sets whether the switch is connected.
105 + * Only call while holding modifySwitchLock
106 + *
107 + * @param connected whether the switch is connected
108 + */
109 + final void setConnected(boolean connected) {
110 + this.connected = connected;
111 + };
112 +
113 + /**
114 + * Sets the Netty Channel this switch instance is associated with.
115 + * <p>
116 + * Called immediately after instantiation
117 + *
118 + * @param channel the channel
119 + */
120 + public final void setChannel(Channel channel) {
121 + this.channel = channel;
122 + };
123 +
124 + //************************
125 + // Switch features related
126 + //************************
127 +
128 + /**
129 + * Gets the datapathId of the switch.
130 + *
131 + * @return the switch buffers
132 + */
133 + public final long getId() {
134 + return this.dpid.value();
135 + };
136 +
137 + /**
138 + * Gets a string version of the ID for this switch.
139 + *
140 + * @return string version of the ID
141 + */
142 + public final String getStringId() {
143 + return this.dpid.toString();
144 + }
145 +
146 + public final void setOFVersion(OFVersion ofV) {
147 + this.ofVersion = ofV;
148 + }
149 +
150 + void setTableFull(boolean full) {
151 + this.tableFull = full;
152 + }
153 +
154 + public abstract void setFeaturesReply(OFFeaturesReply featuresReply);
155 +
156 + /**
157 + * Let peoeple know if you support Nicira style role requests.
158 + *
159 + * @return support Nicira roles or not.
160 + */
161 + public abstract Boolean supportNxRole();
162 +
163 + //************************
164 + // Message handling
165 + //************************
166 + /**
167 + * Handle the message coming from the dataplane.
168 + *
169 + * @param m the actual message
170 + */
171 + public final void handleMessage(OFMessage m) {
172 + this.agent.processMessage(m);
173 + }
174 +
175 + public abstract RoleState getRole();
176 +
177 + final boolean addConnectedSwitch() {
178 + return this.agent.addConnectedSwitch(this.getId(), this);
179 + }
180 +
181 + final boolean addActivatedMasterSwitch() {
182 + return this.agent.addActivatedMasterSwitch(this.getId(), this);
183 + }
184 +
185 + final boolean addActivatedEqualSwitch() {
186 + return this.agent.addActivatedEqualSwitch(this.getId(), this);
187 + }
188 +
189 + final void transitionToEqualSwitch() {
190 + this.agent.transitionToEqualSwitch(this.getId());
191 + }
192 +
193 + final void transitionToMasterSwitch() {
194 + this.agent.transitionToMasterSwitch(this.getId());
195 + }
196 +
197 + final void removeConnectedSwitch() {
198 + this.agent.removeConnectedSwitch(this.getId());
199 + }
200 +
201 + protected OFFactory factory() {
202 + return OFFactories.getFactory(ofVersion);
203 + }
204 +
205 + public void setPortDescReply(OFPortDescStatsReply portDescReply) {
206 + this.ports = portDescReply;
207 + }
208 +
209 + public abstract void startDriverHandshake();
210 +
211 + public abstract boolean isDriverHandshakeComplete();
212 +
213 + public abstract void processDriverHandshakeMessage(OFMessage m);
214 +
215 + public void setRole(RoleState role) {
216 + try {
217 + this.roleMan.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE);
218 + } catch (IOException e) {
219 + log.error("Unable to write to switch {}.", this.dpid);
220 + }
221 + }
222 +
223 + // Role Handling
224 +
225 + void handleRole(OFMessage m) throws SwitchStateException {
226 + RoleReplyInfo rri = roleMan.extractOFRoleReply((OFRoleReply) m);
227 + RoleRecvStatus rrs = roleMan.deliverRoleReply(rri);
228 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
229 + if (rri.getRole() == RoleState.MASTER) {
230 + this.transitionToMasterSwitch();
231 + } else if (rri.getRole() == RoleState.EQUAL ||
232 + rri.getRole() == RoleState.MASTER) {
233 + this.transitionToEqualSwitch();
234 + }
235 + }
236 + }
237 +
238 + void handleNiciraRole(OFMessage m) throws SwitchStateException {
239 + RoleState role = this.roleMan.extractNiciraRoleReply((OFExperimenter) m);
240 + if (role == null) {
241 + // The message wasn't really a Nicira role reply. We just
242 + // dispatch it to the OFMessage listeners in this case.
243 + this.handleMessage(m);
244 + }
245 +
246 + RoleRecvStatus rrs = this.roleMan.deliverRoleReply(
247 + new RoleReplyInfo(role, null, m.getXid()));
248 + if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
249 + if (role == RoleState.MASTER) {
250 + this.transitionToMasterSwitch();
251 + } else if (role == RoleState.EQUAL ||
252 + role == RoleState.SLAVE) {
253 + this.transitionToEqualSwitch();
254 + }
255 + }
256 + }
257 +
258 + boolean handleRoleError(OFErrorMsg error) {
259 + try {
260 + return RoleRecvStatus.OTHER_EXPECTATION != this.roleMan.deliverError(error);
261 + } catch (SwitchStateException e) {
262 + this.disconnectSwitch();
263 + }
264 + return true;
265 + }
266 +
267 + void reassertRole() {
268 + if (this.getRole() == RoleState.MASTER) {
269 + this.setRole(RoleState.MASTER);
270 + }
271 + }
272 +
273 + void setAgent(OpenFlowSwitchAgent ag) {
274 + this.agent = ag;
275 + }
276 +
277 +
278 +
279 +}
1 -package org.onlab.onos.of.controller.impl; 1 +package org.onlab.onos.of.controller.impl.internal;
2 2
3 import org.projectfloodlight.openflow.protocol.OFVersion; 3 import org.projectfloodlight.openflow.protocol.OFVersion;
4 4
5 -import org.onlab.onos.of.controller.impl.registry.IControllerRegistry;
6 5
7 /** 6 /**
8 * Interface to passed to controller class in order to allow 7 * Interface to passed to controller class in order to allow
...@@ -22,12 +21,6 @@ public interface IOFSwitchManager { ...@@ -22,12 +21,6 @@ public interface IOFSwitchManager {
22 * @param ofv openflow version 21 * @param ofv openflow version
23 * @return A switch of type IOFSwitch. 22 * @return A switch of type IOFSwitch.
24 */ 23 */
25 - public IOFSwitch getSwitchImpl(String mfr, String hwDesc, String swDesc, OFVersion ofv); 24 + public AbstractOpenFlowSwitch getSwitchImpl(String mfr, String hwDesc, String swDesc, OFVersion ofv);
26 -
27 - /**
28 - * Returns the mastership registry used during controller-switch role election.
29 - * @return the registry
30 - */
31 - public IControllerRegistry getRegistry();
32 25
33 } 26 }
......
1 +package org.onlab.onos.of.controller.impl.internal;
2 +
3 +import java.util.ArrayList;
4 +import java.util.concurrent.ConcurrentHashMap;
5 +import java.util.concurrent.locks.Lock;
6 +import java.util.concurrent.locks.ReentrantLock;
7 +
8 +import org.apache.felix.scr.annotations.Activate;
9 +import org.apache.felix.scr.annotations.Component;
10 +import org.apache.felix.scr.annotations.Deactivate;
11 +import org.apache.felix.scr.annotations.Service;
12 +import org.onlab.onos.of.controller.Dpid;
13 +import org.onlab.onos.of.controller.OpenFlowController;
14 +import org.onlab.onos.of.controller.OpenFlowSwitch;
15 +import org.onlab.onos.of.controller.OpenFlowSwitchListener;
16 +import org.onlab.onos.of.controller.PacketListener;
17 +import org.onlab.onos.of.controller.RoleState;
18 +import org.projectfloodlight.openflow.protocol.OFMessage;
19 +import org.projectfloodlight.openflow.util.HexString;
20 +import org.slf4j.Logger;
21 +import org.slf4j.LoggerFactory;
22 +
23 +@Component(immediate = true)
24 +@Service
25 +public class OpenFlowControllerImpl implements OpenFlowController {
26 +
27 + protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches;
28 + protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches;
29 + protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches;
30 +
31 + protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
32 + protected ArrayList<OpenFlowSwitchListener> ofEventListener;
33 +
34 + private final Controller ctrl = new Controller();
35 +
36 + @Activate
37 + public void activate() {
38 + ctrl.start(agent);
39 + }
40 +
41 + @Deactivate
42 + public void deactivate() {
43 + ctrl.stop();
44 + }
45 +
46 + @Override
47 + public Iterable<OpenFlowSwitch> getSwitches() {
48 + return connectedSwitches.values();
49 + }
50 +
51 + @Override
52 + public Iterable<OpenFlowSwitch> getMasterSwitches() {
53 + return activeMasterSwitches.values();
54 + }
55 +
56 + @Override
57 + public Iterable<OpenFlowSwitch> getEqualSwitches() {
58 + return activeEqualSwitches.values();
59 + }
60 +
61 + @Override
62 + public OpenFlowSwitch getSwitch(Dpid dpid) {
63 + return connectedSwitches.get(dpid.value());
64 + }
65 +
66 + @Override
67 + public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
68 + return activeMasterSwitches.get(dpid.value());
69 + }
70 +
71 + @Override
72 + public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
73 + return activeEqualSwitches.get(dpid.value()); }
74 +
75 + @Override
76 + public void addListener(OpenFlowSwitchListener listener) {
77 + if (!ofEventListener.contains(listener)) {
78 + this.ofEventListener.add(listener);
79 + }
80 + }
81 +
82 + @Override
83 + public void removeListener(OpenFlowSwitchListener listener) {
84 + this.ofEventListener.remove(listener);
85 + }
86 +
87 + @Override
88 + public void addPacketListener(int priority, PacketListener listener) {
89 + // TODO Auto-generated method stub
90 +
91 + }
92 +
93 + @Override
94 + public void removePacketListener(PacketListener listener) {
95 + // TODO Auto-generated method stub
96 +
97 + }
98 +
99 + @Override
100 + public void write(Dpid dpid, OFMessage msg) {
101 + this.getSwitch(dpid).write(msg);
102 + }
103 +
104 + @Override
105 + public void processPacket(OFMessage msg) {
106 + }
107 +
108 + @Override
109 + public void setRole(Dpid dpid, RoleState role) {
110 + switch (role) {
111 + case MASTER:
112 + agent.transitionToMasterSwitch(dpid.value());
113 + break;
114 + case EQUAL:
115 + agent.transitionToEqualSwitch(dpid.value());
116 + break;
117 + case SLAVE:
118 + //agent.transitionToSlaveSwitch(dpid.value());
119 + break;
120 + default:
121 + //WTF role is this?
122 + }
123 +
124 + }
125 +
126 + public class OpenFlowSwitchAgent {
127 +
128 + private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
129 + private Lock switchLock = new ReentrantLock();
130 +
131 + public boolean addConnectedSwitch(long dpid, AbstractOpenFlowSwitch sw) {
132 + if (connectedSwitches.get(dpid) != null) {
133 + log.error("Trying to add connectedSwitch but found a previous "
134 + + "value for dpid: {}", dpid);
135 + return false;
136 + } else {
137 + log.error("Added switch {}", dpid);
138 + connectedSwitches.put(dpid, sw);
139 + for (OpenFlowSwitchListener l : ofEventListener) {
140 + l.switchAdded(new Dpid(dpid));
141 + }
142 + return true;
143 + }
144 + }
145 +
146 + private boolean validActivation(long dpid) {
147 + if (connectedSwitches.get(dpid) == null) {
148 + log.error("Trying to activate switch but is not in "
149 + + "connected switches: dpid {}. Aborting ..",
150 + HexString.toHexString(dpid));
151 + return false;
152 + }
153 + if (activeMasterSwitches.get(dpid) != null ||
154 + activeEqualSwitches.get(dpid) != null) {
155 + log.error("Trying to activate switch but it is already "
156 + + "activated: dpid {}. Found in activeMaster: {} "
157 + + "Found in activeEqual: {}. Aborting ..", new Object[] {
158 + HexString.toHexString(dpid),
159 + (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
160 + (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
161 + return false;
162 + }
163 + return true;
164 + }
165 +
166 + /**
167 + * Called when a switch is activated, with this controller's role as MASTER.
168 + */
169 + protected boolean addActivatedMasterSwitch(long dpid, AbstractOpenFlowSwitch sw) {
170 + switchLock.lock();
171 + try {
172 + if (!validActivation(dpid)) {
173 + return false;
174 + }
175 + activeMasterSwitches.put(dpid, sw);
176 + return true;
177 + } finally {
178 + switchLock.unlock();
179 + }
180 + }
181 +
182 + /**
183 + * Called when a switch is activated, with this controller's role as EQUAL.
184 + */
185 + protected boolean addActivatedEqualSwitch(long dpid, AbstractOpenFlowSwitch sw) {
186 + switchLock.lock();
187 + try {
188 + if (!validActivation(dpid)) {
189 + return false;
190 + }
191 + activeEqualSwitches.put(dpid, sw);
192 + return true;
193 + } finally {
194 + switchLock.unlock();
195 + }
196 + }
197 +
198 + /**
199 + * Called when this controller's role for a switch transitions from equal
200 + * to master. For 1.0 switches, we internally refer to the role 'slave' as
201 + * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
202 + */
203 + protected void transitionToMasterSwitch(long dpid) {
204 + switchLock.lock();
205 + try {
206 + OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
207 + if (sw == null) {
208 + log.error("Transition to master called on sw {}, but switch "
209 + + "was not found in controller-cache", dpid);
210 + return;
211 + }
212 + activeMasterSwitches.put(dpid, sw);
213 + } finally {
214 + switchLock.unlock();
215 + }
216 + }
217 +
218 +
219 + /**
220 + * Called when this controller's role for a switch transitions to equal.
221 + * For 1.0 switches, we internally refer to the role 'slave' as
222 + * 'equal'.
223 + */
224 + protected void transitionToEqualSwitch(long dpid) {
225 + switchLock.lock();
226 + try {
227 + OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
228 + if (sw == null) {
229 + log.error("Transition to equal called on sw {}, but switch "
230 + + "was not found in controller-cache", dpid);
231 + return;
232 + }
233 + activeEqualSwitches.put(dpid, sw);
234 + } finally {
235 + switchLock.unlock();
236 + }
237 +
238 + }
239 +
240 + /**
241 + * Clear all state in controller switch maps for a switch that has
242 + * disconnected from the local controller. Also release control for
243 + * that switch from the global repository. Notify switch listeners.
244 + */
245 + public void removeConnectedSwitch(long dpid) {
246 + connectedSwitches.remove(dpid);
247 + OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
248 + if (sw == null) {
249 + sw = activeEqualSwitches.remove(dpid);
250 + }
251 + for (OpenFlowSwitchListener l : ofEventListener) {
252 + l.switchRemoved(new Dpid(dpid));
253 + }
254 + }
255 +
256 + public void processMessage(OFMessage m) {
257 + processPacket(m);
258 + }
259 + }
260 +
261 +
262 +
263 +}
1 -package org.onlab.onos.of.controller.impl.registry;
2 -
3 -
4 -
5 -public class ControllerRegistryEntry implements Comparable<ControllerRegistryEntry> {
6 - //
7 - // TODO: Refactor the implementation and decide whether controllerId
8 - // is needed. If "yes", we might need to consider it inside the
9 - // compareTo(), equals() and hashCode() implementations.
10 - //
11 - private final String controllerId;
12 - private final int sequenceNumber;
13 -
14 - public ControllerRegistryEntry(String controllerId, int sequenceNumber) {
15 - this.controllerId = controllerId;
16 - this.sequenceNumber = sequenceNumber;
17 - }
18 -
19 - public String getControllerId() {
20 - return controllerId;
21 - }
22 -
23 - /**
24 - * Compares this object with the specified object for order.
25 - * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
26 - * and doesn't include the controllerId.
27 - *
28 - * @param o the object to be compared.
29 - * @return a negative integer, zero, or a positive integer as this object
30 - * is less than, equal to, or greater than the specified object.
31 - */
32 - @Override
33 - public int compareTo(ControllerRegistryEntry o) {
34 - return this.sequenceNumber - o.sequenceNumber;
35 - }
36 -
37 - /**
38 - * Test whether some other object is "equal to" this one.
39 - * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
40 - * and doesn't include the controllerId.
41 - *
42 - * @param obj the reference object with which to compare.
43 - * @return true if this object is the same as the obj argument; false
44 - * otherwise.
45 - */
46 - @Override
47 - public boolean equals(Object obj) {
48 - if (obj instanceof ControllerRegistryEntry) {
49 - ControllerRegistryEntry other = (ControllerRegistryEntry) obj;
50 - return this.sequenceNumber == other.sequenceNumber;
51 - }
52 - return false;
53 - }
54 -
55 - /**
56 - * Get the hash code for the object.
57 - * NOTE: the computation is based on ControllerRegistryEntry sequence
58 - * numbers, and doesn't include the controller ID.
59 - *
60 - * @return a hash code value for this object.
61 - */
62 - @Override
63 - public int hashCode() {
64 - return Integer.valueOf(this.sequenceNumber).hashCode();
65 - }
66 -}
1 -package org.onlab.onos.of.controller.impl.registry;
2 -
3 -import java.util.Collection;
4 -import java.util.List;
5 -import java.util.Map;
6 -
7 -import org.onlab.onos.of.controller.impl.util.InstanceId;
8 -
9 -/**
10 - * A registry service that allows ONOS to register controllers and switches in a
11 - * way that is global to the entire ONOS cluster. The registry is the arbiter
12 - * for allowing controllers to control switches.
13 - * <p/>
14 - * The OVS/OF1.{2,3} fault tolerance model is a switch connects to multiple
15 - * controllers, and the controllers send role requests to tell the switch their
16 - * role in controlling the switch.
17 - * <p/>
18 - * The ONOS fault tolerance model allows only a single controller to have
19 - * control of a switch (MASTER role) at once. Controllers therefore need a
20 - * mechanism that enables them to decide who should control a each switch. The
21 - * registry service provides this mechanism.
22 - */
23 -public interface IControllerRegistry {
24 -
25 - /**
26 - * Callback interface for control change events.
27 - */
28 - public interface ControlChangeCallback {
29 - /**
30 - * Called whenever the control changes from the point of view of the
31 - * registry. The callee can check whether they have control or not using
32 - * the hasControl parameter.
33 - *
34 - * @param dpid The switch that control has changed for
35 - * @param hasControl Whether the listener now has control or not
36 - */
37 - void controlChanged(long dpid, boolean hasControl);
38 - }
39 -
40 - /**
41 - * Request for control of a switch. This method does not block. When control
42 - * for a switch changes, the controlChanged method on the callback object
43 - * will be called. This happens any time the control changes while the
44 - * request is still active (until releaseControl is called)
45 - *
46 - * @param dpid Switch to request control for
47 - * @param cb Callback that will be used to notify caller of control changes
48 - * @throws RegistryException Errors contacting the registry service
49 - */
50 - public void requestControl(long dpid, ControlChangeCallback cb)
51 - throws RegistryException;
52 -
53 - /**
54 - * Stop trying to take control of a switch. This removes the entry for this
55 - * controller requesting this switch in the registry. If the controller had
56 - * control when this is called, another controller will now gain control of
57 - * the switch. This call doesn't block.
58 - *
59 - * @param dpid Switch to release control of
60 - */
61 - public void releaseControl(long dpid);
62 -
63 - /**
64 - * Check whether the controller has control of the switch This call doesn't
65 - * block.
66 - *
67 - * @param dpid Switch to check control of
68 - * @return true if controller has control of the switch.
69 - */
70 - public boolean hasControl(long dpid);
71 -
72 - /**
73 - * Check whether this instance is the leader for the cluster. This call
74 - * doesn't block.
75 - *
76 - * @return true if the instance is the leader for the cluster, otherwise
77 - * false.
78 - */
79 - public boolean isClusterLeader();
80 -
81 - /**
82 - * Gets the unique ID used to identify this ONOS instance in the cluster.
83 - *
84 - * @return Instance ID.
85 - */
86 - public InstanceId getOnosInstanceId();
87 -
88 - /**
89 - * Register a controller to the ONOS cluster. Must be called before the
90 - * registry can be used to take control of any switches.
91 - *
92 - * @param controllerId A unique string ID identifying this controller in the
93 - * cluster
94 - * @throws RegistryException for errors connecting to registry service,
95 - * controllerId already registered
96 - */
97 - public void registerController(String controllerId)
98 - throws RegistryException;
99 -
100 - /**
101 - * Get all controllers in the cluster.
102 - *
103 - * @return Collection of controller IDs
104 - * @throws RegistryException on error
105 - */
106 - public Collection<String> getAllControllers() throws RegistryException;
107 -
108 - /**
109 - * Get all switches in the cluster, along with which controller is in
110 - * control of them (if any) and any other controllers that have requested
111 - * control.
112 - *
113 - * @return Map of all switches.
114 - */
115 - public Map<String, List<ControllerRegistryEntry>> getAllSwitches();
116 -
117 - /**
118 - * Get the controller that has control of a given switch.
119 - *
120 - * @param dpid Switch to find controller for
121 - * @return controller ID
122 - * @throws RegistryException Errors contacting registry service
123 - */
124 - public String getControllerForSwitch(long dpid) throws RegistryException;
125 -
126 - /**
127 - * Get all switches controlled by a given controller.
128 - *
129 - * @param controllerId ID of the controller
130 - * @return Collection of dpids
131 - */
132 - public Collection<Long> getSwitchesControlledByController(String controllerId);
133 -
134 - /**
135 - * Get a unique Id Block.
136 - *
137 - * @return Id Block.
138 - */
139 - public IdBlock allocateUniqueIdBlock();
140 -
141 - /**
142 - * Get next unique id and retrieve a new range of ids if needed.
143 - *
144 - * @param range range to use for the identifier
145 - * @return Id Block.
146 - */
147 - public IdBlock allocateUniqueIdBlock(long range);
148 -
149 - /**
150 - * Get a globally unique ID.
151 - *
152 - * @return a globally unique ID.
153 - */
154 - public long getNextUniqueId();
155 -}
1 -package org.onlab.onos.of.controller.impl.registry;
2 -
3 -public class IdBlock {
4 - private final long start;
5 - private final long end;
6 - private final long size;
7 -
8 - public IdBlock(long start, long end, long size) {
9 - this.start = start;
10 - this.end = end;
11 - this.size = size;
12 - }
13 -
14 - public long getStart() {
15 - return start;
16 - }
17 -
18 - public long getEnd() {
19 - return end;
20 - }
21 -
22 - public long getSize() {
23 - return size;
24 - }
25 -
26 - @Override
27 - public String toString() {
28 - return "IdBlock [start=" + start + ", end=" + end + ", size=" + size
29 - + "]";
30 - }
31 -}
32 -
1 -package org.onlab.onos.of.controller.impl.registry;
2 -
3 -public class RegistryException extends Exception {
4 -
5 - private static final long serialVersionUID = -8276300722010217913L;
6 -
7 - public RegistryException(String message) {
8 - super(message);
9 - }
10 -
11 - public RegistryException(String message, Throwable cause) {
12 - super(message, cause);
13 - }
14 -
15 -}
1 -package org.onlab.onos.of.controller.impl.util;
2 -
3 -import java.io.IOException;
4 -import java.util.Collection;
5 -import java.util.Date;
6 -import java.util.List;
7 -import java.util.Map;
8 -import java.util.Set;
9 -import java.util.concurrent.Future;
10 -
11 -import org.jboss.netty.channel.Channel;
12 -import org.projectfloodlight.openflow.protocol.OFActionType;
13 -import org.projectfloodlight.openflow.protocol.OFCapabilities;
14 -import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
15 -import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
16 -import org.projectfloodlight.openflow.protocol.OFMessage;
17 -import org.projectfloodlight.openflow.protocol.OFPortDesc;
18 -import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
19 -import org.projectfloodlight.openflow.protocol.OFPortStatus;
20 -import org.projectfloodlight.openflow.protocol.OFStatsReply;
21 -import org.projectfloodlight.openflow.protocol.OFStatsRequest;
22 -import org.projectfloodlight.openflow.protocol.OFVersion;
23 -import org.projectfloodlight.openflow.types.DatapathId;
24 -import org.projectfloodlight.openflow.types.U64;
25 -import org.slf4j.Logger;
26 -import org.slf4j.LoggerFactory;
27 -
28 -import org.onlab.onos.of.controller.impl.IOFSwitch;
29 -import org.onlab.onos.of.controller.impl.Role;
30 -import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
31 -import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService.CounterException;
32 -
33 -public class DummySwitchForTesting implements IOFSwitch {
34 -
35 - protected static final Logger log = LoggerFactory.getLogger(DummySwitchForTesting.class);
36 -
37 - private Channel channel;
38 - private boolean connected = false;
39 - private OFVersion ofv = OFVersion.OF_10;
40 -
41 - private Collection<OFPortDesc> ports;
42 -
43 - private DatapathId datapathId;
44 -
45 - private Set<OFCapabilities> capabilities;
46 -
47 - private int buffers;
48 -
49 - private byte tables;
50 -
51 - private String stringId;
52 -
53 - private Role role;
54 -
55 - @Override
56 - public void disconnectSwitch() {
57 - this.channel.close();
58 - }
59 -
60 - @Override
61 - public void write(OFMessage m) throws IOException {
62 - this.channel.write(m);
63 -
64 - }
65 -
66 - @Override
67 - public void write(List<OFMessage> msglist) throws IOException {
68 - for (OFMessage m : msglist) {
69 - this.channel.write(m);
70 - }
71 -
72 - }
73 -
74 - @Override
75 - public Date getConnectedSince() {
76 - // TODO Auto-generated method stub
77 - return null;
78 - }
79 -
80 - @Override
81 - public int getNextTransactionId() {
82 - return 0;
83 - }
84 -
85 - @Override
86 - public boolean isConnected() {
87 - return this.connected;
88 - }
89 -
90 - @Override
91 - public void setConnected(boolean connected) {
92 - this.connected = connected;
93 -
94 - }
95 -
96 - @Override
97 - public void flush() {
98 - // TODO Auto-generated method stub
99 -
100 - }
101 -
102 - @Override
103 - public void setChannel(Channel channel) {
104 - this.channel = channel;
105 -
106 - }
107 -
108 - @Override
109 - public long getId() {
110 - if (this.stringId == null) {
111 - throw new RuntimeException("Features reply has not yet been set");
112 - }
113 - return this.datapathId.getLong();
114 - }
115 -
116 - @Override
117 - public String getStringId() {
118 - // TODO Auto-generated method stub
119 - return "DummySwitch";
120 - }
121 -
122 - @Override
123 - public int getNumBuffers() {
124 - // TODO Auto-generated method stub
125 - return 0;
126 - }
127 -
128 - @Override
129 - public Set<OFCapabilities> getCapabilities() {
130 - // TODO Auto-generated method stub
131 - return null;
132 - }
133 -
134 - @Override
135 - public byte getNumTables() {
136 - // TODO Auto-generated method stub
137 - return 0;
138 - }
139 -
140 - @Override
141 - public OFDescStatsReply getSwitchDescription() {
142 - // TODO Auto-generated method stub
143 - return null;
144 - }
145 -
146 - @Override
147 - public void cancelFeaturesReply(int transactionId) {
148 - // TODO Auto-generated method stub
149 -
150 - }
151 -
152 - @Override
153 - public Set<OFActionType> getActions() {
154 - // TODO Auto-generated method stub
155 - return null;
156 - }
157 -
158 - @Override
159 - public void setOFVersion(OFVersion version) {
160 - // TODO Auto-generated method stub
161 -
162 - }
163 -
164 - @Override
165 - public OFVersion getOFVersion() {
166 - return this.ofv;
167 - }
168 -
169 - @Override
170 - public Collection<OFPortDesc> getEnabledPorts() {
171 - // TODO Auto-generated method stub
172 - return null;
173 - }
174 -
175 - @Override
176 - public Collection<Integer> getEnabledPortNumbers() {
177 - // TODO Auto-generated method stub
178 - return null;
179 - }
180 -
181 - @Override
182 - public OFPortDesc getPort(int portNumber) {
183 - // TODO Auto-generated method stub
184 - return null;
185 - }
186 -
187 - @Override
188 - public OFPortDesc getPort(String portName) {
189 - // TODO Auto-generated method stub
190 - return null;
191 - }
192 -
193 - @Override
194 - public OrderedCollection<PortChangeEvent> processOFPortStatus(
195 - OFPortStatus ps) {
196 - // TODO Auto-generated method stub
197 - return null;
198 - }
199 -
200 - @Override
201 - public Collection<OFPortDesc> getPorts() {
202 - return ports;
203 - }
204 -
205 - @Override
206 - public boolean portEnabled(int portName) {
207 - // TODO Auto-generated method stub
208 - return false;
209 - }
210 -
211 - @Override
212 - public OrderedCollection<PortChangeEvent> setPorts(
213 - Collection<OFPortDesc> p) {
214 - this.ports = p;
215 - return null;
216 - }
217 -
218 - @Override
219 - public Map<Object, Object> getAttributes() {
220 - return null;
221 - }
222 -
223 - @Override
224 - public boolean hasAttribute(String name) {
225 - // TODO Auto-generated method stub
226 - return false;
227 - }
228 -
229 - @Override
230 - public Object getAttribute(String name) {
231 - return Boolean.FALSE;
232 - }
233 -
234 - @Override
235 - public void setAttribute(String name, Object value) {
236 - // TODO Auto-generated method stub
237 -
238 - }
239 -
240 - @Override
241 - public Object removeAttribute(String name) {
242 - // TODO Auto-generated method stub
243 - return null;
244 - }
245 -
246 - @Override
247 - public void deliverStatisticsReply(OFMessage reply) {
248 - // TODO Auto-generated method stub
249 -
250 - }
251 -
252 - @Override
253 - public void cancelStatisticsReply(int transactionId) {
254 - // TODO Auto-generated method stub
255 -
256 - }
257 -
258 - @Override
259 - public void cancelAllStatisticsReplies() {
260 - // TODO Auto-generated method stub
261 -
262 - }
263 -
264 - @Override
265 - public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
266 - throws IOException {
267 - // TODO Auto-generated method stub
268 - return null;
269 - }
270 -
271 - @Override
272 - public void clearAllFlowMods() {
273 - // TODO Auto-generated method stub
274 -
275 - }
276 -
277 - @Override
278 - public Role getRole() {
279 - return this.role;
280 - }
281 -
282 - @Override
283 - public void setRole(Role role) {
284 - this.role = role;
285 - }
286 -
287 - @Override
288 - public U64 getNextGenerationId() {
289 - // TODO Auto-generated method stub
290 - return null;
291 - }
292 -
293 - @Override
294 - public void setDebugCounterService(IDebugCounterService debugCounter)
295 - throws CounterException {
296 - // TODO Auto-generated method stub
297 -
298 - }
299 -
300 - @Override
301 - public void startDriverHandshake() throws IOException {
302 - // TODO Auto-generated method stub
303 -
304 - }
305 -
306 - @Override
307 - public boolean isDriverHandshakeComplete() {
308 - return true;
309 - }
310 -
311 - @Override
312 - public void processDriverHandshakeMessage(OFMessage m) {
313 -
314 - }
315 -
316 - @Override
317 - public void setTableFull(boolean isFull) {
318 - // TODO Auto-generated method stub
319 -
320 - }
321 -
322 - @Override
323 - public void setFeaturesReply(OFFeaturesReply featuresReply) {
324 - if (featuresReply == null) {
325 - log.error("Error setting featuresReply for switch: {}", getStringId());
326 - return;
327 - }
328 - this.datapathId = featuresReply.getDatapathId();
329 - this.capabilities = featuresReply.getCapabilities();
330 - this.buffers = (int) featuresReply.getNBuffers();
331 - this.tables = (byte) featuresReply.getNTables();
332 - this.stringId = this.datapathId.toString();
333 -
334 - }
335 -
336 - @Override
337 - public void setPortDescReply(OFPortDescStatsReply portDescReply) {
338 - // TODO Auto-generated method stub
339 -
340 - }
341 -
342 - @Override
343 - public void handleMessage(OFMessage m) {
344 - log.info("Got packet {} but I am dumb so I don't know what to do.", m);
345 - }
346 -
347 - @Override
348 - public boolean portEnabled(String portName) {
349 - // TODO Auto-generated method stub
350 - return false;
351 - }
352 -
353 - @Override
354 - public OrderedCollection<PortChangeEvent> comparePorts(
355 - Collection<OFPortDesc> p) {
356 - // TODO Auto-generated method stub
357 - return null;
358 - }
359 -
360 -}
1 -package org.onlab.onos.of.controller.impl.util;
2 -
3 -import java.util.EnumSet;
4 -import java.util.Set;
5 -
6 -/**
7 - * A utility class to convert between integer based bitmaps for (OpenFlow)
8 - * flags and Enum and EnumSet based representations.
9 - *
10 - * The enum used to represent individual flags needs to implement the
11 - * BitmapableEnum interface.
12 - *
13 - * Example:
14 - * {@code
15 - * int bitmap = 0x11; // OFPPC_PORT_DOWN | OFPPC_NO_STP
16 - * EnumSet<OFPortConfig> s = toEnumSet(OFPortConfig.class, bitmap);
17 - * // s will contain OFPPC_PORT_DOWN and OFPPC_NO_STP
18 - * }
19 - *
20 - * {@code
21 - * EnumSet<OFPortConfig> s = EnumSet.of(OFPPC_NO_STP, OFPPC_PORT_DOWN);
22 - * int bitmap = toBitmap(s); // returns 0x11
23 - * }
24 - *
25 - */
26 -public final class EnumBitmaps {
27 -
28 -
29 - private EnumBitmaps() { }
30 -
31 - /**
32 - * Enums used to represent individual flags needs to implement this
33 - * interface.
34 - */
35 - public interface BitmapableEnum {
36 - /** Return the value in the bitmap that the enum constant represents.
37 - * The returned value must have only a single bit set. E.g.,1 << 3
38 - */
39 - int getValue();
40 - }
41 -
42 -
43 - /**
44 - * Convert an integer bitmap to an EnumSet.
45 - *
46 - * See class description for example
47 - * @param type The Enum class to use. Must implement BitmapableEnum
48 - * @param bitmap The integer bitmap
49 - * @return A newly allocated EnumSet representing the bits set in the
50 - * bitmap
51 - * @throws NullPointerException if type is null
52 - * @throws IllegalArgumentException if any enum constant from type has
53 - * more than one bit set.
54 - * @throws IllegalArgumentException if the bitmap has any bits set not
55 - * represented by an enum constant.
56 - */
57 - public static <E extends Enum<E> & BitmapableEnum>
58 - EnumSet<E> toEnumSet(Class<E> type, int bitmap) {
59 - if (type == null) {
60 - throw new NullPointerException("Given enum type must not be null");
61 - }
62 - EnumSet<E> s = EnumSet.noneOf(type);
63 - // allSetBitmap will eventually have all valid bits for the given
64 - // type set.
65 - int allSetBitmap = 0;
66 - for (E element: type.getEnumConstants()) {
67 - if (Integer.bitCount(element.getValue()) != 1) {
68 - String msg = String.format("The %s (%x) constant of the " +
69 - "enum %s is supposed to represent a bitmap entry but " +
70 - "has more than one bit set.",
71 - element.toString(), element.getValue(), type.getName());
72 - throw new IllegalArgumentException(msg);
73 - }
74 - allSetBitmap |= element.getValue();
75 - if ((bitmap & element.getValue()) != 0) {
76 - s.add(element);
77 - }
78 - }
79 - if (((~allSetBitmap) & bitmap) != 0) {
80 - // check if only valid flags are set in the given bitmap
81 - String msg = String.format("The bitmap %x for enum %s has " +
82 - "bits set that are presented by any enum constant",
83 - bitmap, type.getName());
84 - throw new IllegalArgumentException(msg);
85 - }
86 - return s;
87 - }
88 -
89 - /**
90 - * Return the bitmap mask with all possible bits set. E.g., If a bitmap
91 - * has the individual flags 0x1, 0x2, and 0x8 (note the missing 0x4) then
92 - * the mask will be 0xb (1011 binary)
93 - *
94 - * @param type The Enum class to use. Must implement BitmapableEnum
95 - * @throws NullPointerException if type is null
96 - * @throws IllegalArgumentException if any enum constant from type has
97 - * more than one bit set
98 - * @return an integer with all possible bits for the given bitmap enum
99 - * type set.
100 - */
101 - public static <E extends Enum<E> & BitmapableEnum>
102 - int getMask(Class<E> type) {
103 - if (type == null) {
104 - throw new NullPointerException("Given enum type must not be null");
105 - }
106 - // allSetBitmap will eventually have all valid bits for the given
107 - // type set.
108 - int allSetBitmap = 0;
109 - for (E element: type.getEnumConstants()) {
110 - if (Integer.bitCount(element.getValue()) != 1) {
111 - String msg = String.format("The %s (%x) constant of the " +
112 - "enum %s is supposed to represent a bitmap entry but " +
113 - "has more than one bit set.",
114 - element.toString(), element.getValue(), type.getName());
115 - throw new IllegalArgumentException(msg);
116 - }
117 - allSetBitmap |= element.getValue();
118 - }
119 - return allSetBitmap;
120 - }
121 -
122 - /**
123 - * Convert the given EnumSet to the integer bitmap representation.
124 - * @param set The EnumSet to convert. The enum must implement
125 - * BitmapableEnum
126 - * @return the integer bitmap
127 - * @throws IllegalArgumentException if an enum constant from the set (!) has
128 - * more than one bit set
129 - * @throws NullPointerException if the set is null
130 - */
131 - public static <E extends Enum<E> & BitmapableEnum>
132 - int toBitmap(Set<E> set) {
133 - if (set == null) {
134 - throw new NullPointerException("Given set must not be null");
135 - }
136 - int bitmap = 0;
137 - for (E element: set) {
138 - if (Integer.bitCount(element.getValue()) != 1) {
139 - String msg = String.format("The %s (%x) constant in the set " +
140 - "is supposed to represent a bitmap entry but " +
141 - "has more than one bit set.",
142 - element.toString(), element.getValue());
143 - throw new IllegalArgumentException(msg);
144 - }
145 - bitmap |= element.getValue();
146 - }
147 - return bitmap;
148 - }
149 -}
1 -/**
2 - * Copyright 2012, 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 -
18 -package org.onlab.onos.of.controller.impl.util;
19 -
20 -import java.util.Iterator;
21 -import java.util.NoSuchElementException;
22 -
23 -/**
24 - * An iterator that will filter values from an iterator and return only
25 - * those values that match the predicate.
26 - */
27 -public abstract class FilterIterator<T> implements Iterator<T> {
28 - protected Iterator<T> subIterator;
29 - protected T next;
30 -
31 - /**
32 - * Construct a filter iterator from the given sub iterator.
33 - *
34 - * @param subIterator the sub iterator over which we'll filter
35 - */
36 - public FilterIterator(Iterator<T> subIterator) {
37 - super();
38 - this.subIterator = subIterator;
39 - }
40 -
41 - /**
42 - * Check whether the given value should be returned by the
43 - * filter.
44 - *
45 - * @param value the value to check
46 - * @return true if the value should be included
47 - */
48 - protected abstract boolean matches(T value);
49 -
50 - // ***********
51 - // Iterator<T>
52 - // ***********
53 -
54 - @Override
55 - public boolean hasNext() {
56 - if (next != null) {
57 - return true;
58 - }
59 -
60 - while (subIterator.hasNext()) {
61 - next = subIterator.next();
62 - if (matches(next)) {
63 - return true;
64 - }
65 - }
66 - next = null;
67 - return false;
68 - }
69 -
70 - @Override
71 - public T next() {
72 - if (hasNext()) {
73 - T cur = next;
74 - next = null;
75 - return cur;
76 - }
77 - throw new NoSuchElementException();
78 - }
79 -
80 - @Override
81 - public void remove() {
82 - throw new UnsupportedOperationException();
83 - }
84 -
85 -}
1 -package org.onlab.onos.of.controller.impl.util;
2 -
3 -import static com.google.common.base.Preconditions.checkNotNull;
4 -import static com.google.common.base.Preconditions.checkArgument;
5 -
6 -/**
7 - * The class representing an ONOS Instance ID.
8 - *
9 - * This class is immutable.
10 - */
11 -public final class InstanceId {
12 - private final String id;
13 -
14 - /**
15 - * Constructor from a string value.
16 - *
17 - * @param id the value to use.
18 - */
19 - public InstanceId(String id) {
20 - this.id = checkNotNull(id);
21 - checkArgument(!id.isEmpty(), "Empty ONOS Instance ID");
22 - }
23 -
24 - @Override
25 - public int hashCode() {
26 - return id.hashCode();
27 - }
28 -
29 - @Override
30 - public boolean equals(Object obj) {
31 - if (obj == this) {
32 - return true;
33 - }
34 -
35 - if (!(obj instanceof InstanceId)) {
36 - return false;
37 - }
38 -
39 - InstanceId that = (InstanceId) obj;
40 - return this.id.equals(that.id);
41 - }
42 -
43 - @Override
44 - public String toString() {
45 - return id;
46 - }
47 -}
1 -/**
2 - * Copyright 2012 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 -
18 -package org.onlab.onos.of.controller.impl.util;
19 -
20 -import java.util.Iterator;
21 -import java.util.NoSuchElementException;
22 -
23 -/**
24 - * Iterator over all values in an iterator of iterators.
25 - *
26 - * @param <T> the type of elements returned by this iterator
27 - */
28 -public class IterableIterator<T> implements Iterator<T> {
29 - Iterator<? extends Iterable<T>> subIterator;
30 - Iterator<T> current = null;
31 -
32 - public IterableIterator(Iterator<? extends Iterable<T>> subIterator) {
33 - super();
34 - this.subIterator = subIterator;
35 - }
36 -
37 - @Override
38 - public boolean hasNext() {
39 - if (current == null) {
40 - if (subIterator.hasNext()) {
41 - current = subIterator.next().iterator();
42 - } else {
43 - return false;
44 - }
45 - }
46 - while (!current.hasNext() && subIterator.hasNext()) {
47 - current = subIterator.next().iterator();
48 - }
49 -
50 - return current.hasNext();
51 - }
52 -
53 - @Override
54 - public T next() {
55 - if (hasNext()) {
56 - return current.next();
57 - }
58 - throw new NoSuchElementException();
59 - }
60 -
61 - @Override
62 - public void remove() {
63 - if (hasNext()) {
64 - current.remove();
65 - }
66 - throw new NoSuchElementException();
67 - }
68 -}
1 -/**
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 -
18 -package org.onlab.onos.of.controller.impl.util;
19 -
20 -import java.util.LinkedHashMap;
21 -import java.util.Map;
22 -
23 -public class LRUHashMap<K, V> extends LinkedHashMap<K, V> {
24 -
25 - private static final long serialVersionUID = 1L;
26 -
27 - private final int capacity;
28 -
29 - public LRUHashMap(int capacity) {
30 - super(capacity + 1, 0.75f, true);
31 - this.capacity = capacity;
32 - }
33 -
34 - protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
35 - return size() > capacity;
36 - }
37 -
38 -}
1 -package org.onlab.onos.of.controller.impl.util;
2 -
3 -import java.util.Collection;
4 -import java.util.LinkedHashSet;
5 -
6 -import com.google.common.collect.ForwardingCollection;
7 -
8 -/**
9 - * A simple wrapper / forwarder that forwards all calls to a LinkedHashSet.
10 - * This wrappers sole reason for existence is to implement the
11 - * OrderedCollection marker interface.
12 - *
13 - */
14 -public class LinkedHashSetWrapper<E>
15 - extends ForwardingCollection<E> implements OrderedCollection<E> {
16 - private final Collection<E> delegate;
17 -
18 - public LinkedHashSetWrapper() {
19 - super();
20 - this.delegate = new LinkedHashSet<E>();
21 - }
22 -
23 - public LinkedHashSetWrapper(Collection<? extends E> c) {
24 - super();
25 - this.delegate = new LinkedHashSet<E>(c);
26 - }
27 -
28 - @Override
29 - protected Collection<E> delegate() {
30 - return this.delegate;
31 - }
32 -}
1 -/**
2 - * Copyright 2012 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 -
18 -package org.onlab.onos.of.controller.impl.util;
19 -
20 -import java.util.Iterator;
21 -import java.util.NoSuchElementException;
22 -
23 -/**
24 - * Iterator over all values in an iterator of iterators.
25 - *
26 - * @param <T> the type of elements returned by this iterator
27 - */
28 -public class MultiIterator<T> implements Iterator<T> {
29 - Iterator<Iterator<T>> subIterator;
30 - Iterator<T> current = null;
31 -
32 - public MultiIterator(Iterator<Iterator<T>> subIterator) {
33 - super();
34 - this.subIterator = subIterator;
35 - }
36 -
37 - @Override
38 - public boolean hasNext() {
39 - if (current == null) {
40 - if (subIterator.hasNext()) {
41 - current = subIterator.next();
42 - } else {
43 - return false;
44 - }
45 - }
46 - while (!current.hasNext() && subIterator.hasNext()) {
47 - current = subIterator.next();
48 - }
49 -
50 - return current.hasNext();
51 - }
52 -
53 - @Override
54 - public T next() {
55 - if (hasNext()) {
56 - return current.next();
57 - }
58 - throw new NoSuchElementException();
59 - }
60 -
61 - @Override
62 - public void remove() {
63 - if (hasNext()) {
64 - current.remove();
65 - }
66 - throw new NoSuchElementException();
67 - }
68 -}
1 -package org.onlab.onos.of.controller.impl.util;
2 -
3 -import java.util.Collection;
4 -
5 -/**
6 - * A marker interface indicating that this Collection defines a particular
7 - * iteration order. The details about the iteration order are specified by
8 - * the concrete implementation.
9 - *
10 - * @param <E>
11 - */
12 -public interface OrderedCollection<E> extends Collection<E> {
13 -
14 -}
1 -/**
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 -
18 -package org.onlab.onos.of.controller.impl.internal;
19 -
20 -import junit.framework.TestCase;
21 -import org.onlab.onos.of.controller.impl.IOFSwitch;
22 -
23 -import org.easymock.EasyMock;
24 -import org.junit.After;
25 -import org.junit.Before;
26 -import org.junit.Test;
27 -
28 -
29 -public class ControllerTest extends TestCase {
30 -
31 - private Controller controller;
32 - private IOFSwitch sw;
33 - private OFChannelHandler h;
34 -
35 - @Override
36 - @Before
37 - public void setUp() throws Exception {
38 - super.setUp();
39 - sw = EasyMock.createMock(IOFSwitch.class);
40 - h = EasyMock.createMock(OFChannelHandler.class);
41 - controller = new Controller();
42 - ControllerRunThread t = new ControllerRunThread();
43 - t.start();
44 - /*
45 - * Making sure the thread is properly started before making calls
46 - * to controller class.
47 - */
48 - Thread.sleep(200);
49 - }
50 -
51 - /**
52 - * Starts the base mocks used in these tests.
53 - */
54 - private void startMocks() {
55 - EasyMock.replay(sw, h);
56 - }
57 -
58 - /**
59 - * Reset the mocks to a known state.
60 - * Automatically called after tests.
61 - */
62 - @After
63 - private void resetMocks() {
64 - EasyMock.reset(sw);
65 - }
66 -
67 - /**
68 - * Fetches the controller instance.
69 - * @return the controller
70 - */
71 - public Controller getController() {
72 - return controller;
73 - }
74 -
75 - /**
76 - * Run the controller's main loop so that updates are processed.
77 - */
78 - protected class ControllerRunThread extends Thread {
79 - @Override
80 - public void run() {
81 - controller.openFlowPort = 0; // Don't listen
82 - controller.activate();
83 - }
84 - }
85 -
86 - /**
87 - * Verify that we are able to add a switch that just connected.
88 - * If it already exists then this should fail
89 - *
90 - * @throws Exception error
91 - */
92 - @Test
93 - public void testAddConnectedSwitches() throws Exception {
94 - startMocks();
95 - assertTrue(controller.addConnectedSwitch(0, h));
96 - assertFalse(controller.addConnectedSwitch(0, h));
97 - }
98 -
99 - /**
100 - * Add active master but cannot re-add active master.
101 - * @throws Exception an error occurred.
102 - */
103 - @Test
104 - public void testAddActivatedMasterSwitch() throws Exception {
105 - startMocks();
106 - controller.addConnectedSwitch(0, h);
107 - assertTrue(controller.addActivatedMasterSwitch(0, sw));
108 - assertFalse(controller.addActivatedMasterSwitch(0, sw));
109 - }
110 -
111 - /**
112 - * Tests that an activated switch can be added but cannot be re-added.
113 - *
114 - * @throws Exception an error occurred
115 - */
116 - @Test
117 - public void testAddActivatedEqualSwitch() throws Exception {
118 - startMocks();
119 - controller.addConnectedSwitch(0, h);
120 - assertTrue(controller.addActivatedEqualSwitch(0, sw));
121 - assertFalse(controller.addActivatedEqualSwitch(0, sw));
122 - }
123 -
124 - /**
125 - * Move an equal switch to master.
126 - * @throws Exception an error occurred
127 - */
128 - @Test
129 - public void testTranstitionToMaster() throws Exception {
130 - startMocks();
131 - controller.addConnectedSwitch(0, h);
132 - controller.addActivatedEqualSwitch(0, sw);
133 - controller.transitionToMasterSwitch(0);
134 - assertNotNull(controller.getMasterSwitch(0));
135 - }
136 -
137 - /**
138 - * Transition a master switch to equal state.
139 - * @throws Exception an error occurred
140 - */
141 - @Test
142 - public void testTranstitionToEqual() throws Exception {
143 - startMocks();
144 - controller.addConnectedSwitch(0, h);
145 - controller.addActivatedMasterSwitch(0, sw);
146 - controller.transitionToEqualSwitch(0);
147 - assertNotNull(controller.getEqualSwitch(0));
148 - }
149 -
150 - /**
151 - * Remove the switch from the controller instance.
152 - * @throws Exception an error occurred
153 - */
154 - @Test
155 - public void testRemoveSwitch() throws Exception {
156 - sw.cancelAllStatisticsReplies();
157 - EasyMock.expectLastCall().once();
158 - sw.setConnected(false);
159 - EasyMock.expectLastCall().once();
160 - startMocks();
161 - controller.addConnectedSwitch(0, h);
162 - controller.addActivatedMasterSwitch(0, sw);
163 - controller.removeConnectedSwitch(0);
164 - assertNull(controller.getSwitch(0));
165 - EasyMock.verify(sw, h);
166 - }
167 -}