Merge branch 'master' of https://github.com/OPENNETWORKINGLAB/ONOS
diff --git a/build.xml b/build.xml
index 2bd1343..4aa99bf 100644
--- a/build.xml
+++ b/build.xml
@@ -41,6 +41,7 @@
<property name="main-class" value="net.floodlightcontroller.core.Main"/>
<property name="floodlight-jar" location="${target}/floodlight.jar"/>
<property name="floodlight-test-jar" location="${target}/floodlight-test.jar"/>
+ <property name="floodlight-only-jar" location="${target}/floodlight-only.jar"/>
<property name="thrift.dir" value="${basedir}/src/main/thrift"/>
<property name="thrift.out.dir" value="lib/gen-java"/>
<property name="thrift.package" value="net/floodlightcontroller/packetstreamer/thrift"/>
@@ -65,6 +66,9 @@
<include name="concurrentlinkedhashmap-lru-1.3.jar"/>
<include name="jython-2.5.2.jar"/>
<include name="libthrift-0.7.0.jar"/>
+ <include name="curator-client-1.3.1.jar"/>
+ <include name="curator-framework-1.3.1.jar"/>
+ <include name="curator-recipes-1.3.1.jar"/>
</patternset>
<patternset id="titanlib">
@@ -224,6 +228,16 @@
</target>
<target name="coverage" depends="instrument,test,coverage-report"/>
+ <target name="jar" depends="compile">
+ <jar destfile="${floodlight-only-jar}">
+ <fileset dir="${build}"/>
+ <fileset dir="${resources}"/>
+ <fileset dir="${python-src}">
+ <include name="**/*.py"/>
+ </fileset>
+ </jar>
+ </target>
+
<target name="dist" depends="compile,compile-test">
<jar destfile="${floodlight-jar}" filesetmanifest="mergewithoutmain">
<manifest>
diff --git a/mastership-test.sh b/mastership-test.sh
new file mode 100755
index 0000000..06189df
--- /dev/null
+++ b/mastership-test.sh
@@ -0,0 +1 @@
+java -Dlogback.configurationFile=logback.xml -cp target/floodlight-only.jar:lib/*:lib/titan/* net.floodlightcontroller.mastership.MastershipManager $1
diff --git a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
index 347bf5b..e84e0f6 100644
--- a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
+++ b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
@@ -11,6 +11,7 @@
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.counter.ICounterStoreService;
+import net.floodlightcontroller.mastership.IMastershipService;
import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.storage.IStorageSourceService;
@@ -49,6 +50,7 @@
dependencies.add(IRestApiService.class);
dependencies.add(ICounterStoreService.class);
dependencies.add(IThreadPoolService.class);
+ dependencies.add(IMastershipService.class);
return dependencies;
}
@@ -64,6 +66,7 @@
context.getServiceImpl(IRestApiService.class));
controller.setThreadPoolService(
context.getServiceImpl(IThreadPoolService.class));
+ controller.setMastershipService(context.getServiceImpl(IMastershipService.class));
controller.init(context.getConfigParams(this));
}
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
new file mode 100644
index 0000000..eb363a7
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
@@ -0,0 +1,113 @@
+package net.floodlightcontroller.core;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.frames.Adjacency;
+import com.tinkerpop.frames.Incidence;
+import com.tinkerpop.frames.Property;
+import com.tinkerpop.frames.annotations.gremlin.GremlinGroovy;
+import com.tinkerpop.frames.VertexFrame;
+
+public interface INetMapTopologyObjects {
+
+public interface IBaseObject extends VertexFrame {
+
+ @JsonProperty("state")
+ @Property("state")
+ public String getState();
+ @Property("state")
+ public void setState(final String state);
+
+ @JsonIgnore
+ @Property("type")
+ public String getType();
+ @Property("type")
+ public void setType(final String type);
+
+}
+
+public interface ISwitchObject extends IBaseObject{
+
+ @JsonProperty("dpid")
+ @Property("dpid")
+ public String getDPID();
+
+ @Property("dpid")
+ public void setDPID(String dpid);
+
+ @JsonProperty("ports")
+ @Adjacency(label="on")
+ public Iterable<IPortObject> getPorts();
+
+ @Adjacency(label="on")
+ public void addPort(final IPortObject port);
+
+ @Adjacency(label="on")
+ public void removePort(final IPortObject port);
+
+ @JsonIgnore
+ @GremlinGroovy("_().out('on').out('host')")
+ public Iterable<IDeviceObject> getDevices();
+ }
+
+ public interface IPortObject extends IBaseObject{
+
+ @JsonProperty("number")
+ @Property("number")
+ public Short getNumber();
+
+ @JsonProperty("desc")
+ @Property("desc")
+ public String getDesc();
+
+ @JsonIgnore
+ @Incidence(label="on",direction = Direction.IN)
+ public ISwitchObject getSwitch();
+
+ @JsonIgnore
+ @Adjacency(label="host")
+ public Iterable<IDeviceObject> getDevices();
+
+ @Adjacency(label="host")
+ public void setDevice(final IDeviceObject device);
+
+ @Adjacency(label="host")
+ public void removeDevice(final IDeviceObject device);
+
+// @JsonIgnore
+// @Adjacency(label="link")
+// public Iterable<ILinkObject> getLinks();
+ }
+
+ public interface IDeviceObject extends IBaseObject {
+
+ @JsonProperty("mac")
+ @Property("dl_addr")
+ public String getMACAddress();
+ @Property("dl_addr")
+ public void setMACAddress();
+
+ @JsonProperty("ipv4")
+ @Property("nw_addr")
+ public String getIPAddress();
+ @Property("dl_addr")
+ public void setIPAddress();
+
+ @JsonIgnore
+ @Incidence(label="host",direction = Direction.IN)
+ public IPortObject getPort();
+
+ @JsonIgnore
+ @GremlinGroovy("_().in('host').in('on')")
+ public ISwitchObject getSwitch();
+
+ public interface AttachmentPoint {
+ @GremlinGroovy("_().in('host').in('on').dpid")
+ public String getDPID();
+ @GremlinGroovy("_().in('host').number")
+ public Short getPortNumber();
+ }
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapTopologyService.java b/src/main/java/net/floodlightcontroller/core/INetMapTopologyService.java
index f0c7f7f..e5df25e 100644
--- a/src/main/java/net/floodlightcontroller/core/INetMapTopologyService.java
+++ b/src/main/java/net/floodlightcontroller/core/INetMapTopologyService.java
@@ -2,7 +2,7 @@
import java.util.List;
-import net.floodlightcontroller.core.ISwitchStorage.ISwitchObject;
+import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.floodlightcontroller.routing.Link;
import net.floodlightcontroller.topology.NodePortTuple;
diff --git a/src/main/java/net/floodlightcontroller/core/ISwitchStorage.java b/src/main/java/net/floodlightcontroller/core/ISwitchStorage.java
index 5e81000..5a1e1a7 100644
--- a/src/main/java/net/floodlightcontroller/core/ISwitchStorage.java
+++ b/src/main/java/net/floodlightcontroller/core/ISwitchStorage.java
@@ -1,6 +1,9 @@
package net.floodlightcontroller.core;
import java.util.Collection;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
+
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.openflow.protocol.OFPhysicalPort;
@@ -17,52 +20,7 @@
INACTIVE,
ACTIVE
}
-
- public interface ISwitchObject extends VertexFrame{
-
- @JsonProperty("dpid")
- @Property("dpid")
- public String getDPID();
-
- @JsonProperty("state")
- @Property("state")
- public String getState();
-
- @JsonIgnore
- @Property("type")
- public String getType();
-
- @JsonProperty("ports")
- @Adjacency(label="on")
- public Iterable<IPortObject> getPorts();
- }
- public interface IPortObject extends VertexFrame{
-
- @JsonProperty("state")
- @Property("state")
- public int getState();
-
- @JsonIgnore
- @Property("type")
- public String getType();
-
- @JsonProperty("number")
- @Property("number")
- public Short getNumber();
-
- @JsonProperty("desc")
- @Property("desc")
- public String getDesc();
-
- @JsonIgnore
- @Incidence(label="on",direction = Direction.IN)
- public ISwitchObject getSwitch();
-
-// @JsonIgnore
-// @Adjacency(label="link")
-// public Iterable<ILinkObject> getLinks();
- }
/*
* Update the switch details
*/
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index a5ee71a..d9cc5e1 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -65,6 +65,7 @@
import net.floodlightcontroller.core.util.ListenerDispatcher;
import net.floodlightcontroller.core.web.CoreWebRoutable;
import net.floodlightcontroller.counter.ICounterStoreService;
+import net.floodlightcontroller.mastership.IMastershipService;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
import net.floodlightcontroller.restserver.IRestApiService;
@@ -134,6 +135,7 @@
import org.slf4j.LoggerFactory;
+
/**
* The main controller class. Handles all setup and network listeners
*/
@@ -187,6 +189,7 @@
protected IStorageSourceService storageSource;
protected IPktInProcessingTimeService pktinProcTime;
protected IThreadPoolService threadPool;
+ protected IMastershipService masterHelper;
// Configuration options
protected int openFlowPort = 6633;
@@ -389,6 +392,10 @@
this.threadPool = tp;
}
+ public void setMastershipService(IMastershipService serviceImpl) {
+ this.masterHelper = serviceImpl;
+ }
+
@Override
public Role getRole() {
synchronized(roleChanger) {
@@ -761,7 +768,7 @@
else {
// Role supported not enabled on controller (for now)
// automatically promote switch to active state.
- log.debug("This controller's role is null, " +
+ log.debug("This controller's role is {}, " +
"not sending role request msg to {}",
role, sw);
// Need to clear FlowMods before we add the switch
diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
index 72c6b50..3cb8163 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
@@ -22,6 +22,7 @@
import com.tinkerpop.frames.FramedGraph;
import com.tinkerpop.gremlin.java.GremlinPipeline;
+import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.floodlightcontroller.core.ISwitchStorage;
public class SwitchStorageImpl implements ISwitchStorage {
diff --git a/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java b/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
index cb2eb46..1136a90 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
@@ -2,8 +2,8 @@
import java.util.List;
+import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.floodlightcontroller.core.INetMapTopologyService.ITopoSwitchService;
-import net.floodlightcontroller.core.ISwitchStorage.ISwitchObject;
public class TopoSwitchServiceImpl implements ITopoSwitchService {
diff --git a/src/main/java/net/floodlightcontroller/core/web/TopoSwitchesResource.java b/src/main/java/net/floodlightcontroller/core/web/TopoSwitchesResource.java
index e75d26a..c5b7e66 100644
--- a/src/main/java/net/floodlightcontroller/core/web/TopoSwitchesResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/TopoSwitchesResource.java
@@ -2,7 +2,7 @@
import java.util.Iterator;
-import net.floodlightcontroller.core.ISwitchStorage.ISwitchObject;
+import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.floodlightcontroller.core.internal.TopoSwitchServiceImpl;
import org.restlet.resource.Get;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
new file mode 100644
index 0000000..d9f19ba
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -0,0 +1,149 @@
+package net.floodlightcontroller.flowcache;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.flowcache.IFlowService;
+import net.floodlightcontroller.flowcache.web.FlowWebRoutable;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.floodlightcontroller.util.CallerId;
+import net.floodlightcontroller.util.DataPathEndpoints;
+import net.floodlightcontroller.util.FlowId;
+import net.floodlightcontroller.util.FlowPath;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowManager implements IFloodlightModule, IFlowService {
+
+ protected IRestApiService restApi;
+
+ /** The logger. */
+ private static Logger logger =
+ LoggerFactory.getLogger(FlowReconcileManager.class);
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IFlowService.class);
+ return l;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService>
+ getServiceImpls() {
+ Map<Class<? extends IFloodlightService>,
+ IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>,
+ IFloodlightService>();
+ m.put(IFlowService.class, this);
+ return m;
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>>
+ getModuleDependencies() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IRestApiService.class);
+ return l;
+ }
+
+ @Override
+ public void init(FloodlightModuleContext context)
+ throws FloodlightModuleException {
+ restApi = context.getServiceImpl(IRestApiService.class);
+ }
+
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+ restApi.addRestletRoutable(new FlowWebRoutable());
+ }
+
+ /**
+ * Add a flow.
+ *
+ * Internally, ONOS will automatically register the installer for
+ * receiving Flow Path Notifications for that path.
+ *
+ * @param flowPath the Flow Path to install.
+ * @param flowId the return-by-reference Flow ID as assigned internally.
+ * @return true on success, otherwise false.
+ */
+ @Override
+ public boolean addFlow(FlowPath flowPath, FlowId flowId) {
+ // TODO
+ return true;
+ }
+
+ /**
+ * Delete a previously added flow.
+ *
+ * @param flowId the Flow ID of the flow to delete.
+ * @return true on success, otherwise false.
+ */
+ @Override
+ public boolean deleteFlow(FlowId flowId) {
+ // TODO
+ return true;
+ }
+
+ /**
+ * Get a previously added flow.
+ *
+ * @param flowId the Flow ID of the flow to get.
+ * @param flowPath the return-by-reference flow path.
+ * @return true on success, otherwise false.
+ */
+ @Override
+ public boolean getFlow(FlowId flowId, FlowPath flowPath) {
+ // TODO
+ return true;
+ }
+
+ /**
+ * Get a previously added flow by a specific installer for given
+ * data path endpoints.
+ *
+ * @param installerId the Caller ID of the installer of the flow to get.
+ * @param dataPathEndpoints the data path endpoints of the flow to get.
+ * @param flowPath the return-by-reference flow path.
+ * @return true on success, otherwise false.
+ */
+ @Override
+ public boolean getFlow(CallerId installerId,
+ DataPathEndpoints dataPathEndpoints,
+ FlowPath flowPath) {
+ // TODO
+ return true;
+ }
+
+ /**
+ * Get all installed flows by all installers for given data path endpoints.
+ *
+ * @param dataPathEndpoints the data path endpoints of the flows to get.
+ * @param flowPaths the return-by-reference list of flows.
+ */
+ @Override
+ public void getAllFlows(DataPathEndpoints dataPathEndpoints,
+ ArrayList<FlowPath> flowPaths) {
+ // TODO
+ }
+
+ /**
+ * Get all installed flows by all installers.
+ *
+ * @param flowPaths the return-by-reference list of flows.
+ */
+ @Override
+ public void getAllFlows(ArrayList<FlowPath> flowPaths) {
+ // TODO
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java b/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
new file mode 100644
index 0000000..956caab
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
@@ -0,0 +1,72 @@
+package net.floodlightcontroller.flowcache;
+
+import java.util.ArrayList;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.util.CallerId;
+import net.floodlightcontroller.util.DataPathEndpoints;
+import net.floodlightcontroller.util.FlowId;
+import net.floodlightcontroller.util.FlowPath;
+
+/**
+ * @short Interface for providing Flow Service to other modules.
+ */
+public interface IFlowService extends IFloodlightService {
+ /**
+ * Add a flow.
+ *
+ * Internally, ONOS will automatically register the installer for
+ * receiving Flow Path Notifications for that path.
+ *
+ * @param flowPath the Flow Path to install.
+ * @param flowId the return-by-reference Flow ID as assigned internally.
+ * @return true on success, otherwise false.
+ */
+ boolean addFlow(FlowPath flowPath, FlowId flowId);
+
+ /**
+ * Delete a previously added flow.
+ *
+ * @param flowId the Flow ID of the flow to delete.
+ * @return true on success, otherwise false.
+ */
+ boolean deleteFlow(FlowId flowId);
+
+ /**
+ * Get a previously added flow.
+ *
+ * @param flowId the Flow ID of the flow to get.
+ * @param flowPath the return-by-reference flow path.
+ * @return true on success, otherwise false.
+ */
+ boolean getFlow(FlowId flowId, FlowPath flowPath);
+
+ /**
+ * Get a previously added flow by a specific installer for given
+ * data path endpoints.
+ *
+ * @param installerId the Caller ID of the installer of the flow to get.
+ * @param dataPathEndpoints the data path endpoints of the flow to get.
+ * @param flowPath the return-by-reference flow path.
+ * @return true on success, otherwise false.
+ */
+ boolean getFlow(CallerId installerId,
+ DataPathEndpoints dataPathEndpoints,
+ FlowPath flowPath);
+
+ /**
+ * Get all installed flows by all installers for given data path endpoints.
+ *
+ * @param dataPathEndpoints the data path endpoints of the flows to get.
+ * @param flowPaths the return-by-reference list of flows.
+ */
+ void getAllFlows(DataPathEndpoints dataPathEndpoints,
+ ArrayList<FlowPath> flowPaths);
+
+ /**
+ * Get all installed flows by all installers.
+ *
+ * @param flowPaths the return-by-reference list of flows.
+ */
+ void getAllFlows(ArrayList<FlowPath> flowPaths);
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java
new file mode 100644
index 0000000..35367eb
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java
@@ -0,0 +1,36 @@
+package net.floodlightcontroller.flowcache.web;
+
+import net.floodlightcontroller.flowcache.IFlowService;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AddFlowResource extends ServerResource {
+
+ protected static Logger log = LoggerFactory.getLogger(AddFlowResource.class);
+
+ @Get("json")
+ public Boolean retrieve() {
+ Boolean result = false;
+
+ IFlowService flowService =
+ (IFlowService)getContext().getAttributes().
+ get(IFlowService.class.getCanonicalName());
+
+ if (flowService == null) {
+ log.debug("ONOS Flow Service not found");
+ return result;
+ }
+
+ // Extract the arguments
+ String flowPathStr = (String) getRequestAttributes().get("flow");
+ log.debug("Add Flow Path: " + flowPathStr);
+
+ // TODO: Implement it.
+ result = true;
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/DeleteFlowResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/DeleteFlowResource.java
new file mode 100644
index 0000000..f323a54
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/DeleteFlowResource.java
@@ -0,0 +1,37 @@
+package net.floodlightcontroller.flowcache.web;
+
+import net.floodlightcontroller.flowcache.IFlowService;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DeleteFlowResource extends ServerResource {
+ protected static Logger log = LoggerFactory.getLogger(DeleteFlowResource.class);
+
+ @Get("json")
+ public Boolean retrieve() {
+ Boolean result = false;
+
+ IFlowService flowService =
+ (IFlowService)getContext().getAttributes().
+ get(IFlowService.class.getCanonicalName());
+
+ if (flowService == null) {
+ log.debug("ONOS Flow Service not found");
+ return result;
+ }
+
+ // Extract the arguments
+ String flowIdStr = (String) getRequestAttributes().get("flow-id");
+ long flowId = HexString.toLong(flowIdStr);
+ log.debug("Delete Flow Id: " + flowIdStr);
+
+ // TODO: Implement it.
+ result = true;
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java b/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java
new file mode 100644
index 0000000..b1188c8
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java
@@ -0,0 +1,32 @@
+package net.floodlightcontroller.flowcache.web;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+public class FlowWebRoutable implements RestletRoutable {
+ /**
+ * Create the Restlet router and bind to the proper resources.
+ */
+ @Override
+ public Restlet getRestlet(Context context) {
+ Router router = new Router(context);
+ router.attach("/add/{flow}/json", AddFlowResource.class);
+ router.attach("/delete/{flow-id}/json", DeleteFlowResource.class);
+ router.attach("/get/{flow-id}/json", GetFlowByIdResource.class);
+ router.attach("/get/{installer-id}/{data-path-endpoints}/json", GetFlowByInstallerIdResource.class);
+ router.attach("/getall/{data-path-endpoints}/json", GetAllFlowsByEndpointsResource.class);
+ router.attach("/getall/json", GetAllFlowsResource.class);
+ return router;
+ }
+
+ /**
+ * Set the base path for the Topology
+ */
+ @Override
+ public String basePath() {
+ return "/wm/flow";
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java
new file mode 100644
index 0000000..211a051
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java
@@ -0,0 +1,37 @@
+package net.floodlightcontroller.flowcache.web;
+
+import java.util.ArrayList;
+
+import net.floodlightcontroller.flowcache.IFlowService;
+import net.floodlightcontroller.util.FlowPath;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GetAllFlowsByEndpointsResource extends ServerResource {
+ protected static Logger log = LoggerFactory.getLogger(GetAllFlowsByEndpointsResource.class);
+
+ @Get("json")
+ public ArrayList<FlowPath> retrieve() {
+ ArrayList<FlowPath> result = new ArrayList<FlowPath>();
+
+ IFlowService flowService =
+ (IFlowService)getContext().getAttributes().
+ get(IFlowService.class.getCanonicalName());
+
+ if (flowService == null) {
+ log.debug("ONOS Flow Service not found");
+ return result;
+ }
+
+ // Extract the arguments
+ String dataPathEndpointsStr = (String) getRequestAttributes().get("data-path-endpoints");
+ log.debug("Get All Flows Endpoints: " + dataPathEndpointsStr);
+
+ // TODO: Implement it.
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java
new file mode 100644
index 0000000..9d95651
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java
@@ -0,0 +1,36 @@
+package net.floodlightcontroller.flowcache.web;
+
+import java.util.ArrayList;
+
+import net.floodlightcontroller.flowcache.IFlowService;
+import net.floodlightcontroller.util.FlowPath;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GetAllFlowsResource extends ServerResource {
+ protected static Logger log = LoggerFactory.getLogger(GetAllFlowsResource.class);
+
+ @Get("json")
+ public ArrayList<FlowPath> retrieve() {
+ ArrayList<FlowPath> result = new ArrayList<FlowPath>();
+
+ IFlowService flowService =
+ (IFlowService)getContext().getAttributes().
+ get(IFlowService.class.getCanonicalName());
+
+ if (flowService == null) {
+ log.debug("ONOS Flow Service not found");
+ return result;
+ }
+
+ // Extract the arguments
+ log.debug("Get All Flows Endpoints");
+
+ // TODO: Implement it.
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java
new file mode 100644
index 0000000..99f880c
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java
@@ -0,0 +1,37 @@
+package net.floodlightcontroller.flowcache.web;
+
+import net.floodlightcontroller.flowcache.IFlowService;
+import net.floodlightcontroller.util.FlowPath;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GetFlowByIdResource extends ServerResource {
+ protected static Logger log = LoggerFactory.getLogger(GetFlowByIdResource.class);
+
+ @Get("json")
+ public FlowPath retrieve() {
+ FlowPath result = null;
+
+ IFlowService flowService =
+ (IFlowService)getContext().getAttributes().
+ get(IFlowService.class.getCanonicalName());
+
+ if (flowService == null) {
+ log.debug("ONOS Flow Service not found");
+ return result;
+ }
+
+ // Extract the arguments
+ String flowIdStr = (String) getRequestAttributes().get("flow-id");
+ long flowId = HexString.toLong(flowIdStr);
+ log.debug("Get Flow Id: " + flowIdStr);
+
+ // TODO: Implement it.
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByInstallerIdResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByInstallerIdResource.java
new file mode 100644
index 0000000..32d20cc
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByInstallerIdResource.java
@@ -0,0 +1,36 @@
+package net.floodlightcontroller.flowcache.web;
+
+import net.floodlightcontroller.flowcache.IFlowService;
+import net.floodlightcontroller.util.FlowPath;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GetFlowByInstallerIdResource extends ServerResource {
+ protected static Logger log = LoggerFactory.getLogger(GetFlowByInstallerIdResource.class);
+
+ @Get("json")
+ public FlowPath retrieve() {
+ FlowPath result = null;
+
+ IFlowService flowService =
+ (IFlowService)getContext().getAttributes().
+ get(IFlowService.class.getCanonicalName());
+
+ if (flowService == null) {
+ log.debug("ONOS Flow Service not found");
+ return result;
+ }
+
+ // Extract the arguments
+ String installerIdStr = (String) getRequestAttributes().get("installer-id");
+ String dataPathEndpointsStr = (String) getRequestAttributes().get("data-path-endpoints");
+ log.debug("Get Flow Installer: " + installerIdStr + " Endpoints: " + dataPathEndpointsStr);
+
+ // TODO: Implement it.
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
index 3aa1fc0..966e180 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
@@ -5,8 +5,8 @@
import java.util.List;
import java.util.Set;
+import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.floodlightcontroller.core.INetMapTopologyService.ITopoSwitchService;
-import net.floodlightcontroller.core.ISwitchStorage.ISwitchObject;
import net.floodlightcontroller.core.internal.TopoSwitchServiceImpl;
import net.floodlightcontroller.linkdiscovery.ILinkStorage;
import net.floodlightcontroller.linkdiscovery.LinkInfo;
diff --git a/src/main/java/net/floodlightcontroller/mastership/IMastershipHelper.java b/src/main/java/net/floodlightcontroller/mastership/IMastershipHelper.java
new file mode 100644
index 0000000..b4becfa
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/IMastershipHelper.java
@@ -0,0 +1,27 @@
+package net.floodlightcontroller.mastership;
+
+public interface IMastershipHelper {
+
+ // Callback for all mastership changes.
+ // Change callback is called when mastership is acquired or released
+ public interface MastershipCallback {
+ public void changeCallback(long dpid);
+ }
+
+ // Set/get mastership identifier. This is used to set the unique identifier of the controller that is asking for mastership.
+ // It needs to be set first before any mastership call can be made
+ public void setMastershipId (String id);
+ public String getMastershipId ();
+
+ // Request mastership for a switch. Our request for mastership remains in a queue. If we win mastership, the callback
+ // is called. This call is non-blocking and can be called from the packet processing context as well.
+ public void requestMastership(long dpid, MastershipCallback cb);
+
+ // Release mastership for a switch. If we are the master, then the mastership will be released and given to the next
+ // controller who had requested mastership. If we are not the master our request for mastership will be
+ // removed from the queue.
+ public void releaseMastership(long dpid);
+
+ // Check if I am the master of a switch and return true if I am the master.
+ public boolean amMaster(long dpid);
+}
diff --git a/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java b/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
new file mode 100644
index 0000000..83800c3
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/IMastershipService.java
@@ -0,0 +1,27 @@
+package net.floodlightcontroller.mastership;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+public interface IMastershipService extends IFloodlightService {
+
+ // Callback for all mastership changes.
+ // Change callback is called when mastership is acquired or released
+ public interface MastershipCallback {
+ public void changeCallback(long dpid, boolean isMaster);
+ }
+
+ // Acquire mastership for a switch.
+ public void acquireMastership(long dpid, MastershipCallback cb) throws Exception;
+
+ // Release mastership for a switch
+ public void releaseMastership(long dpid);
+
+ // Check if I am the master of a switch. This is a nonblocking call that checks if the caller is a
+ public boolean amMaster(long dpid);
+
+ // Set/Get mastership identifier.
+ // This is typically a unique identifier of the controller that does not change across restarts
+ public void setMastershipId (String id);
+ public String getMastershipId ();
+
+}
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipHelper.java b/src/main/java/net/floodlightcontroller/mastership/MastershipHelper.java
new file mode 100644
index 0000000..fdac8ca
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipHelper.java
@@ -0,0 +1,35 @@
+package net.floodlightcontroller.mastership;
+
+public class MastershipHelper implements IMastershipHelper {
+
+ @Override
+ public void setMastershipId(String id) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getMastershipId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void requestMastership(long dpid, MastershipCallback cb) {
+ // TODO Auto-generated method stub
+ return;
+ }
+
+ @Override
+ public void releaseMastership(long dpid) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean amMaster(long dpid) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java b/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
new file mode 100644
index 0000000..46b533e
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipManager.java
@@ -0,0 +1,281 @@
+package net.floodlightcontroller.mastership;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.curator.RetryPolicy;
+import com.netflix.curator.framework.CuratorFramework;
+import com.netflix.curator.framework.CuratorFrameworkFactory;
+import com.netflix.curator.framework.api.CuratorWatcher;
+import com.netflix.curator.framework.recipes.leader.LeaderLatch;
+import com.netflix.curator.framework.recipes.leader.Participant;
+import com.netflix.curator.retry.ExponentialBackoffRetry;
+
+public class MastershipManager implements IFloodlightModule, IMastershipService {
+
+ protected static Logger log = LoggerFactory.getLogger(MastershipManager.class);
+ protected String mastershipId = null;
+
+ //TODO read this from configuration
+ protected String connectionString = "localhost:2181";
+ private final String namespace = "onos";
+ private final String switchLatchesPath = "/switchmastership";
+
+ protected CuratorFramework client;
+
+ protected Map<String, LeaderLatch> switchLatches;
+ protected Map<String, MastershipCallback> switchCallbacks;
+
+ protected class ParamaterizedCuratorWatcher implements CuratorWatcher {
+ private String dpid;
+ private boolean isLeader = false;
+ private String latchPath;
+
+ public ParamaterizedCuratorWatcher(String dpid, String latchPath){
+ this.dpid = dpid;
+ this.latchPath = latchPath;
+ }
+
+ @Override
+ public void process(WatchedEvent event) throws Exception {
+ log.debug("Watch Event: {}", event);
+
+ LeaderLatch latch = switchLatches.get(dpid);
+
+ if (event.getState() == KeeperState.Disconnected){
+ if (isLeader) {
+ log.debug("Disconnected while leader - lost leadership for {}", dpid);
+
+ isLeader = false;
+ switchCallbacks.get(dpid).changeCallback(HexString.toLong(dpid), false);
+ }
+ return;
+ }
+
+ try {
+ Participant leader = latch.getLeader();
+
+ if (leader.getId().equals(mastershipId) && !isLeader){
+ log.debug("Became leader for {}", dpid);
+
+ isLeader = true;
+ switchCallbacks.get(dpid).changeCallback(HexString.toLong(dpid), true);
+ }
+ else if (!leader.getId().equals(mastershipId) && isLeader){
+ log.debug("Lost leadership for {}", dpid);
+
+ isLeader = false;
+ switchCallbacks.get(dpid).changeCallback(HexString.toLong(dpid), false);
+ }
+ } catch (Exception e){
+ if (isLeader){
+ log.debug("Exception checking leadership status. Assume leadship lost for {}",
+ dpid);
+
+ isLeader = false;
+ switchCallbacks.get(dpid).changeCallback(HexString.toLong(dpid), false);
+ }
+ }
+
+ client.getChildren().usingWatcher(this).inBackground().forPath(latchPath);
+ //client.getChildren().usingWatcher(this).forPath(latchPath);
+ }
+ }
+
+ @Override
+ public void acquireMastership(long dpid, MastershipCallback cb) throws Exception {
+
+ if (mastershipId == null){
+ throw new RuntimeException("Must set mastershipId before calling aquireMastership");
+ }
+
+ String dpidStr = HexString.toHexString(dpid);
+ String latchPath = switchLatchesPath + "/" + dpidStr;
+
+ if (switchLatches.get(dpidStr) != null){
+ throw new RuntimeException("Leader election for switch " + dpidStr +
+ "is already running");
+ }
+
+ LeaderLatch latch = new LeaderLatch(client, latchPath, mastershipId);
+ switchLatches.put(dpidStr, latch);
+ switchCallbacks.put(dpidStr, cb);
+
+ try {
+ //client.getChildren().usingWatcher(watcher).inBackground().forPath(singleLatchPath);
+ client.getChildren().usingWatcher(
+ new ParamaterizedCuratorWatcher(dpidStr, latchPath))
+ .inBackground().forPath(latchPath);
+ latch.start();
+ } catch (Exception e) {
+ log.warn("Error starting leader latch: {}", e.getMessage());
+ throw e;
+ }
+
+ }
+
+ @Override
+ public void releaseMastership(long dpid) {
+ String dpidStr = HexString.toHexString(dpid);
+
+ LeaderLatch latch = switchLatches.get(dpidStr);
+ if (latch == null) {
+ log.debug("Trying to release mastership for switch we are not contesting");
+ return;
+ }
+
+ try {
+ latch.close();
+ } catch (IOException e) {
+
+ }
+
+ switchLatches.remove(dpidStr);
+ switchCallbacks.remove(dpidStr);
+ }
+
+ @Override
+ public boolean amMaster(long dpid) {
+ LeaderLatch latch = switchLatches.get(HexString.toHexString(dpid));
+
+ if (latch == null) {
+ log.warn("No leader latch for dpid {}", HexString.toHexString(dpid));
+ return false;
+ }
+
+ try {
+ return latch.getLeader().getId().equals(mastershipId);
+ } catch (Exception e) {
+ //TODO swallow exception?
+ return false;
+ }
+ }
+
+ @Override
+ public void setMastershipId(String id) {
+ mastershipId = id;
+ }
+
+ @Override
+ public String getMastershipId() {
+ return mastershipId;
+ }
+
+
+ /*
+ * IFloodlightModule
+ */
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IMastershipService.class);
+ return l;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+ Map<Class<? extends IFloodlightService>, IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+ m.put(IMastershipService.class, this);
+ return m;
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+ // no module dependencies
+ return null;
+ }
+
+ @Override
+ public void init (FloodlightModuleContext context) throws FloodlightModuleException {
+
+ try {
+ String localHostname = java.net.InetAddress.getLocalHost().getHostName();
+ mastershipId = localHostname;
+ log.debug("Setting mastership id to {}", mastershipId);
+ } catch (UnknownHostException e) {
+ // TODO Handle this exception
+ e.printStackTrace();
+ }
+
+ switchLatches = new HashMap<String, LeaderLatch>();
+ switchCallbacks = new HashMap<String, MastershipCallback>();
+
+ RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
+ client = CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
+
+ client.start();
+
+ client = client.usingNamespace(namespace);
+
+ return;
+ }
+
+ @Override
+ public void startUp (FloodlightModuleContext context) {
+ // Nothing to be done on startup
+ }
+
+ public static void main(String args[]){
+ FloodlightModuleContext fmc = new FloodlightModuleContext();
+ MastershipManager mm = new MastershipManager();
+
+ String id = null;
+ if (args.length > 0){
+ id = args[0];
+ log.info("Using unique id: {}", id);
+ }
+
+ try {
+ mm.init(fmc);
+ mm.startUp(fmc);
+
+ if (id != null){
+ mm.setMastershipId(id);
+ }
+
+ mm.acquireMastership(1L,
+ new MastershipCallback(){
+ @Override
+ public void changeCallback(long dpid, boolean isMaster) {
+ if (isMaster){
+ log.debug("Callback for becoming master for {}", HexString.toHexString(dpid));
+ }
+ else {
+ log.debug("Callback for losing mastership for {}", HexString.toHexString(dpid));
+ }
+ }
+ });
+
+ //"Server" loop
+ while (true) {
+ Thread.sleep(60000);
+ }
+
+ } catch (FloodlightModuleException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ log.debug("is master: {}", mm.amMaster(1L));
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipRouteResource.java b/src/main/java/net/floodlightcontroller/mastership/MastershipRouteResource.java
new file mode 100644
index 0000000..f75c518
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipRouteResource.java
@@ -0,0 +1,32 @@
+package net.floodlightcontroller.mastership;
+
+import org.restlet.resource.ServerResource;
+import org.restlet.resource.Get;
+import org.restlet.resource.Post;
+import org.restlet.resource.Delete;
+
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+public class MastershipRouteResource extends ServerResource {
+
+ protected static Logger log = LoggerFactory.getLogger(MastershipRouteResource.class);
+
+ @Get
+ public String get(String fmJson) {
+ // TODO
+ return null;
+ }
+
+ @Post
+ public String store (String fmJson) {
+ //TODO
+ return null;
+ }
+
+ @Delete
+ public String delete (String fmJson) {
+ //TODO
+ return null;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/mastership/MastershipWebRoutable.java b/src/main/java/net/floodlightcontroller/mastership/MastershipWebRoutable.java
new file mode 100644
index 0000000..56d5d66
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/mastership/MastershipWebRoutable.java
@@ -0,0 +1,23 @@
+package net.floodlightcontroller.mastership;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+public class MastershipWebRoutable implements RestletRoutable {
+
+ @Override
+ public Restlet getRestlet(Context context) {
+ Router router = new Router(context);
+ router.attach("/json", MastershipRouteResource.class);
+ return router;
+ }
+
+ @Override
+ public String basePath() {
+ return "/wm/mastership";
+ }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java b/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
index 9d921f5..90fdb6e 100644
--- a/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
+++ b/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
@@ -10,20 +10,8 @@
import org.openflow.util.HexString;
-import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanGraph;
-// import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
-// import com.tinkerpop.gremlin.groovy.Gremlin;
-// import com.tinkerpop.gremlin.java.GremlinPipeline;
-// import com.tinkerpop.pipes.Pipe;
-// import com.tinkerpop.pipes.PipeFunction;
-// import com.tinkerpop.pipes.branch.LoopPipe;
-// import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
-// import com.tinkerpop.pipes.filter.FilterPipe.Filter;
-// import com.tinkerpop.pipes.util.PipesFluentPipeline;
-
-import com.tinkerpop.blueprints.Element;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
@@ -56,11 +44,13 @@
//
// Implement the Shortest Path between two vertices by using
- // the following Gremlin code:
- // results = []; v_src.as('x').out.out.in.has("type", "switch").dedup().loop('x'){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)
+ // the following Gremlin CLI code:
+ // v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path(){it.dpid}{it.number}{it.number}
+ // The equivalent code used here is:
+ // results = []; v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path().fill(results)
//
- String gremlin = "v_src.as(\"x\").out.out.in.has(\"type\", \"switch\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)";
+ String gremlin = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid}.path().fill(results)";
// Get the source vertex
Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
@@ -73,7 +63,21 @@
if (! iter.hasNext())
return null; // Destination vertex not found
Vertex v_dest = iter.next();
-
+
+ //
+ // Test whether we are computing a path from/to the same DPID.
+ // If "yes", then just list the "src" and "dest" in the return
+ // result.
+ // NOTE: The return value will change in the future to return
+ // a single hop/entry instead of two. Currently, we need
+ // both entries to capture the source and destination ports.
+ //
+ if (dpid_src.equals(dpid_dest)) {
+ result_list.add(new NodePortTuple(src));
+ result_list.add(new NodePortTuple(dest));
+ return result_list;
+ }
+
//
// Implement the Gremlin script and run it
//
diff --git a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
index 4983529..6ac8f29 100644
--- a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
+++ b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
@@ -18,6 +18,16 @@
protected short portId; // switch port id
/**
+ * A copy constructor for NodePortTuple.
+ *
+ * @param other the object to copy the state from.
+ */
+ public NodePortTuple(NodePortTuple other) {
+ this.nodeId = other.nodeId;
+ this.portId = other.portId;
+ }
+
+ /**
* Creates a NodePortTuple
* @param nodeId The DPID of the switch
* @param portId The port of the switch
diff --git a/src/main/java/net/floodlightcontroller/util/CallerId.java b/src/main/java/net/floodlightcontroller/util/CallerId.java
new file mode 100644
index 0000000..898da31
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/CallerId.java
@@ -0,0 +1,48 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing a Caller ID for an ONOS component.
+ */
+public class CallerId {
+ private String value;
+
+ /**
+ * Default constructor.
+ */
+ public CallerId() {}
+
+ /**
+ * Constructor from a string value.
+ *
+ * @param value the value to use.
+ */
+ public CallerId(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the Caller ID.
+ *
+ * @return the value of the Caller ID.
+ */
+ public String value() { return value; }
+
+ /**
+ * Set the value of the Caller ID.
+ *
+ * @param value the value to set.
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Convert the Caller ID value to a string.
+ *
+ * @return the Caller ID value to a string.
+ */
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/DataPath.java b/src/main/java/net/floodlightcontroller/util/DataPath.java
new file mode 100644
index 0000000..2374fbe
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/DataPath.java
@@ -0,0 +1,81 @@
+package net.floodlightcontroller.util;
+
+import java.util.ArrayList;
+
+import net.floodlightcontroller.util.SwitchPort;
+import net.floodlightcontroller.util.FlowEntry;
+
+/**
+ * The class representing the Data Path.
+ */
+public class DataPath {
+ private SwitchPort srcPort; // The source port
+ private SwitchPort dstPort; // The destination port
+ private ArrayList<FlowEntry> flowEntries; // The Flow Entries
+
+ /**
+ * Default constructor.
+ */
+ public DataPath() {
+ }
+
+ /**
+ * Get the data path source port.
+ *
+ * @return the data path source port.
+ */
+ public SwitchPort srcPort() { return srcPort; }
+
+ /**
+ * Set the data path source port.
+ *
+ * @param srcPort the data path source port to set.
+ */
+ public void setSrcPort(SwitchPort srcPort) {
+ this.srcPort = srcPort;
+ }
+
+ /**
+ * Get the data path destination port.
+ *
+ * @return the data path destination port.
+ */
+ public SwitchPort dstPort() { return dstPort; }
+
+ /**
+ * Set the data path destination port.
+ *
+ * @param dstPort the data path destination port to set.
+ */
+ public void setDstPort(SwitchPort dstPort) {
+ this.dstPort = dstPort;
+ }
+
+ /**
+ * Get the data path flow entries.
+ *
+ * @return the data path flow entries.
+ */
+ public ArrayList<FlowEntry> flowEntries() { return flowEntries; }
+
+ /**
+ * Set the data path flow entries.
+ *
+ * @param flowEntries the data path flow entries to set.
+ */
+ public void setFlowEntries(ArrayList<FlowEntry> flowEntries) {
+ this.flowEntries = flowEntries;
+ }
+
+ /**
+ * Convert the data path to a string.
+ *
+ * @return the data path as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/DataPathEndpoints.java b/src/main/java/net/floodlightcontroller/util/DataPathEndpoints.java
new file mode 100644
index 0000000..5c9e02c
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/DataPathEndpoints.java
@@ -0,0 +1,72 @@
+package net.floodlightcontroller.util;
+
+import net.floodlightcontroller.util.SwitchPort;
+
+/**
+ * The class representing the Data Path Endpoints.
+ */
+public class DataPathEndpoints {
+ private SwitchPort srcPort; // The source port
+ private SwitchPort dstPort; // The destination port
+
+ /**
+ * Default constructor.
+ */
+ public DataPathEndpoints() {
+ }
+
+ /**
+ * Constructor for given source and destination ports.
+ *
+ * @param srcPort the source port to use.
+ * @param dstPort the destination port to use.
+ */
+ public DataPathEndpoints(SwitchPort srcPort, SwitchPort dstPort) {
+ this.srcPort = srcPort;
+ this.dstPort = dstPort;
+ }
+
+ /**
+ * Get the data path source port.
+ *
+ * @return the data path source port.
+ */
+ public SwitchPort srcPort() { return srcPort; }
+
+ /**
+ * Set the data path source port.
+ *
+ * @param srcPort the data path source port to set.
+ */
+ public void setSrcPort(SwitchPort srcPort) {
+ this.srcPort = srcPort;
+ }
+
+ /**
+ * Get the data path destination port.
+ *
+ * @return the data path destination port.
+ */
+ public SwitchPort dstPort() { return dstPort; }
+
+ /**
+ * Set the data path destination port.
+ *
+ * @param dstPort the data path destination port to set.
+ */
+ public void setDstPort(SwitchPort dstPort) {
+ this.dstPort = dstPort;
+ }
+
+ /**
+ * Convert the data path endpoints to a string.
+ *
+ * @return the data path endpoints as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/Dpid.java b/src/main/java/net/floodlightcontroller/util/Dpid.java
new file mode 100644
index 0000000..3a8d1e8
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/Dpid.java
@@ -0,0 +1,54 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing a network switch DPID.
+ */
+public class Dpid {
+ static public long UNKNOWN = 0;
+
+ private long value;
+
+ /**
+ * Default constructor.
+ */
+ public Dpid() {
+ this.value = Dpid.UNKNOWN;
+ }
+
+ /**
+ * Constructor from a long value.
+ *
+ * @param value the value to use.
+ */
+ public Dpid(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the DPID.
+ *
+ * @return the value of the DPID.
+ */
+ public long value() { return value; }
+
+ /**
+ * Set the value of the DPID.
+ *
+ * @param value the value to set.
+ */
+ public void setValue(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Convert the DPID value to a ':' separated hex string.
+ *
+ * @return the DPID value as a ':' separated hex string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntry.java b/src/main/java/net/floodlightcontroller/util/FlowEntry.java
new file mode 100644
index 0000000..e9c4bbe
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntry.java
@@ -0,0 +1,224 @@
+package net.floodlightcontroller.util;
+
+import net.floodlightcontroller.util.Dpid;
+import net.floodlightcontroller.util.FlowEntryActions;
+import net.floodlightcontroller.util.FlowEntryId;
+import net.floodlightcontroller.util.FlowEntryMatch;
+import net.floodlightcontroller.util.Port;
+
+/**
+ * The Flow Entry state as set by the user (via the ONOS API).
+ */
+enum FlowEntryUserState {
+ FE_USER_UNKNOWN, // Initialization value: state unknown
+ FE_USER_ADD, // Flow entry that is added
+ FE_USER_MODIFY, // Flow entry that is modified
+ FE_USER_DELETE // Flow entry that is deleted
+}
+
+/**
+ * The Flow Entry state as set by the controller.
+ */
+enum FlowEntrySwitchState {
+ FE_SWITCH_UNKNOWN, // Initialization value: state unknown
+ FE_SWITCH_NOT_UPDATED, // Switch not updated with this entry
+ FE_SWITCH_UPDATE_IN_PROGRESS, // Switch update in progress
+ FE_SWITCH_UPDATED, // Switch updated with this entry
+ FE_SWITCH_UPDATE_FAILED // Error updating the switch with this entry
+}
+
+
+/**
+ * The class representing the Flow Entry.
+ *
+ * NOTE: The specification is incomplete. E.g., the entry needs to
+ * support multiple in-ports and multiple out-ports.
+ */
+public class FlowEntry {
+ private FlowEntryId flowEntryId; // The Flow Entry ID
+ private FlowEntryMatch flowEntryMatch; // The Flow Entry Match
+ private FlowEntryActions flowEntryActions; // The Flow Entry Actions
+ private Dpid dpid; // The Switch DPID
+ private Port inPort; // The Switch incoming port
+ private Port outPort; // The Switch outgoing port
+ private FlowEntryUserState flowEntryUserState; // The Flow Entry User state
+ private FlowEntrySwitchState flowEntrySwitchState; // The Flow Entry Switch state
+ // The Flow Entry Error state (if FlowEntrySwitchState is FE_SWITCH_FAILED)
+ private FlowEntryErrorState flowEntryErrorState;
+
+ /**
+ * Default constructor.
+ */
+ public FlowEntry() {
+ flowEntryUserState = FlowEntryUserState.FE_USER_UNKNOWN;
+ flowEntrySwitchState = FlowEntrySwitchState.FE_SWITCH_UNKNOWN;
+ }
+
+ /**
+ * Get the Flow Entry ID.
+ *
+ * @return the Flow Entry ID.
+ */
+ public FlowEntryId flowEntryId() { return flowEntryId; }
+
+ /**
+ * Set the Flow Entry ID.
+ *
+ * @param flowEntryId the Flow Entry ID to set.
+ */
+ public void setFlowEntryId(FlowEntryId flowEntryId) {
+ this.flowEntryId = flowEntryId;
+ }
+
+ /**
+ * Get the Flow Entry Match.
+ *
+ * @return the Flow Entry Match.
+ */
+ public FlowEntryMatch flowEntryMatch() { return flowEntryMatch; }
+
+ /**
+ * Set the Flow Entry Match.
+ *
+ * @param flowEntryMatch the Flow Entry Match to set.
+ */
+ public void setFlowEntryMatch(FlowEntryMatch flowEntryMatch) {
+ this.flowEntryMatch = flowEntryMatch;
+ }
+
+ /**
+ * Get the Flow Entry Actions.
+ *
+ * @return the Flow Entry Actions.
+ */
+ public FlowEntryActions flowEntryActions() { return flowEntryActions; }
+
+ /**
+ * Set the Flow Entry Actions.
+ *
+ * @param flowEntryActions the Flow Entry Actions to set.
+ */
+ public void setFlowEntryActions(FlowEntryActions flowEntryActions) {
+ this.flowEntryActions = flowEntryActions;
+ }
+
+ /**
+ * Get the Switch DPID.
+ *
+ * @return the Switch DPID.
+ */
+ public Dpid dpid() { return dpid; }
+
+ /**
+ * Set the Switch DPID.
+ *
+ * @param dpid the Switch DPID to set.
+ */
+ public void setDpid(Dpid dpid) {
+ this.dpid = dpid;
+ }
+
+ /**
+ * Get the Switch incoming port.
+ *
+ * @return the Switch incoming port.
+ */
+ public Port inPort() { return inPort; }
+
+ /**
+ * Set the Switch incoming port.
+ *
+ * @param inPort the Switch incoming port to set.
+ */
+ public void setInPort(Port inPort) {
+ this.inPort = inPort;
+ }
+
+ /**
+ * Get the Switch outgoing port.
+ *
+ * @return the Switch outgoing port.
+ */
+ public Port outPort() { return outPort; }
+
+ /**
+ * Set the Switch outgoing port.
+ *
+ * @param outPort the Switch outgoing port to set.
+ */
+ public void setOutPort(Port outPort) {
+ this.outPort = outPort;
+ }
+
+ /**
+ * Get the Flow Entry User state.
+ *
+ * @return the Flow Entry User state.
+ */
+ public FlowEntryUserState flowEntryUserState() {
+ return flowEntryUserState;
+ }
+
+ /**
+ * Set the Flow Entry User state.
+ *
+ * @param flowEntryUserState the Flow Entry User state to set.
+ */
+ public void setFlowEntryUserState(FlowEntryUserState flowEntryUserState) {
+ this.flowEntryUserState = flowEntryUserState;
+ }
+
+ /**
+ * Get the Flow Entry Switch state.
+ *
+ * The Flow Entry Error state is used if FlowEntrySwitchState is
+ * FE_SWITCH_FAILED.
+ *
+ * @return the Flow Entry Switch state.
+ */
+ public FlowEntrySwitchState flowEntrySwitchState() {
+ return flowEntrySwitchState;
+ }
+
+ /**
+ * Set the Flow Entry Switch state.
+ *
+ * The Flow Entry Error state is used if FlowEntrySwitchState is
+ * FE_SWITCH_FAILED.
+ *
+ * @param flowEntrySwitchState the Flow Entry Switch state to set.
+ */
+ public void setFlowEntrySwitchState(FlowEntrySwitchState flowEntrySwitchState) {
+ this.flowEntrySwitchState = flowEntrySwitchState;
+ }
+
+ /**
+ * Get the Flow Entry Error state.
+ *
+ * @return the Flow Entry Error state.
+ */
+ public FlowEntryErrorState flowEntryErrorState() {
+ return flowEntryErrorState;
+ }
+
+ /**
+ * Set the Flow Entry Error state.
+ *
+ * @param flowEntryErrorState the Flow Entry Error state to set.
+ */
+ public void setFlowEntryErrorState(FlowEntryErrorState flowEntryErrorState) {
+ this.flowEntryErrorState = flowEntryErrorState;
+ }
+
+ /**
+ * Convert the flow entry to a string.
+ *
+ * @return the flow entry as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryActions.java b/src/main/java/net/floodlightcontroller/util/FlowEntryActions.java
new file mode 100644
index 0000000..90f42fb
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntryActions.java
@@ -0,0 +1,30 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing the Flow Entry set of actions.
+ *
+ * The Flow Entry set of actions need to be applied to each packet.
+ *
+ * NOTE: This is just an empty placeholder (for now). The implied action is
+ * forwarding on a single port.
+ */
+public class FlowEntryActions {
+
+ /**
+ * Default constructor.
+ */
+ public FlowEntryActions() {
+ }
+
+ /**
+ * Convert the set of actions to a string.
+ *
+ * @return the set of actions as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryErrorState.java b/src/main/java/net/floodlightcontroller/util/FlowEntryErrorState.java
new file mode 100644
index 0000000..63c103d
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntryErrorState.java
@@ -0,0 +1,65 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing the Flow Entry error state.
+ */
+public class FlowEntryErrorState {
+ private short type; // The error type (e.g., see OF-1.3.1 spec, pp. 95)
+ private short code; // The error code (e.g., see OF-1.3.1 spec, pp. 95)
+
+ /**
+ * Default constructor.
+ */
+ public FlowEntryErrorState() {
+ this.type = 0;
+ this.code = 0;
+ }
+
+ /**
+ * Constructor for a given error type and code.
+ *
+ * @param type the error type to use.
+ * @param code the error code to use.
+ */
+ public FlowEntryErrorState(short type, short code) {
+ this.type = type;
+ this.code = code;
+ }
+
+ /**
+ * Get the error type.
+ *
+ * @return the error type.
+ */
+ public short type() { return type; }
+
+ /**
+ * Get the error code.
+ *
+ * @return the error code.
+ */
+ public short code() { return code; }
+
+ /**
+ * Set the values of the error type and code.
+ *
+ * @param type the error type to use.
+ * @param code the error code to use.
+ */
+ public void setValue(short type, short code) {
+ this.type = type;
+ this.code = code;
+ }
+
+ /**
+ * Convert the error type and code to a string.
+ *
+ * @return the error type and code as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryId.java b/src/main/java/net/floodlightcontroller/util/FlowEntryId.java
new file mode 100644
index 0000000..4736ed5
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntryId.java
@@ -0,0 +1,52 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing a Flow Entry ID.
+ */
+public class FlowEntryId {
+ private long value;
+
+ /**
+ * Default constructor.
+ */
+ public FlowEntryId() {
+ this.value = 0;
+ }
+
+ /**
+ * Constructor from an integer value.
+ *
+ * @param value the value to use.
+ */
+ public FlowEntryId(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the Flow Entry ID.
+ *
+ * @return the value of the Flow Entry ID.
+ */
+ public long value() { return value; }
+
+ /**
+ * Set the value of the Flow Entry ID.
+ *
+ * @param value the value to set.
+ */
+ public void setValue(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Convert the Flow Entry ID value to a string.
+ *
+ * @return the Flow Entry ID value to a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryMatch.java b/src/main/java/net/floodlightcontroller/util/FlowEntryMatch.java
new file mode 100644
index 0000000..a8f43f5
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntryMatch.java
@@ -0,0 +1,105 @@
+package net.floodlightcontroller.util;
+
+import net.floodlightcontroller.util.MACAddress;
+import net.floodlightcontroller.util.IPv4Net;
+
+/**
+ * The class representing the Flow Entry Matching filter.
+ *
+ * The Flow Entry matching filter that is used to specify
+ * the network data that would be forwarded on the data path from
+ * the source to the destination. Examples: MAC address (of the
+ * sender), IP prefix that includes the destination's IP address, etc.
+ *
+ * NOTE: The FlowEntryMatch specification below is incomplete: we need
+ * more matching fields, we need to indicate which fields need to be
+ * matched, etc.
+ */
+public class FlowEntryMatch {
+ private MACAddress srcMac; // Matching source MAC address
+ private MACAddress dstMac; // Matching destination MAC address
+ private IPv4Net srcIPv4Net; // Matching source IPv4 prefix
+ private IPv4Net dstIPv4Net; // Matching destination IPv4 prefix
+
+ /**
+ * Default constructor.
+ */
+ public FlowEntryMatch() {
+ }
+
+ /**
+ * Get the matching source MAC address.
+ *
+ * @return the matching source MAC address.
+ */
+ public MACAddress srcMac() { return srcMac; }
+
+ /**
+ * Set the matching source MAC address.
+ *
+ * @param srcMac the matching source MAC address to set.
+ */
+ public void setSrcMac(MACAddress srcMac) {
+ this.srcMac = srcMac;
+ }
+
+ /**
+ * Get the matching destination MAC address.
+ *
+ * @return the matching destination MAC address.
+ */
+ public MACAddress dstMac() { return dstMac; }
+
+ /**
+ * Set the matching destination MAC address.
+ *
+ * @param dstMac the matching destination MAC address to set.
+ */
+ public void setDstMac(MACAddress dstMac) {
+ this.dstMac = dstMac;
+ }
+
+ /**
+ * Get the matching source IPv4 prefix.
+ *
+ * @return the matching source IPv4 prefix.
+ */
+ public IPv4Net srcIPv4Net() { return srcIPv4Net; }
+
+ /**
+ * Set the matching source IPv4 prefix.
+ *
+ * @param srcIPv4Net the matching source IPv4 prefix to set.
+ */
+ public void setSrcIPv4Net(IPv4Net srcIPv4Net) {
+ this.srcIPv4Net = srcIPv4Net;
+ }
+
+ /**
+ * Get the matching destination IPv4 prefix.
+ *
+ * @return the matching destination IPv4 prefix.
+ */
+ public IPv4Net dstIPv4Net() { return dstIPv4Net; }
+
+ /**
+ * Set the matching destination IPv4 prefix.
+ *
+ * @param srcIPv4Net the matching destination IPv4 prefix to set.
+ */
+ public void setDstIPv4Net(IPv4Net dstIPv4Net) {
+ this.dstIPv4Net = dstIPv4Net;
+ }
+
+ /**
+ * Convert the matching filter to a string.
+ *
+ * @return the matching filter as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowId.java b/src/main/java/net/floodlightcontroller/util/FlowId.java
new file mode 100644
index 0000000..827c1d9
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowId.java
@@ -0,0 +1,52 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing a Flow ID.
+ */
+public class FlowId {
+ private long value;
+
+ /**
+ * Default constructor.
+ */
+ public FlowId() {
+ this.value = 0;
+ }
+
+ /**
+ * Constructor from an integer value.
+ *
+ * @param value the value to use.
+ */
+ public FlowId(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the Flow ID.
+ *
+ * @return the value of the Flow ID.
+ */
+ public long value() { return value; }
+
+ /**
+ * Set the value of the Flow ID.
+ *
+ * @param value the value to set.
+ */
+ public void setValue(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Convert the Flow ID value to a string.
+ *
+ * @return the Flow ID value to a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowPath.java b/src/main/java/net/floodlightcontroller/util/FlowPath.java
new file mode 100644
index 0000000..46a1f82
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowPath.java
@@ -0,0 +1,80 @@
+package net.floodlightcontroller.util;
+
+import net.floodlightcontroller.util.CallerId;
+import net.floodlightcontroller.util.DataPath;
+import net.floodlightcontroller.util.FlowId;
+
+/**
+ * The class representing the Flow Path.
+ */
+public class FlowPath {
+ private FlowId flowId; // The Flow ID
+ private CallerId installerId; // The Caller ID of the path installer
+ private DataPath dataPath; // The data path
+
+ /**
+ * Default constructor.
+ */
+ public FlowPath() {
+ }
+
+ /**
+ * Get the flow path Flow ID.
+ *
+ * @return the flow path Flow ID.
+ */
+ public FlowId flowId() { return flowId; }
+
+ /**
+ * Set the flow path Flow ID.
+ *
+ * @param flowId the flow path Flow ID to set.
+ */
+ public void setFlowId(FlowId flowId) {
+ this.flowId = flowId;
+ }
+
+ /**
+ * Get the Caller ID of the flow path installer.
+ *
+ * @return the Caller ID of the flow path installer.
+ */
+ public CallerId installerId() { return installerId; }
+
+ /**
+ * Set the Caller ID of the flow path installer.
+ *
+ * @param installerId the Caller ID of the flow path installer.
+ */
+ public void setInstallerId(CallerId installerId) {
+ this.installerId = installerId;
+ }
+
+ /**
+ * Get the flow path's data path.
+ *
+ * @return the flow path's data path.
+ */
+ public DataPath dataPath() { return dataPath; }
+
+ /**
+ * Set the flow path's data path.
+ *
+ * @param dataPath the flow path's data path to set.
+ */
+ public void setDataPath(DataPath dataPath) {
+ this.dataPath = dataPath;
+ }
+
+ /**
+ * Convert the flow path to a string.
+ *
+ * @return the flow path as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/IPv4.java b/src/main/java/net/floodlightcontroller/util/IPv4.java
new file mode 100644
index 0000000..b4fc787
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/IPv4.java
@@ -0,0 +1,52 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing an IPv4 address.
+ */
+public class IPv4 {
+ private int value;
+
+ /**
+ * Default constructor.
+ */
+ public IPv4() {
+ this.value = 0;
+ }
+
+ /**
+ * Constructor from an integer value.
+ *
+ * @param value the value to use.
+ */
+ public IPv4(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the IPv4 address.
+ *
+ * @return the value of the IPv4 address.
+ */
+ public int value() { return value; }
+
+ /**
+ * Set the value of the IPv4 address.
+ *
+ * @param value the value to set.
+ */
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Convert the IPv4 value to a '.' separated string.
+ *
+ * @return the IPv4 value as a '.' separated string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/IPv4Net.java b/src/main/java/net/floodlightcontroller/util/IPv4Net.java
new file mode 100644
index 0000000..6c4c651
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/IPv4Net.java
@@ -0,0 +1,66 @@
+package net.floodlightcontroller.util;
+
+import net.floodlightcontroller.util.IPv4;
+
+/**
+ * The class representing an IPv4 network address.
+ */
+public class IPv4Net {
+ private IPv4 address; // The IPv4 address
+ private short prefixLen; // The prefix length
+
+ /**
+ * Default constructor.
+ */
+ public IPv4Net() {
+ this.prefixLen = 0;
+ }
+
+ /**
+ * Constructor for a given address and prefix length.
+ *
+ * @param address the address to use.
+ * @param prefixLen the prefix length to use.
+ */
+ public IPv4Net(IPv4 address, short prefixLen) {
+ this.address = address;
+ this.prefixLen = prefixLen;
+ }
+
+ /**
+ * Get the address value of the IPv4Net address.
+ *
+ * @return the address value of the IPv4Net address.
+ */
+ public IPv4 address() { return address; }
+
+ /**
+ * Get the prefix length value of the IPv4Net address.
+ *
+ * @return the prefix length value of the IPv4Net address.
+ */
+ public short prefixLen() { return prefixLen; }
+
+ /**
+ * Set the value of the IPv4Net address.
+ *
+ * @param address the address to use.
+ * @param prefixLen the prefix length to use.
+ */
+ public void setValue(IPv4 address, short prefixLen) {
+ this.address = address;
+ this.prefixLen = prefixLen;
+ }
+
+ /**
+ * Convert the IPv4Net value to an "address/prefixLen" string.
+ *
+ * @return the IPv4Net value as an "address/prefixLen" string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/IPv6.java b/src/main/java/net/floodlightcontroller/util/IPv6.java
new file mode 100644
index 0000000..dfa071b
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/IPv6.java
@@ -0,0 +1,67 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing an IPv6 address.
+ */
+public class IPv6 {
+ private long valueHigh; // The higher (more significant) 64 bits
+ private long valueLow; // The lower (less significant) 64 bits
+
+ /**
+ * Default constructor.
+ */
+ public IPv6() {
+ this.valueHigh = 0;
+ this.valueLow = 0;
+ }
+
+ /**
+ * Constructor from integer values.
+ *
+ * @param valueHigh the higher (more significant) 64 bits of the address.
+ * @param valueLow the lower (less significant) 64 bits of the address.
+ */
+ public IPv6(long valueHigh, long valueLow) {
+ this.valueHigh = valueHigh;
+ this.valueLow = valueLow;
+ }
+
+ /**
+ * Get the value of the higher (more significant) 64 bits of the address.
+ *
+ * @return the value of the higher (more significant) 64 bits of the
+ * address.
+ */
+ public long valueHigh() { return valueHigh; }
+
+ /**
+ * Get the value of the lower (less significant) 64 bits of the address.
+ *
+ * @return the value of the lower (less significant) 64 bits of the
+ * address.
+ */
+ public long valueLow() { return valueLow; }
+
+ /**
+ * Set the value of the IPv6 address.
+ *
+ * @param valueHigh the higher (more significant) 64 bits of the address.
+ * @param valueLow the lower (less significant) 64 bits of the address.
+ */
+ public void setValue(long valueHigh, long valueLow) {
+ this.valueHigh = valueHigh;
+ this.valueLow = valueLow;
+ }
+
+ /**
+ * Convert the IPv6 value to a ':' separated string.
+ *
+ * @return the IPv6 value as a ':' separated string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/IPv6Net.java b/src/main/java/net/floodlightcontroller/util/IPv6Net.java
new file mode 100644
index 0000000..85de4f7
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/IPv6Net.java
@@ -0,0 +1,66 @@
+package net.floodlightcontroller.util;
+
+import net.floodlightcontroller.util.IPv6;
+
+/**
+ * The class representing an IPv6 network address.
+ */
+public class IPv6Net {
+ private IPv6 address; // The IPv6 address
+ private short prefixLen; // The prefix length
+
+ /**
+ * Default constructor.
+ */
+ public IPv6Net() {
+ this.prefixLen = 0;
+ }
+
+ /**
+ * Constructor for a given address and prefix length.
+ *
+ * @param address the address to use.
+ * @param prefixLen the prefix length to use.
+ */
+ public IPv6Net(IPv6 address, short prefixLen) {
+ this.address = address;
+ this.prefixLen = prefixLen;
+ }
+
+ /**
+ * Get the address value of the IPv6Net address.
+ *
+ * @return the address value of the IPv6Net address.
+ */
+ public IPv6 address() { return address; }
+
+ /**
+ * Get the prefix length value of the IPv6Net address.
+ *
+ * @return the prefix length value of the IPv6Net address.
+ */
+ public short prefixLen() { return prefixLen; }
+
+ /**
+ * Set the value of the IPv6Net address.
+ *
+ * @param address the address to use.
+ * @param prefixLen the prefix length to use.
+ */
+ public void setValue(IPv6 address, short prefixLen) {
+ this.address = address;
+ this.prefixLen = prefixLen;
+ }
+
+ /**
+ * Convert the IPv6Net value to an "address/prefixLen" string.
+ *
+ * @return the IPv6Net value as an "address/prefixLen" string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/Port.java b/src/main/java/net/floodlightcontroller/util/Port.java
new file mode 100644
index 0000000..8fbb727
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/Port.java
@@ -0,0 +1,52 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The class representing a network port of a switch.
+ */
+public class Port {
+ private short value;
+
+ /**
+ * Default constructor.
+ */
+ public Port() {
+ this.value = 0;
+ }
+
+ /**
+ * Constructor from a long value.
+ *
+ * @param value the value to use.
+ */
+ public Port(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the value of the port.
+ *
+ * @return the value of the port.
+ */
+ public short value() { return value; }
+
+ /**
+ * Set the value of the port.
+ *
+ * @param value the value to set.
+ */
+ public void setValue(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Convert the port value to a string.
+ *
+ * @return the port value as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/SwitchPort.java b/src/main/java/net/floodlightcontroller/util/SwitchPort.java
new file mode 100644
index 0000000..31061bc
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/SwitchPort.java
@@ -0,0 +1,66 @@
+package net.floodlightcontroller.util;
+
+import net.floodlightcontroller.util.Dpid;
+import net.floodlightcontroller.util.Port;
+
+/**
+ * The class representing a Switch-Port.
+ */
+public class SwitchPort {
+ private Dpid dpid; // The DPID of the switch
+ private Port port; // The port of the switch
+
+ /**
+ * Default constructor.
+ */
+ public SwitchPort() {
+ }
+
+ /**
+ * Constructor for a given DPID and a port.
+ *
+ * @param dpid the DPID to use.
+ * @param port the port to use.
+ */
+ public SwitchPort(Dpid dpid, Port port) {
+ this.dpid = dpid;
+ this.port = port;
+ }
+
+ /**
+ * Get the DPID value of the Switch-Port.
+ *
+ * @return the DPID value of the Switch-Port.
+ */
+ public Dpid dpid() { return dpid; }
+
+ /**
+ * Get the port value of the Switch-Port.
+ *
+ * @return the port value of the Switch-Port.
+ */
+ public Port port() { return port; }
+
+ /**
+ * Set the DPID and port values of the Switch-Port.
+ *
+ * @param dpid the DPID to use.
+ * @param port the port to use.
+ */
+ public void setValue(Dpid dpid, Port port) {
+ this.dpid = dpid;
+ this.port = port;
+ }
+
+ /**
+ * Convert the Switch-Port value to a string.
+ *
+ * @return the Switch-Port value as a string.
+ */
+ @Override
+ public String toString() {
+ String ret = "";
+ // TODO: Implement it!
+ return ret;
+ }
+}
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index 0225a2b..44436f4 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -22,4 +22,7 @@
net.floodlightcontroller.devicemanager.test.MockDeviceManager
net.floodlightcontroller.core.test.MockFloodlightProvider
net.floodlightcontroller.core.test.MockThreadPoolService
-net.floodlightcontroller.firewall.Firewall
\ No newline at end of file
+net.floodlightcontroller.firewall.Firewall
+net.floodlightcontroller.mastership.MastershipManager
+
+
diff --git a/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java b/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
index 177769b..b4a044f 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
@@ -7,7 +7,6 @@
import java.util.ArrayList;
import java.util.Iterator;
-import java.util.List;
import net.floodlightcontroller.core.ISwitchStorage;
import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
@@ -19,16 +18,10 @@
import org.openflow.protocol.OFPhysicalPort;
import com.thinkaurelius.titan.core.TitanGraph;
-import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.gremlin.groovy.Gremlin;
import com.tinkerpop.gremlin.java.GremlinPipeline;
-import com.tinkerpop.pipes.Pipe;
import com.tinkerpop.pipes.PipeFunction;
-import com.tinkerpop.pipes.branch.LoopPipe;
import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
-import com.tinkerpop.pipes.filter.FilterPipe.Filter;
-import com.tinkerpop.pipes.util.PipesFluentPipeline;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
@@ -168,8 +161,7 @@
}
public Boolean compute(LoopBundle<Vertex> bundle) {
Boolean output = false;
- if ((bundle.getObject().getProperty("dpid") != dpid) &&
- (bundle.getLoops() < 10)) {
+ if (bundle.getObject().getProperty("dpid") != dpid) {
output = true;
}
return output;
@@ -183,11 +175,15 @@
//
// Implement the Shortest Path between two vertices by using
- // the following Gremlin code:
- // results = []; v_src.as('x').out.out.in.has("type", "switch").dedup().loop('x'){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)
+ // the following Gremlin CLI code:
+ // v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path(){it.dpid}{it.number}{it.number}
+ // The equivalent code used here is:
+ // results = []; v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path().fill(results)
//
- String gremlin = "v_src.as(\"x\").out.out.in.has(\"type\", \"switch\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)";
+ String gremlin = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid}.path().fill(results)";
+
+ String gremlin_nopath = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != \"NO-SUCH-DPID\"}.path().fill(results)";
// Get the source vertex
Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
@@ -255,11 +251,25 @@
//
// XXX: An alternative (faster?) solution that fails to compile
//
- MyLoopFunction whileFunction = new MyLoopFunction(dpid_dest);
- GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
- // pipe.start(v_src).as("x").out().out().in().has("type", "switch").dedup().loop("x", whileFunction);
+ // MyLoopFunction whileFunction = new MyLoopFunction(dpid_dest);
+ // GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
+ // ArrayList<ArrayList<Vertex>> results2 = new ArrayList<ArrayList<Vertex>>();
+ // TODO: The statement below doesn't compile
+ // pipe.start(v_src).as("x").out("on").out("link").in("on").dedup().loop("x", whileFunction).path().fill(results2);
// Check the result
assertEquals(results_str, expected_result);
+
+ //
+ // Test Shortest-Path computation to non-existing destination
+ //
+ results.clear();
+ try {
+ engine.eval(gremlin_nopath);
+ } catch (ScriptException e) {
+ System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
+ return;
+ }
+ assertTrue(results.size() == 0);
}
}
diff --git a/start-onos.sh b/start-onos.sh
index 089b1d9..a3c0c43 100755
--- a/start-onos.sh
+++ b/start-onos.sh
@@ -79,6 +79,7 @@
echo "Starting ONOS controller ..."
echo
java ${JVM_OPTS} -Dlogback.configurationFile=${FL_LOGBACK} -jar ${FL_JAR} -cf ./onos.properties > /dev/null 2>&1 &
+# echo "java ${JVM_OPTS} -Dlogback.configurationFile=${FL_LOGBACK} -jar ${FL_JAR} -cf ./onos.properties > /dev/null 2>&1 &"
sudo -b /usr/sbin/tcpdump -n -i eth0 -s0 -w ${PCAP_LOG} 'tcp port 6633' > /dev/null 2>&1
}
diff --git a/web/favicon.ico b/web/favicon.ico
new file mode 100644
index 0000000..a72928b
--- /dev/null
+++ b/web/favicon.ico
Binary files differ
diff --git a/web/js/onos-topology.js b/web/js/onos-topology.js
index 7bee4c0..aee3eaf 100644
--- a/web/js/onos-topology.js
+++ b/web/js/onos-topology.js
@@ -201,7 +201,12 @@
circle.append("title")
.text(function(d) { return d.name; });
- circle.attr("fill", function(d) { if (d.group == 0){return "blue";}else{ return "gray"; }})
+ circle.attr("fill", function(d) {
+ if (d.group == 1){return "red";}
+ else if (d.group == 2){return "blue";}
+ else if (d.group == 3){return "green";}
+ else{ return "gray"; }
+ });
force.on("tick", tick);
path.exit().remove();
@@ -233,7 +238,12 @@
circle.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
- circle.attr("fill", function(d) { if (d.group == 0){return "blue";}else{ return "gray"; }});
+ circle.attr("fill", function(d) {
+ if (d.group == 1){return "red";}
+ else if (d.group == 2){return "blue";}
+ else if (d.group == 3){return "green";}
+ else{ return "gray"; }
+ });
// text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
// text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
text.attr("transform", function(d) {
diff --git a/web/topology_rest.py b/web/topology_rest.py
index be4844d..cdc8a4d 100755
--- a/web/topology_rest.py
+++ b/web/topology_rest.py
@@ -158,6 +158,97 @@
return resp
+#@app.route("/wm/topology/toporoute/00:00:00:00:00:a1/2/00:00:00:00:00:c1/3/json")
+#@app.route("/wm/topology/toporoute/<srcdpid>/<srcport>/<destdpid>/<destport>/json")
+@app.route("/wm/topology/toporoute/<v1>/<p1>/<v2>/<p2>/json")
+def shortest_path(v1, p1, v2, p2):
+ try:
+ command = "curl -s \'http://%s:%s/wm/core/topology/switches/all/json\'" % (RestIP, RestPort)
+ result = os.popen(command).read()
+ parsedResult = json.loads(result)
+ except:
+ log_error("REST IF has issue: %s" % command)
+ log_error("%s" % result)
+ sys.exit(0)
+
+ topo = {}
+ switches = []
+ links = []
+
+ for v in parsedResult:
+ if v.has_key('dpid'):
+ dpid = str(v['dpid'])
+ state = str(v['state'])
+ sw = {}
+ sw['name']=dpid
+ if str(v['state']) == "ACTIVE":
+ if dpid[-2:-1] == "a":
+ sw['group']=1
+ if dpid[-2:-1] == "b":
+ sw['group']=2
+ if dpid[-2:-1] == "c":
+ sw['group']=3
+ if str(v['state']) == "INACTIVE":
+ sw['group']=0
+
+ switches.append(sw)
+
+ try:
+ command = "curl -s http://%s:%s/wm/topology/route/%s/%s/%s/%s/json" % (RestIP, RestPort, v1, p1, v2, p2)
+ result = os.popen(command).read()
+ parsedResult = json.loads(result)
+ except:
+ log_error("No route")
+ parsedResult = []
+# exit(1)
+
+ path = [];
+ for i, v in enumerate(parsedResult):
+ if i < len(parsedResult) - 1:
+ sdpid= parsedResult[i]['switch']
+ ddpid = parsedResult[i+1]['switch']
+ path.append( (sdpid, ddpid))
+
+ try:
+ command = "curl -s \'http://%s:%s/wm/core/topology/links/json\'" % (RestIP, RestPort)
+ result = os.popen(command).read()
+ parsedResult = json.loads(result)
+ except:
+ log_error("REST IF has issue: %s" % command)
+ log_error("%s" % result)
+ sys.exit(0)
+
+ for v in parsedResult:
+ link = {}
+ if v.has_key('dst-switch'):
+ dst_dpid = str(v['dst-switch'])
+ dst_id = node_id(switches, dst_dpid)
+ if v.has_key('src-switch'):
+ src_dpid = str(v['src-switch'])
+ src_id = node_id(switches, src_dpid)
+ link['source'] = src_id
+ link['target'] = dst_id
+ onpath = 0
+ for (s,d) in path:
+ if s == v['src-switch'] and d == v['dst-switch']:
+ onpath = 1
+ break
+
+ link['type'] = onpath
+ links.append(link)
+
+ topo['nodes'] = switches
+ topo['links'] = links
+
+ pp.pprint(topo)
+ js = json.dumps(topo)
+ resp = Response(js, status=200, mimetype='application/json')
+ return resp
+
+
+
+
+
@app.route("/wm/core/controller/switches/json")
def query_switch():
try: