Merge branch 'master' of https://github.com/OPENNETWORKINGLAB/ONOS
diff --git a/conf/onos-embedded.properties b/conf/onos-embedded.properties
index 8bbf25d..777ff2b 100644
--- a/conf/onos-embedded.properties
+++ b/conf/onos-embedded.properties
@@ -9,6 +9,7 @@
net.floodlightcontroller.ui.web.StaticWebRoutable,\
net.onrc.onos.datagrid.HazelcastDatagrid,\
net.onrc.onos.ofcontroller.flowmanager.FlowManager,\
+net.onrc.onos.ofcontroller.topology.TopologyManager,\
net.onrc.onos.registry.controller.ZookeeperRegistry
net.floodlightcontroller.restserver.RestApiServer.port = 8080
net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
diff --git a/conf/onos.properties b/conf/onos.properties
index c67b340..e858adb 100644
--- a/conf/onos.properties
+++ b/conf/onos.properties
@@ -9,6 +9,7 @@
net.floodlightcontroller.ui.web.StaticWebRoutable,\
net.onrc.onos.datagrid.HazelcastDatagrid,\
net.onrc.onos.ofcontroller.flowmanager.FlowManager,\
+net.onrc.onos.ofcontroller.topology.TopologyManager,\
net.onrc.onos.registry.controller.ZookeeperRegistry
net.floodlightcontroller.restserver.RestApiServer.port = 8080
net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
diff --git a/pom.xml b/pom.xml
index 71e8192..002ba60 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,7 @@
<exclude>**/*TestCase.java</exclude>
-->
</excludes>
+ <argLine>-XX:MaxPermSize=256m</argLine>
</configuration>
</plugin>
<!-- exec:java -->
@@ -165,6 +166,14 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </plugin>
</plugins>
</build>
<!-- for getting visualization reporting -->
@@ -349,7 +358,7 @@
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
- <version>3.2</version>
+ <version>3.1</version>
<scope>test</scope>
</dependency>
<dependency>
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 44510a7..134a3b0 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -2352,7 +2352,7 @@
// new controller node IP
addedControllerNodeIPs.put(controllerID, discoveredIP);
}
- else if (curIP.equals(discoveredIP)) {
+ else if (!curIP.equals(discoveredIP)) {
// IP changed
removedControllerNodeIPs.put(controllerID, curIP);
addedControllerNodeIPs.put(controllerID, discoveredIP);
diff --git a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
index 7736880..3ff773e 100644
--- a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
+++ b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
@@ -27,9 +27,7 @@
* appropriate in a multi-node cluster.
*/
public class HazelcastDatagrid implements IFloodlightModule, IDatagridService {
- protected static Logger log =
- LoggerFactory.getLogger(HazelcastDatagrid.class);
-
+ protected static Logger log = LoggerFactory.getLogger(HazelcastDatagrid.class);
protected IFloodlightProviderService floodlightProvider;
protected static final String HazelcastConfigFile = "datagridConfig";
@@ -101,7 +99,7 @@
public Map<Class<? extends IFloodlightService>, IFloodlightService>
getServiceImpls() {
Map<Class<? extends IFloodlightService>,
- IFloodlightService> m =
+ IFloodlightService> m =
new HashMap<Class<? extends IFloodlightService>,
IFloodlightService>();
m.put(IDatagridService.class, this);
diff --git a/src/main/java/net/onrc/onos/graph/GraphDBConnection.java b/src/main/java/net/onrc/onos/graph/GraphDBConnection.java
index f9f3b67..bebcdd2 100644
--- a/src/main/java/net/onrc/onos/graph/GraphDBConnection.java
+++ b/src/main/java/net/onrc/onos/graph/GraphDBConnection.java
@@ -87,9 +87,10 @@
return singleton;
}
- /**
+ /**
* Get a FramedGraph instance of the graph.
*/
+ @Override
public FramedGraph<TitanGraph> getFramedGraph() {
if (isValid()) {
FramedGraph<TitanGraph> fg = new FramedGraph<TitanGraph>(graph);
@@ -115,6 +116,7 @@
/**
* Add LocalGraphChangedLister for the graph.
*/
+ @Override
public void addEventListener(final LocalGraphChangedListener listener) {
EventTransactionalGraph<TitanGraph> eg = this.getEventGraph();
eg.addListener(listener);
@@ -124,13 +126,15 @@
/**
* Return whether this connection is valid.
*/
+ @Override
public Boolean isValid() {
- return (graph != null || graph.isOpen());
+ return (graph != null && graph.isOpen());
}
/**
* Commit changes for the graph operations.
*/
+ @Override
public void commit() {
try {
graph.commit();
@@ -143,6 +147,7 @@
/**
* Rollback changes for the graph operations.
*/
+ @Override
public void rollback() {
try {
graph.rollback();
@@ -155,6 +160,7 @@
/**
* Close this database connection.
*/
+ @Override
public void close() {
commit();
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
index 9b6ac53..30b39a6 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -42,6 +42,7 @@
import net.onrc.onos.ofcontroller.proxyarp.IProxyArpService;
import net.onrc.onos.ofcontroller.proxyarp.ProxyArpManager;
import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
+import net.onrc.onos.ofcontroller.topology.Topology;
import net.onrc.onos.ofcontroller.topology.TopologyManager;
import net.onrc.onos.ofcontroller.util.DataPath;
import net.onrc.onos.ofcontroller.util.Dpid;
@@ -79,72 +80,72 @@
IOFSwitchListener, ILayer3InfoService,
IProxyArpService {
- protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);
+ private static Logger log = LoggerFactory.getLogger(BgpRoute.class);
- protected IFloodlightProviderService floodlightProvider;
- protected ITopologyService topology;
- protected ITopologyNetService topologyNetService;
- protected ILinkDiscoveryService linkDiscoveryService;
- protected IRestApiService restApi;
+ private IFloodlightProviderService floodlightProvider;
+ private ITopologyService topologyService;
+ private ITopologyNetService topologyNetService;
+ private ILinkDiscoveryService linkDiscoveryService;
+ private IRestApiService restApi;
- protected ProxyArpManager proxyArp;
+ private ProxyArpManager proxyArp;
- protected IPatriciaTrie<RibEntry> ptree;
- protected IPatriciaTrie<Interface> interfacePtrie;
- protected BlockingQueue<RibUpdate> ribUpdates;
+ private IPatriciaTrie<RibEntry> ptree;
+ private IPatriciaTrie<Interface> interfacePtrie;
+ private BlockingQueue<RibUpdate> ribUpdates;
- protected String bgpdRestIp;
- protected String routerId;
- protected String configFilename = "config.json";
+ private String bgpdRestIp;
+ private String routerId;
+ private String configFilename = "config.json";
//We need to identify our flows somehow. But like it says in LearningSwitch.java,
//the controller/OS should hand out cookie IDs to prevent conflicts.
- protected final long APP_COOKIE = 0xa0000000000000L;
+ private final long APP_COOKIE = 0xa0000000000000L;
//Cookie for flows that do L2 forwarding within SDN domain to egress routers
- protected final long L2_FWD_COOKIE = APP_COOKIE + 1;
+ private final long L2_FWD_COOKIE = APP_COOKIE + 1;
//Cookie for flows in ingress switches that rewrite the MAC address
- protected final long MAC_RW_COOKIE = APP_COOKIE + 2;
+ private final long MAC_RW_COOKIE = APP_COOKIE + 2;
//Cookie for flows that setup BGP paths
- protected final long BGP_COOKIE = APP_COOKIE + 3;
+ private final long BGP_COOKIE = APP_COOKIE + 3;
//Forwarding uses priority 0, and the mac rewrite entries in ingress switches
//need to be higher priority than this otherwise the rewrite may not get done
- protected final short SDNIP_PRIORITY = 10;
- protected final short ARP_PRIORITY = 20;
+ private final short SDNIP_PRIORITY = 10;
+ private final short ARP_PRIORITY = 20;
- protected final short BGP_PORT = 179;
+ private final short BGP_PORT = 179;
- protected final int TOPO_DETECTION_WAIT = 2; //seconds
+ private final int TOPO_DETECTION_WAIT = 2; //seconds
//Configuration stuff
- protected List<String> switches;
- protected Map<String, Interface> interfaces;
- protected Map<InetAddress, BgpPeer> bgpPeers;
- protected SwitchPort bgpdAttachmentPoint;
- protected MACAddress bgpdMacAddress;
+ private List<String> switches;
+ private Map<String, Interface> interfaces;
+ private Map<InetAddress, BgpPeer> bgpPeers;
+ private SwitchPort bgpdAttachmentPoint;
+ private MACAddress bgpdMacAddress;
//True when all switches have connected
- protected volatile boolean switchesConnected = false;
+ private volatile boolean switchesConnected = false;
//True when we have a full mesh of shortest paths between gateways
- protected volatile boolean topologyReady = false;
+ private volatile boolean topologyReady = false;
- protected ArrayList<LDUpdate> linkUpdates;
- protected SingletonTask topologyChangeDetectorTask;
+ private ArrayList<LDUpdate> linkUpdates;
+ private SingletonTask topologyChangeDetectorTask;
- protected SetMultimap<InetAddress, RibUpdate> prefixesWaitingOnArp;
+ private SetMultimap<InetAddress, RibUpdate> prefixesWaitingOnArp;
- protected Map<InetAddress, Path> pathsWaitingOnArp;
+ private Map<InetAddress, Path> pathsWaitingOnArp;
- protected ExecutorService bgpUpdatesExecutor;
+ private ExecutorService bgpUpdatesExecutor;
- protected Map<InetAddress, Path> pushedPaths;
- protected Map<Prefix, Path> prefixToPath;
- protected Multimap<Prefix, PushedFlowMod> pushedFlows;
+ private Map<InetAddress, Path> pushedPaths;
+ private Map<Prefix, Path> prefixToPath;
+ private Multimap<Prefix, PushedFlowMod> pushedFlows;
private FlowCache flowCache;
- protected volatile Map<Long, ?> shortestPathTopo = null;
+ private volatile Topology topology = null;
- protected class TopologyChangeDetector implements Runnable {
+ private class TopologyChangeDetector implements Runnable {
@Override
public void run() {
log.debug("Running topology change detection task");
@@ -260,13 +261,13 @@
// Register floodlight provider and REST handler.
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
- topology = context.getServiceImpl(ITopologyService.class);
+ topologyService = context.getServiceImpl(ITopologyService.class);
linkDiscoveryService = context.getServiceImpl(ILinkDiscoveryService.class);
restApi = context.getServiceImpl(IRestApiService.class);
//TODO We'll initialise this here for now, but it should really be done as
//part of the controller core
- proxyArp = new ProxyArpManager(floodlightProvider, topology, this, restApi);
+ proxyArp = new ProxyArpManager(floodlightProvider, topologyService, this, restApi);
linkUpdates = new ArrayList<LDUpdate>();
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
@@ -318,7 +319,7 @@
@Override
public void startUp(FloodlightModuleContext context) {
restApi.addRestletRoutable(new BgpRouteWebRoutable());
- topology.addListener(this);
+ topologyService.addListener(this);
floodlightProvider.addOFSwitchListener(this);
proxyArp.startUp();
@@ -483,7 +484,7 @@
}
private void addPrefixFlows(Prefix prefix, Interface egressInterface, MACAddress nextHopMacAddress) {
- log.debug("Adding flows for prefix {} added, next hop mac {}",
+ log.debug("Adding flows for prefix {}, next hop mac {}",
prefix, nextHopMacAddress);
//We only need one flow mod per switch, so pick one interface on each switch
@@ -498,14 +499,14 @@
//Add a flow to rewrite mac for this prefix to all other border switches
for (Interface srcInterface : srcInterfaces.values()) {
DataPath shortestPath;
- if (shortestPathTopo == null) {
- shortestPath = topologyNetService.getShortestPath(
+ if (topology == null) {
+ shortestPath = topologyNetService.getDatabaseShortestPath(
srcInterface.getSwitchPort(),
egressInterface.getSwitchPort());
}
else {
- shortestPath = topologyNetService.getTopoShortestPath(
- shortestPathTopo, srcInterface.getSwitchPort(),
+ shortestPath = topologyNetService.getTopologyShortestPath(
+ topology, srcInterface.getSwitchPort(),
egressInterface.getSwitchPort());
}
@@ -692,17 +693,17 @@
List<PushedFlowMod> pushedFlows = new ArrayList<PushedFlowMod>();
for (Interface srcInterface : interfaces.values()) {
- if (dstInterface.equals(srcInterface.getName())){
+ if (dstInterface.getName().equals(srcInterface.getName())){
continue;
}
DataPath shortestPath;
- if (shortestPathTopo == null) {
- shortestPath = topologyNetService.getShortestPath(
+ if (topology == null) {
+ shortestPath = topologyNetService.getDatabaseShortestPath(
srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
}
else {
- shortestPath = topologyNetService.getTopoShortestPath(shortestPathTopo,
+ shortestPath = topologyNetService.getTopologyShortestPath(topology,
srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
}
@@ -771,7 +772,7 @@
for (BgpPeer bgpPeer : bgpPeers.values()){
Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
- DataPath path = topologyNetService.getShortestPath(
+ DataPath path = topologyNetService.getDatabaseShortestPath(
peerInterface.getSwitchPort(), bgpdAttachmentPoint);
if (path == null){
@@ -1046,7 +1047,7 @@
private void beginRouting(){
log.debug("Topology is now ready, beginning routing function");
- shortestPathTopo = topologyNetService.prepareShortestPathTopo();
+ topology = topologyNetService.newDatabaseTopology();
setupArpFlows();
setupDefaultDropFlows();
@@ -1086,7 +1087,7 @@
continue;
}
- DataPath shortestPath = topologyNetService.getShortestPath(
+ DataPath shortestPath = topologyNetService.getDatabaseShortestPath(
srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
if (shortestPath == null){
@@ -1120,10 +1121,22 @@
RibUpdate update = ribUpdates.take();
switch (update.getOperation()){
case UPDATE:
- processRibAdd(update);
+ if (validateUpdate(update)) {
+ processRibAdd(update);
+ }
+ else {
+ log.debug("Rib UPDATE out of order: {} via {}",
+ update.getPrefix(), update.getRibEntry().getNextHop());
+ }
break;
case DELETE:
- processRibDelete(update);
+ if (validateUpdate(update)) {
+ processRibDelete(update);
+ }
+ else {
+ log.debug("Rib DELETE out of order: {} via {}",
+ update.getPrefix(), update.getRibEntry().getNextHop());
+ }
break;
}
} catch (InterruptedException e) {
@@ -1139,6 +1152,40 @@
}
}
}
+
+ private boolean validateUpdate(RibUpdate update) {
+ RibEntry newEntry = update.getRibEntry();
+ RibEntry oldEntry = ptree.lookup(update.getPrefix());
+
+ //If there is no existing entry we must assume this is the most recent
+ //update. However this might not always be the case as we might have a
+ //POST then DELETE reordering.
+ //if (oldEntry == null || !newEntry.getNextHop().equals(oldEntry.getNextHop())) {
+ if (oldEntry == null) {
+ return true;
+ }
+
+ // This handles the case where routes are gathered in the initial
+ // request because they don't have sequence number info
+ if (newEntry.getSysUpTime() == -1 && newEntry.getSequenceNum() == -1) {
+ return true;
+ }
+
+ if (newEntry.getSysUpTime() > oldEntry.getSysUpTime()) {
+ return true;
+ }
+ else if (newEntry.getSysUpTime() == oldEntry.getSysUpTime()) {
+ if (newEntry.getSequenceNum() > oldEntry.getSequenceNum()) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+ }
@Override
public void topologyChanged() {
@@ -1147,7 +1194,7 @@
}
boolean refreshNeeded = false;
- for (LDUpdate ldu : topology.getLastLinkUpdates()){
+ for (LDUpdate ldu : topologyService.getLastLinkUpdates()){
if (!ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_UPDATED)){
//We don't need to recalculate anything for just link updates
//They happen very frequently
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
index 8403f71..c1f0cd6 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
@@ -68,19 +68,27 @@
IBgpRouteService bgpRoute = (IBgpRouteService) getContext().getAttributes().
get(IBgpRouteService.class.getCanonicalName());
+ String strSysuptime = (String) getRequestAttributes().get("sysuptime");
+ String strSequence = (String) getRequestAttributes().get("sequence");
String routerId = (String) getRequestAttributes().get("routerid");
String prefix = (String) getRequestAttributes().get("prefix");
String mask = (String) getRequestAttributes().get("mask");
String nexthop = (String) getRequestAttributes().get("nexthop");
String capability = (String) getRequestAttributes().get("capability");
+
+ log.debug("sysuptime: {}", strSysuptime);
+ log.debug("sequence: {}", strSequence);
String reply = "";
if (capability == null) {
// this is a prefix add
Prefix p;
+ long sysUpTime, sequenceNum;
try {
p = new Prefix(prefix, Integer.valueOf(mask));
+ sysUpTime = Long.parseLong(strSysuptime);
+ sequenceNum = Long.parseLong(strSequence);
} catch (NumberFormatException e) {
reply = "[POST: mask format is wrong]";
log.info(reply);
@@ -91,7 +99,7 @@
return reply + "\n";
}
- RibEntry rib = new RibEntry(routerId, nexthop);
+ RibEntry rib = new RibEntry(routerId, nexthop, sysUpTime, sequenceNum);
bgpRoute.newRibUpdate(new RibUpdate(Operation.UPDATE, p, rib));
@@ -117,19 +125,27 @@
IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
get(IBgpRouteService.class.getCanonicalName());
+ String strSysuptime = (String) getRequestAttributes().get("sysuptime");
+ String strSequence = (String) getRequestAttributes().get("sequence");
String routerId = (String) getRequestAttributes().get("routerid");
String prefix = (String) getRequestAttributes().get("prefix");
String mask = (String) getRequestAttributes().get("mask");
String nextHop = (String) getRequestAttributes().get("nexthop");
String capability = (String) getRequestAttributes().get("capability");
+ log.debug("sysuptime: {}", strSysuptime);
+ log.debug("sequence: {}", strSequence);
+
String reply = "";
if (capability == null) {
// this is a prefix delete
Prefix p;
+ long sysUpTime, sequenceNum;
try {
p = new Prefix(prefix, Integer.valueOf(mask));
+ sysUpTime = Long.parseLong(strSysuptime);
+ sequenceNum = Long.parseLong(strSequence);
} catch (NumberFormatException e) {
reply = "[DELE: mask format is wrong]";
log.info(reply);
@@ -140,7 +156,7 @@
return reply + "\n";
}
- RibEntry r = new RibEntry(routerId, nextHop);
+ RibEntry r = new RibEntry(routerId, nextHop, sysUpTime, sequenceNum);
bgpRoute.newRibUpdate(new RibUpdate(Operation.DELETE, p, r));
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
index 669c385..26971b0 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
@@ -12,7 +12,7 @@
Router router = new Router(context);
router.attach("/json", BgpRouteResource.class);
router.attach("/rib/{dest}", BgpRouteResource.class);
- router.attach("/{routerid}/{prefix}/{mask}/{nexthop}", BgpRouteResource.class);
+ router.attach("/{sysuptime}/{sequence}/{routerid}/{prefix}/{mask}/{nexthop}", BgpRouteResource.class);
router.attach("/{routerid}/{prefix}/{mask}/{nexthop}/synch", BgpRouteResourceSynch.class);
router.attach("/{routerid}/{capability}", BgpRouteResource.class);
return router;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibEntry.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibEntry.java
index 1520c60..ccf8951 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibEntry.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibEntry.java
@@ -7,21 +7,57 @@
public class RibEntry {
private final InetAddress routerId;
private final InetAddress nextHop;
+
+ /*
+ * Store the sequence number information provided on the update here for
+ * now. I think this *should* really be in the RibUpdate, and we should
+ * store RibUpdates in the Ptrie. But, that's a bigger change to change
+ * what the Ptrie stores.
+ */
+ private final long sysUpTime;
+ private final long sequenceNum;
+
+ /*
+ * Marker for RibEntries where we don't have sequence number info.
+ * The user of this class should make sure they don't check this data
+ * if they don't provide it.
+ */
+ private final static long NULL_TIME = -1;
public RibEntry(InetAddress routerId, InetAddress nextHop) {
this.routerId = routerId;
this.nextHop = nextHop;
+ sequenceNum = NULL_TIME;
+ sysUpTime = NULL_TIME;
}
public RibEntry(String routerId, String nextHop) {
this.routerId = InetAddresses.forString(routerId);
this.nextHop = InetAddresses.forString(nextHop);
+ sequenceNum = NULL_TIME;
+ sysUpTime = NULL_TIME;
+ }
+
+ public RibEntry(String routerId, String nextHop, long sysUpTime
+ , long sequenceNum) {
+ this.routerId = InetAddresses.forString(routerId);
+ this.nextHop = InetAddresses.forString(nextHop);
+ this.sequenceNum = sequenceNum;
+ this.sysUpTime = sysUpTime;
}
public InetAddress getNextHop() {
return nextHop;
}
+ public long getSysUpTime() {
+ return sysUpTime;
+ }
+
+ public long getSequenceNum() {
+ return sequenceNum;
+ }
+
@Override
public boolean equals(Object other) {
if (other == null || !(other instanceof RibEntry)) {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
index 978fcde..cd3cf15 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
@@ -18,7 +18,7 @@
}
public TopoSwitchServiceImpl() {
- this("/tmp/cassandra.titan");
+ this("");
}
public void finalize() {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/INetworkGraphService.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/INetworkGraphService.java
new file mode 100644
index 0000000..121eaf9
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/INetworkGraphService.java
@@ -0,0 +1,10 @@
+package net.onrc.onos.ofcontroller.floodlightlistener;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+/**
+ * Interface for providing Network Graph Service to other module.
+ */
+public interface INetworkGraphService extends IFloodlightService {
+ // TODO
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
index 046a38b..852cbb8 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -45,8 +46,12 @@
import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
import net.onrc.onos.registry.controller.RegistryException;
-public class NetworkGraphPublisher implements IDeviceListener, IOFSwitchListener, IOFSwitchPortListener,
- ILinkDiscoveryListener, IFloodlightModule {
+public class NetworkGraphPublisher implements IDeviceListener,
+ IOFSwitchListener,
+ IOFSwitchPortListener,
+ ILinkDiscoveryListener,
+ IFloodlightModule,
+ INetworkGraphService {
protected IDeviceStorage devStore;
protected ISwitchStorage swStore;
@@ -229,14 +234,20 @@
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
- // TODO Auto-generated method stub
- return null;
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(INetworkGraphService.class);
+ return l;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
- // TODO Auto-generated method stub
- return null;
+ Map<Class<? extends IFloodlightService>,
+ IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>,
+ IFloodlightService>();
+ m.put(INetworkGraphService.class, this);
+ return m;
}
@Override
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
new file mode 100644
index 0000000..7550b37
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
@@ -0,0 +1,926 @@
+package net.onrc.onos.ofcontroller.flowmanager;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import net.floodlightcontroller.util.MACAddress;
+
+import net.onrc.onos.graph.GraphDBOperation;
+
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.util.*;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class for performing Flow-related operations on the Database.
+ */
+class FlowDatabaseOperation {
+ private static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
+
+ /**
+ * Add a flow.
+ *
+ * @param flowManager the Flow Manager to use.
+ * @param dbHandler the Graph Database handler to use.
+ * @param flowPath the Flow Path to install.
+ * @param flowId the return-by-reference Flow ID as assigned internally.
+ * @param dataPathSummaryStr the data path summary string if the added
+ * flow will be maintained internally, otherwise null.
+ * @return true on success, otherwise false.
+ */
+ static boolean addFlow(FlowManager flowManager,
+ GraphDBOperation dbHandler,
+ FlowPath flowPath, FlowId flowId,
+ String dataPathSummaryStr) {
+ IFlowPath flowObj = null;
+ boolean found = false;
+ try {
+ if ((flowObj = dbHandler.searchFlowPath(flowPath.flowId())) != null) {
+ found = true;
+ } else {
+ flowObj = dbHandler.newFlowPath();
+ }
+ } catch (Exception e) {
+ dbHandler.rollback();
+
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ String stacktrace = sw.toString();
+
+ log.error(":addFlow FlowId:{} failed: {}",
+ flowPath.flowId().toString(),
+ stacktrace);
+ return false;
+ }
+ if (flowObj == null) {
+ log.error(":addFlow FlowId:{} failed: Flow object not created",
+ flowPath.flowId().toString());
+ dbHandler.rollback();
+ return false;
+ }
+
+ //
+ // Set the Flow key:
+ // - flowId
+ //
+ flowObj.setFlowId(flowPath.flowId().toString());
+ flowObj.setType("flow");
+
+ //
+ // Set the Flow attributes:
+ // - flowPath.installerId()
+ // - flowPath.flowPathFlags()
+ // - flowPath.dataPath().srcPort()
+ // - flowPath.dataPath().dstPort()
+ // - flowPath.matchSrcMac()
+ // - flowPath.matchDstMac()
+ // - flowPath.matchEthernetFrameType()
+ // - flowPath.matchVlanId()
+ // - flowPath.matchVlanPriority()
+ // - flowPath.matchSrcIPv4Net()
+ // - flowPath.matchDstIPv4Net()
+ // - flowPath.matchIpProto()
+ // - flowPath.matchIpToS()
+ // - flowPath.matchSrcTcpUdpPort()
+ // - flowPath.matchDstTcpUdpPort()
+ // - flowPath.flowEntryActions()
+ //
+ flowObj.setInstallerId(flowPath.installerId().toString());
+ flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
+ flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
+ flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
+ flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
+ flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
+ if (flowPath.flowEntryMatch().matchSrcMac()) {
+ flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
+ }
+ if (flowPath.flowEntryMatch().matchDstMac()) {
+ flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
+ }
+ if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
+ flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
+ }
+ if (flowPath.flowEntryMatch().matchVlanId()) {
+ flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
+ }
+ if (flowPath.flowEntryMatch().matchVlanPriority()) {
+ flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
+ }
+ if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
+ flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
+ }
+ if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
+ flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
+ }
+ if (flowPath.flowEntryMatch().matchIpProto()) {
+ flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
+ }
+ if (flowPath.flowEntryMatch().matchIpToS()) {
+ flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
+ }
+ if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
+ flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
+ }
+ if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
+ flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
+ }
+ if (! flowPath.flowEntryActions().actions().isEmpty()) {
+ flowObj.setActions(flowPath.flowEntryActions().toString());
+ }
+
+ if (dataPathSummaryStr != null) {
+ flowObj.setDataPathSummary(dataPathSummaryStr);
+ } else {
+ flowObj.setDataPathSummary("");
+ }
+
+ if (found)
+ flowObj.setUserState("FE_USER_MODIFY");
+ else
+ flowObj.setUserState("FE_USER_ADD");
+
+ // Flow edges:
+ // HeadFE
+
+
+ //
+ // Flow Entries:
+ // flowPath.dataPath().flowEntries()
+ //
+ for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
+ if (addFlowEntry(flowManager, dbHandler, flowObj, flowEntry) == null) {
+ dbHandler.rollback();
+ return false;
+ }
+ }
+ dbHandler.commit();
+
+ //
+ // TODO: We need a proper Flow ID allocation mechanism.
+ //
+ flowId.setValue(flowPath.flowId().value());
+
+ return true;
+ }
+
+ /**
+ * Add a flow entry to the Network MAP.
+ *
+ * @param flowManager the Flow Manager to use.
+ * @param dbHandler the Graph Database handler to use.
+ * @param flowObj the corresponding Flow Path object for the Flow Entry.
+ * @param flowEntry the Flow Entry to install.
+ * @return the added Flow Entry object on success, otherwise null.
+ */
+ static IFlowEntry addFlowEntry(FlowManager flowManager,
+ GraphDBOperation dbHandler,
+ IFlowPath flowObj,
+ FlowEntry flowEntry) {
+ // Flow edges
+ // HeadFE (TODO)
+
+ //
+ // Assign the FlowEntry ID.
+ //
+ if ((flowEntry.flowEntryId() == null) ||
+ (flowEntry.flowEntryId().value() == 0)) {
+ long id = flowManager.getNextFlowEntryId();
+ flowEntry.setFlowEntryId(new FlowEntryId(id));
+ }
+
+ IFlowEntry flowEntryObj = null;
+ boolean found = false;
+ try {
+ if ((flowEntryObj =
+ dbHandler.searchFlowEntry(flowEntry.flowEntryId())) != null) {
+ found = true;
+ } else {
+ flowEntryObj = dbHandler.newFlowEntry();
+ }
+ } catch (Exception e) {
+ log.error(":addFlow FlowEntryId:{} failed",
+ flowEntry.flowEntryId().toString());
+ return null;
+ }
+ if (flowEntryObj == null) {
+ log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
+ flowEntry.flowEntryId().toString());
+ return null;
+ }
+
+ //
+ // Set the Flow Entry key:
+ // - flowEntry.flowEntryId()
+ //
+ flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
+ flowEntryObj.setType("flow_entry");
+
+ //
+ // Set the Flow Entry Edges and attributes:
+ // - Switch edge
+ // - InPort edge
+ // - OutPort edge
+ //
+ // - flowEntry.dpid()
+ // - flowEntry.flowEntryUserState()
+ // - flowEntry.flowEntrySwitchState()
+ // - flowEntry.flowEntryErrorState()
+ // - flowEntry.matchInPort()
+ // - flowEntry.matchSrcMac()
+ // - flowEntry.matchDstMac()
+ // - flowEntry.matchEthernetFrameType()
+ // - flowEntry.matchVlanId()
+ // - flowEntry.matchVlanPriority()
+ // - flowEntry.matchSrcIPv4Net()
+ // - flowEntry.matchDstIPv4Net()
+ // - flowEntry.matchIpProto()
+ // - flowEntry.matchIpToS()
+ // - flowEntry.matchSrcTcpUdpPort()
+ // - flowEntry.matchDstTcpUdpPort()
+ // - flowEntry.actionOutputPort()
+ // - flowEntry.actions()
+ //
+ ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
+ flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
+ flowEntryObj.setSwitch(sw);
+ if (flowEntry.flowEntryMatch().matchInPort()) {
+ IPortObject inport =
+ dbHandler.searchPort(flowEntry.dpid().toString(),
+ flowEntry.flowEntryMatch().inPort().value());
+ flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
+ flowEntryObj.setInPort(inport);
+ }
+ if (flowEntry.flowEntryMatch().matchSrcMac()) {
+ flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
+ }
+ if (flowEntry.flowEntryMatch().matchDstMac()) {
+ flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
+ }
+ if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
+ flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
+ }
+ if (flowEntry.flowEntryMatch().matchVlanId()) {
+ flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
+ }
+ if (flowEntry.flowEntryMatch().matchVlanPriority()) {
+ flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
+ }
+ if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
+ flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
+ }
+ if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
+ flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
+ }
+ if (flowEntry.flowEntryMatch().matchIpProto()) {
+ flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
+ }
+ if (flowEntry.flowEntryMatch().matchIpToS()) {
+ flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
+ }
+ if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
+ flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
+ }
+ if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
+ flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
+ }
+
+ for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
+ if (fa.actionOutput() != null) {
+ IPortObject outport =
+ dbHandler.searchPort(flowEntry.dpid().toString(),
+ fa.actionOutput().port().value());
+ flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
+ flowEntryObj.setOutPort(outport);
+ }
+ }
+ if (! flowEntry.flowEntryActions().isEmpty()) {
+ flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
+ }
+
+ // TODO: Hacks with hard-coded state names!
+ if (found)
+ flowEntryObj.setUserState("FE_USER_MODIFY");
+ else
+ flowEntryObj.setUserState("FE_USER_ADD");
+ flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
+ //
+ // TODO: Take care of the FlowEntryErrorState.
+ //
+
+ // Flow Entries edges:
+ // Flow
+ // NextFE (TODO)
+ if (! found) {
+ flowObj.addFlowEntry(flowEntryObj);
+ flowEntryObj.setFlow(flowObj);
+ }
+
+ return flowEntryObj;
+ }
+
+ /**
+ * Delete all previously added flows.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @return true on success, otherwise false.
+ */
+ static boolean deleteAllFlows(GraphDBOperation dbHandler) {
+ final ConcurrentLinkedQueue<FlowId> concurrentAllFlowIds =
+ new ConcurrentLinkedQueue<FlowId>();
+
+ // Get all Flow IDs
+ Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
+ for (IFlowPath flowPathObj : allFlowPaths) {
+ if (flowPathObj == null)
+ continue;
+ String flowIdStr = flowPathObj.getFlowId();
+ if (flowIdStr == null)
+ continue;
+ FlowId flowId = new FlowId(flowIdStr);
+ concurrentAllFlowIds.add(flowId);
+ }
+
+ // Delete all flows one-by-one
+ for (FlowId flowId : concurrentAllFlowIds)
+ deleteFlow(dbHandler, flowId);
+
+ /*
+ * TODO: A faster mechanism to delete the Flow Paths by using
+ * a number of threads. Commented-out for now.
+ */
+ /*
+ //
+ // Create the threads to delete the Flow Paths
+ //
+ List<Thread> threads = new LinkedList<Thread>();
+ for (int i = 0; i < 10; i++) {
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (true) {
+ FlowId flowId = concurrentAllFlowIds.poll();
+ if (flowId == null)
+ return;
+ deleteFlow(dbHandler, flowId);
+ }
+ }}, "Delete All Flow Paths");
+ threads.add(thread);
+ }
+
+ // Start processing
+ for (Thread thread : threads) {
+ thread.start();
+ }
+
+ // Wait for all threads to complete
+ for (Thread thread : threads) {
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ log.debug("Exception waiting for a thread to delete a Flow Path: ", e);
+ }
+ }
+ */
+
+ return true;
+ }
+
+ /**
+ * Delete a previously added flow.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @param flowId the Flow ID of the flow to delete.
+ * @return true on success, otherwise false.
+ */
+ static boolean deleteFlow(GraphDBOperation dbHandler, FlowId flowId) {
+ IFlowPath flowObj = null;
+ //
+ // We just mark the entries for deletion,
+ // and let the switches remove each individual entry after
+ // it has been removed from the switches.
+ //
+ try {
+ flowObj = dbHandler.searchFlowPath(flowId);
+ } catch (Exception e) {
+ // TODO: handle exceptions
+ dbHandler.rollback();
+ log.error(":deleteFlow FlowId:{} failed", flowId.toString());
+ return false;
+ }
+ if (flowObj == null) {
+ dbHandler.commit();
+ return true; // OK: No such flow
+ }
+
+ //
+ // Find and mark for deletion all Flow Entries,
+ // and the Flow itself.
+ //
+ flowObj.setUserState("FE_USER_DELETE");
+ Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+ boolean empty = true; // TODO: an ugly hack
+ for (IFlowEntry flowEntryObj : flowEntries) {
+ empty = false;
+ // flowObj.removeFlowEntry(flowEntryObj);
+ // conn.utils().removeFlowEntry(conn, flowEntryObj);
+ flowEntryObj.setUserState("FE_USER_DELETE");
+ flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
+ }
+ // Remove from the database empty flows
+ if (empty)
+ dbHandler.removeFlowPath(flowObj);
+ dbHandler.commit();
+
+ return true;
+ }
+
+ /**
+ * Clear the state for all previously added flows.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @return true on success, otherwise false.
+ */
+ static boolean clearAllFlows(GraphDBOperation dbHandler) {
+ List<FlowId> allFlowIds = new LinkedList<FlowId>();
+
+ // Get all Flow IDs
+ Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
+ for (IFlowPath flowPathObj : allFlowPaths) {
+ if (flowPathObj == null)
+ continue;
+ String flowIdStr = flowPathObj.getFlowId();
+ if (flowIdStr == null)
+ continue;
+ FlowId flowId = new FlowId(flowIdStr);
+ allFlowIds.add(flowId);
+ }
+
+ // Clear all flows one-by-one
+ for (FlowId flowId : allFlowIds) {
+ clearFlow(dbHandler, flowId);
+ }
+
+ return true;
+ }
+
+ /**
+ * Clear the state for a previously added flow.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @param flowId the Flow ID of the flow to clear.
+ * @return true on success, otherwise false.
+ */
+ static boolean clearFlow(GraphDBOperation dbHandler, FlowId flowId) {
+ IFlowPath flowObj = null;
+ try {
+ flowObj = dbHandler.searchFlowPath(flowId);
+ } catch (Exception e) {
+ // TODO: handle exceptions
+ dbHandler.rollback();
+ log.error(":clearFlow FlowId:{} failed", flowId.toString());
+ return false;
+ }
+ if (flowObj == null) {
+ dbHandler.commit();
+ return true; // OK: No such flow
+ }
+
+ //
+ // Remove all Flow Entries
+ //
+ Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+ for (IFlowEntry flowEntryObj : flowEntries) {
+ flowObj.removeFlowEntry(flowEntryObj);
+ dbHandler.removeFlowEntry(flowEntryObj);
+ }
+ // Remove the Flow itself
+ dbHandler.removeFlowPath(flowObj);
+ dbHandler.commit();
+
+ return true;
+ }
+
+ /**
+ * Get a previously added flow.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @param flowId the Flow ID of the flow to get.
+ * @return the Flow Path if found, otherwise null.
+ */
+ static FlowPath getFlow(GraphDBOperation dbHandler, FlowId flowId) {
+ IFlowPath flowObj = null;
+ try {
+ flowObj = dbHandler.searchFlowPath(flowId);
+ } catch (Exception e) {
+ // TODO: handle exceptions
+ dbHandler.rollback();
+ log.error(":getFlow FlowId:{} failed", flowId.toString());
+ return null;
+ }
+ if (flowObj == null) {
+ dbHandler.commit();
+ return null; // Flow not found
+ }
+
+ //
+ // Extract the Flow state
+ //
+ FlowPath flowPath = extractFlowPath(flowObj);
+ dbHandler.commit();
+
+ return flowPath;
+ }
+
+ /**
+ * Get all installed flows by all installers.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @return the Flow Paths if found, otherwise null.
+ */
+ static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler) {
+ Iterable<IFlowPath> flowPathsObj = null;
+ ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
+
+ try {
+ flowPathsObj = dbHandler.getAllFlowPaths();
+ } catch (Exception e) {
+ // TODO: handle exceptions
+ dbHandler.rollback();
+ log.error(":getAllFlowPaths failed");
+ return flowPaths;
+ }
+ if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
+ dbHandler.commit();
+ return flowPaths; // No Flows found
+ }
+
+ for (IFlowPath flowObj : flowPathsObj) {
+ //
+ // Extract the Flow state
+ //
+ FlowPath flowPath = extractFlowPath(flowObj);
+ if (flowPath != null)
+ flowPaths.add(flowPath);
+ }
+
+ dbHandler.commit();
+
+ return flowPaths;
+ }
+
+ /**
+ * Get all previously added flows by a specific installer for a given
+ * data path endpoints.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @param installerId the Caller ID of the installer of the flow to get.
+ * @param dataPathEndpoints the data path endpoints of the flow to get.
+ * @return the Flow Paths if found, otherwise null.
+ */
+ static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler,
+ CallerId installerId,
+ DataPathEndpoints dataPathEndpoints) {
+ //
+ // TODO: The implementation below is not optimal:
+ // We fetch all flows, and then return only the subset that match
+ // the query conditions.
+ // We should use the appropriate Titan/Gremlin query to filter-out
+ // the flows as appropriate.
+ //
+ ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
+ ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
+
+ if (allFlows == null)
+ return flowPaths;
+
+ for (FlowPath flow : allFlows) {
+ //
+ // TODO: String-based comparison is sub-optimal.
+ // We are using it for now to save us the extra work of
+ // implementing the "equals()" and "hashCode()" methods.
+ //
+ if (! flow.installerId().toString().equals(installerId.toString()))
+ continue;
+ if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
+ continue;
+ }
+ if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
+ continue;
+ }
+ flowPaths.add(flow);
+ }
+
+ return flowPaths;
+ }
+
+ /**
+ * Get all installed flows by all installers for given data path endpoints.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @param dataPathEndpoints the data path endpoints of the flows to get.
+ * @return the Flow Paths if found, otherwise null.
+ */
+ static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler,
+ DataPathEndpoints dataPathEndpoints) {
+ //
+ // TODO: The implementation below is not optimal:
+ // We fetch all flows, and then return only the subset that match
+ // the query conditions.
+ // We should use the appropriate Titan/Gremlin query to filter-out
+ // the flows as appropriate.
+ //
+ ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
+ ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
+
+ if (allFlows == null)
+ return flowPaths;
+
+ for (FlowPath flow : allFlows) {
+ //
+ // TODO: String-based comparison is sub-optimal.
+ // We are using it for now to save us the extra work of
+ // implementing the "equals()" and "hashCode()" methods.
+ //
+ if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
+ continue;
+ }
+ if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
+ continue;
+ }
+ flowPaths.add(flow);
+ }
+
+ return flowPaths;
+ }
+
+ /**
+ * Get summary of all installed flows by all installers in a given range.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @param flowId the Flow ID of the first flow in the flow range to get.
+ * @param maxFlows the maximum number of flows to be returned.
+ * @return the Flow Paths if found, otherwise null.
+ */
+ static ArrayList<IFlowPath> getAllFlowsSummary(GraphDBOperation dbHandler,
+ FlowId flowId,
+ int maxFlows) {
+ //
+ // TODO: The implementation below is not optimal:
+ // We fetch all flows, and then return only the subset that match
+ // the query conditions.
+ // We should use the appropriate Titan/Gremlin query to filter-out
+ // the flows as appropriate.
+ //
+ ArrayList<IFlowPath> flowPathsWithoutFlowEntries =
+ getAllFlowsWithoutFlowEntries(dbHandler);
+
+ Collections.sort(flowPathsWithoutFlowEntries,
+ new Comparator<IFlowPath>() {
+ @Override
+ public int compare(IFlowPath first, IFlowPath second) {
+ long result =
+ new FlowId(first.getFlowId()).value()
+ - new FlowId(second.getFlowId()).value();
+ if (result > 0) {
+ return 1;
+ } else if (result < 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ }
+ );
+
+ return flowPathsWithoutFlowEntries;
+ }
+
+ /**
+ * Get all Flows information, without the associated Flow Entries.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @return all Flows information, without the associated Flow Entries.
+ */
+ static ArrayList<IFlowPath> getAllFlowsWithoutFlowEntries(GraphDBOperation dbHandler) {
+ Iterable<IFlowPath> flowPathsObj = null;
+ ArrayList<IFlowPath> flowPathsObjArray = new ArrayList<IFlowPath>();
+
+ // TODO: Remove this op.commit() flow, because it is not needed?
+ dbHandler.commit();
+
+ try {
+ flowPathsObj = dbHandler.getAllFlowPaths();
+ } catch (Exception e) {
+ // TODO: handle exceptions
+ dbHandler.rollback();
+ log.error(":getAllFlowPaths failed");
+ return flowPathsObjArray; // No Flows found
+ }
+ if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
+ return flowPathsObjArray; // No Flows found
+ }
+
+ for (IFlowPath flowObj : flowPathsObj)
+ flowPathsObjArray.add(flowObj);
+
+ // conn.endTx(Transaction.COMMIT);
+
+ return flowPathsObjArray;
+ }
+
+ /**
+ * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
+ *
+ * @param flowObj the object to extract the Flow Path State from.
+ * @return the extracted Flow Path State.
+ */
+ private static FlowPath extractFlowPath(IFlowPath flowObj) {
+ //
+ // Extract the Flow state
+ //
+ String flowIdStr = flowObj.getFlowId();
+ String installerIdStr = flowObj.getInstallerId();
+ Long flowPathFlags = flowObj.getFlowPathFlags();
+ String srcSwitchStr = flowObj.getSrcSwitch();
+ Short srcPortShort = flowObj.getSrcPort();
+ String dstSwitchStr = flowObj.getDstSwitch();
+ Short dstPortShort = flowObj.getDstPort();
+
+ if ((flowIdStr == null) ||
+ (installerIdStr == null) ||
+ (flowPathFlags == null) ||
+ (srcSwitchStr == null) ||
+ (srcPortShort == null) ||
+ (dstSwitchStr == null) ||
+ (dstPortShort == null)) {
+ // TODO: A work-around, becauuse of some bogus database objects
+ return null;
+ }
+
+ FlowPath flowPath = new FlowPath();
+ flowPath.setFlowId(new FlowId(flowIdStr));
+ flowPath.setInstallerId(new CallerId(installerIdStr));
+ flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
+ flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
+ flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
+ flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
+ flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
+ //
+ // Extract the match conditions common for all Flow Entries
+ //
+ {
+ FlowEntryMatch match = new FlowEntryMatch();
+ String matchSrcMac = flowObj.getMatchSrcMac();
+ if (matchSrcMac != null)
+ match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+ String matchDstMac = flowObj.getMatchDstMac();
+ if (matchDstMac != null)
+ match.enableDstMac(MACAddress.valueOf(matchDstMac));
+ Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
+ if (matchEthernetFrameType != null)
+ match.enableEthernetFrameType(matchEthernetFrameType);
+ Short matchVlanId = flowObj.getMatchVlanId();
+ if (matchVlanId != null)
+ match.enableVlanId(matchVlanId);
+ Byte matchVlanPriority = flowObj.getMatchVlanPriority();
+ if (matchVlanPriority != null)
+ match.enableVlanPriority(matchVlanPriority);
+ String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
+ if (matchSrcIPv4Net != null)
+ match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+ String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
+ if (matchDstIPv4Net != null)
+ match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+ Byte matchIpProto = flowObj.getMatchIpProto();
+ if (matchIpProto != null)
+ match.enableIpProto(matchIpProto);
+ Byte matchIpToS = flowObj.getMatchIpToS();
+ if (matchIpToS != null)
+ match.enableIpToS(matchIpToS);
+ Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
+ if (matchSrcTcpUdpPort != null)
+ match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
+ Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
+ if (matchDstTcpUdpPort != null)
+ match.enableDstTcpUdpPort(matchDstTcpUdpPort);
+
+ flowPath.setFlowEntryMatch(match);
+ }
+ //
+ // Extract the actions for the first Flow Entry
+ //
+ {
+ String actionsStr = flowObj.getActions();
+ if (actionsStr != null) {
+ FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
+ flowPath.setFlowEntryActions(flowEntryActions);
+ }
+ }
+
+ //
+ // Extract all Flow Entries
+ //
+ Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+ for (IFlowEntry flowEntryObj : flowEntries) {
+ FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
+ if (flowEntry == null)
+ continue;
+ flowPath.dataPath().flowEntries().add(flowEntry);
+ }
+
+ return flowPath;
+ }
+
+ /**
+ * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
+ *
+ * @param flowEntryObj the object to extract the Flow Entry State from.
+ * @return the extracted Flow Entry State.
+ */
+ private static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
+ String flowEntryIdStr = flowEntryObj.getFlowEntryId();
+ String switchDpidStr = flowEntryObj.getSwitchDpid();
+ String userState = flowEntryObj.getUserState();
+ String switchState = flowEntryObj.getSwitchState();
+
+ if ((flowEntryIdStr == null) ||
+ (switchDpidStr == null) ||
+ (userState == null) ||
+ (switchState == null)) {
+ // TODO: A work-around, becauuse of some bogus database objects
+ return null;
+ }
+
+ FlowEntry flowEntry = new FlowEntry();
+ flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
+ flowEntry.setDpid(new Dpid(switchDpidStr));
+
+ //
+ // Extract the match conditions
+ //
+ FlowEntryMatch match = new FlowEntryMatch();
+ Short matchInPort = flowEntryObj.getMatchInPort();
+ if (matchInPort != null)
+ match.enableInPort(new Port(matchInPort));
+ String matchSrcMac = flowEntryObj.getMatchSrcMac();
+ if (matchSrcMac != null)
+ match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+ String matchDstMac = flowEntryObj.getMatchDstMac();
+ if (matchDstMac != null)
+ match.enableDstMac(MACAddress.valueOf(matchDstMac));
+ Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+ if (matchEthernetFrameType != null)
+ match.enableEthernetFrameType(matchEthernetFrameType);
+ Short matchVlanId = flowEntryObj.getMatchVlanId();
+ if (matchVlanId != null)
+ match.enableVlanId(matchVlanId);
+ Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
+ if (matchVlanPriority != null)
+ match.enableVlanPriority(matchVlanPriority);
+ String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+ if (matchSrcIPv4Net != null)
+ match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+ String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+ if (matchDstIPv4Net != null)
+ match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+ Byte matchIpProto = flowEntryObj.getMatchIpProto();
+ if (matchIpProto != null)
+ match.enableIpProto(matchIpProto);
+ Byte matchIpToS = flowEntryObj.getMatchIpToS();
+ if (matchIpToS != null)
+ match.enableIpToS(matchIpToS);
+ Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
+ if (matchSrcTcpUdpPort != null)
+ match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
+ Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
+ if (matchDstTcpUdpPort != null)
+ match.enableDstTcpUdpPort(matchDstTcpUdpPort);
+ flowEntry.setFlowEntryMatch(match);
+
+ //
+ // Extract the actions
+ //
+ FlowEntryActions actions = new FlowEntryActions();
+ String actionsStr = flowEntryObj.getActions();
+ if (actionsStr != null)
+ actions = new FlowEntryActions(actionsStr);
+ flowEntry.setFlowEntryActions(actions);
+ flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
+ flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
+ //
+ // TODO: Take care of FlowEntryErrorState.
+ //
+ return flowEntry;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
index 2c5f4ba..e11814b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -1,19 +1,12 @@
package net.onrc.onos.ofcontroller.flowmanager;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import java.util.Random;
-import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -25,42 +18,20 @@
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.util.MACAddress;
import net.floodlightcontroller.util.OFMessageDamper;
+
+import net.onrc.onos.datagrid.IDatagridService;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.ofcontroller.core.INetMapStorage;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
-import net.onrc.onos.ofcontroller.topology.TopologyManager;
-import net.onrc.onos.ofcontroller.util.CallerId;
-import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryAction;
-import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
-import net.onrc.onos.ofcontroller.util.FlowEntryActions;
-import net.onrc.onos.ofcontroller.util.FlowEntryId;
-import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
-import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
-import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.FlowPathFlags;
-import net.onrc.onos.ofcontroller.util.IPv4Net;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
+import net.onrc.onos.ofcontroller.topology.Topology;
+import net.onrc.onos.ofcontroller.util.*;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -69,11 +40,12 @@
*/
public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
- protected GraphDBOperation op;
+ protected GraphDBOperation dbHandler;
- protected IRestApiService restApi;
protected volatile IFloodlightProviderService floodlightProvider;
protected volatile ITopologyNetService topologyNetService;
+ protected volatile IDatagridService datagridService;
+ protected IRestApiService restApi;
protected FloodlightModuleContext context;
protected OFMessageDamper messageDamper;
@@ -84,9 +56,6 @@
//
protected static final int OFMESSAGE_DAMPER_CAPACITY = 50000; // TODO: find sweet spot
protected static final int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms
- public static final short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 0; // infinity
- public static final short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
- public static final short PRIORITY_DEFAULT = 100;
// Flow Entry ID generation state
private static Random randomGenerator = new Random();
@@ -94,12 +63,6 @@
private static int nextFlowEntryIdSuffix = 0;
private static long nextFlowEntryId = 0;
- // State for measurement purpose
- private static long measurementFlowId = 100000;
- private static String measurementFlowIdStr = "0x186a0"; // 100000
- private long modifiedMeasurementFlowTime = 0;
- //
-
/** The logger. */
private static Logger log = LoggerFactory.getLogger(FlowManager.class);
@@ -117,7 +80,7 @@
runImpl();
} catch (Exception e) {
log.debug("Exception processing All Flow Entries from the Network MAP: ", e);
- op.rollback();
+ dbHandler.rollback();
return;
}
}
@@ -143,12 +106,12 @@
new LinkedList<IFlowEntry>();
//
- // Fetch all Flow Entries which need to be updated and select only my Flow Entries
- // that need to be updated into the switches.
+ // Fetch all Flow Entries which need to be updated and select
+ // only my Flow Entries that need to be updated into the
+ // switches.
//
- boolean processed_measurement_flow = false;
Iterable<IFlowEntry> allFlowEntries =
- op.getAllSwitchNotUpdatedFlowEntries();
+ dbHandler.getAllSwitchNotUpdatedFlowEntries();
for (IFlowEntry flowEntryObj : allFlowEntries) {
counterAllFlowEntries++;
@@ -161,7 +124,7 @@
continue; // Ignore the entry: not my switch
IFlowPath flowObj =
- op.getFlowPathByFlowEntry(flowEntryObj);
+ dbHandler.getFlowPathByFlowEntry(flowEntryObj);
if (flowObj == null)
continue; // Should NOT happen
if (flowObj.getFlowId() == null)
@@ -183,15 +146,6 @@
addFlowEntries.add(flowEntryObj);
}
counterMyNotUpdatedFlowEntries++;
- // Code for measurement purpose
- // TODO: Commented-out for now
- /*
- {
- if (flowObj.getFlowId().equals(measurementFlowIdStr)) {
- processed_measurement_flow = true;
- }
- }
- */
}
//
@@ -199,7 +153,7 @@
//
for (IFlowEntry flowEntryObj : addFlowEntries) {
IFlowPath flowObj =
- op.getFlowPathByFlowEntry(flowEntryObj);
+ dbHandler.getFlowPathByFlowEntry(flowEntryObj);
if (flowObj == null)
continue; // Should NOT happen
if (flowObj.getFlowId() == null)
@@ -223,24 +177,16 @@
while (! deleteFlowEntries.isEmpty()) {
IFlowEntry flowEntryObj = deleteFlowEntries.poll();
IFlowPath flowObj =
- op.getFlowPathByFlowEntry(flowEntryObj);
+ dbHandler.getFlowPathByFlowEntry(flowEntryObj);
if (flowObj == null) {
log.debug("Did not find FlowPath to be deleted");
continue;
}
flowObj.removeFlowEntry(flowEntryObj);
- op.removeFlowEntry(flowEntryObj);
+ dbHandler.removeFlowEntry(flowEntryObj);
}
- op.commit();
-
- if (processed_measurement_flow) {
- long estimatedTime =
- System.nanoTime() - modifiedMeasurementFlowTime;
- String logMsg = "MEASUREMENT: Pushed Flow delay: " +
- (double)estimatedTime / 1000000000 + " sec";
- log.debug(logMsg);
- }
+ dbHandler.commit();
long estimatedTime = System.nanoTime() - startTime;
double rate = 0.0;
@@ -265,7 +211,7 @@
runImpl();
} catch (Exception e) {
log.debug("Exception processing All Flows from the Network MAP: ", e);
- op.rollback();
+ dbHandler.rollback();
return;
}
}
@@ -287,15 +233,12 @@
}
LinkedList<IFlowPath> deleteFlows = new LinkedList<IFlowPath>();
- boolean processed_measurement_flow = false;
-
//
// Fetch and recompute the Shortest Path for those
// Flow Paths this controller is responsible for.
//
- Map<Long, ?> shortestPathTopo =
- topologyNetService.prepareShortestPathTopo();
- Iterable<IFlowPath> allFlowPaths = op.getAllFlowPaths();
+ Topology topology = topologyNetService.newDatabaseTopology();
+ Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
for (IFlowPath flowPathObj : allFlowPaths) {
counterAllFlowPaths++;
if (flowPathObj == null)
@@ -359,18 +302,19 @@
counterMyFlowPaths++;
//
- // NOTE: Using here the regular getShortestPath() method
- // won't work here, because that method calls internally
- // "conn.endTx(Transaction.COMMIT)", and that will
- // invalidate all handlers to the Titan database.
+ // NOTE: Using here the regular getDatabaseShortestPath()
+ // method won't work here, because that method calls
+ // internally "conn.endTx(Transaction.COMMIT)", and that
+ // will invalidate all handlers to the Titan database.
// If we want to experiment with calling here
- // getShortestPath(), we need to refactor that code
+ // getDatabaseShortestPath(), we need to refactor that code
// to avoid closing the transaction.
//
DataPath dataPath =
- topologyNetService.getTopoShortestPath(shortestPathTopo,
- srcSwitchPort,
- dstSwitchPort);
+ topologyNetService.getTopologyShortestPath(
+ topology,
+ srcSwitchPort,
+ dstSwitchPort);
if (dataPath == null) {
// We need the DataPath to compare the paths
dataPath = new DataPath();
@@ -392,20 +336,12 @@
//
while (! deleteFlows.isEmpty()) {
IFlowPath flowPathObj = deleteFlows.poll();
- op.removeFlowPath(flowPathObj);
+ dbHandler.removeFlowPath(flowPathObj);
}
- topologyNetService.dropShortestPathTopo(shortestPathTopo);
+ topologyNetService.dropTopology(topology);
- op.commit();
-
- if (processed_measurement_flow) {
- long estimatedTime =
- System.nanoTime() - modifiedMeasurementFlowTime;
- String logMsg = "MEASUREMENT: Pushed Flow delay: " +
- (double)estimatedTime / 1000000000 + " sec";
- log.debug(logMsg);
- }
+ dbHandler.commit();
long estimatedTime = System.nanoTime() - startTime;
double rate = 0.0;
@@ -428,8 +364,7 @@
*/
@Override
public void init(String conf) {
- op = new GraphDBOperation(conf);
- topologyNetService = new TopologyManager(conf);
+ dbHandler = new GraphDBOperation(conf);
}
/**
@@ -444,7 +379,7 @@
*/
@Override
public void close() {
- op.close();
+ dbHandler.close();
}
/**
@@ -469,9 +404,9 @@
public Map<Class<? extends IFloodlightService>, IFloodlightService>
getServiceImpls() {
Map<Class<? extends IFloodlightService>,
- IFloodlightService> m =
- new HashMap<Class<? extends IFloodlightService>,
- IFloodlightService>();
+ IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>,
+ IFloodlightService>();
m.put(IFlowService.class, this);
return m;
}
@@ -483,10 +418,12 @@
*/
@Override
public Collection<Class<? extends IFloodlightService>>
- getModuleDependencies() {
+ getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
+ l.add(INetworkGraphService.class);
+ l.add(IDatagridService.class);
l.add(IRestApiService.class);
return l;
}
@@ -501,15 +438,16 @@
throws FloodlightModuleException {
this.context = context;
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+ topologyNetService = context.getServiceImpl(ITopologyNetService.class);
+ datagridService = context.getServiceImpl(IDatagridService.class);
restApi = context.getServiceImpl(IRestApiService.class);
+
messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
EnumSet.of(OFType.FLOW_MOD),
OFMESSAGE_DAMPER_TIMEOUT);
- // TODO: An ugly hack!
- String conf = "/tmp/cassandra.titan";
- this.init(conf);
-
+ this.init("");
+
mapReaderScheduler = Executors.newScheduledThreadPool(1);
shortestPathReconcileScheduler = Executors.newScheduledThreadPool(1);
}
@@ -519,7 +457,7 @@
*
* @return the next Flow Entry ID to use.
*/
- private synchronized long getNextFlowEntryId() {
+ public synchronized long getNextFlowEntryId() {
//
// Generate the next Flow Entry ID.
// NOTE: For now, the higher 32 bits are random, and
@@ -545,10 +483,10 @@
@Override
public void startUp(FloodlightModuleContext context) {
restApi.addRestletRoutable(new FlowWebRoutable());
-
+
// Initialize the Flow Entry ID generator
nextFlowEntryIdPrefix = randomGenerator.nextInt();
-
+
mapReaderScheduler.scheduleAtFixedRate(
mapReader, 3, 3, TimeUnit.SECONDS);
shortestPathReconcileScheduler.scheduleAtFixedRate(
@@ -558,9 +496,6 @@
/**
* 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.
* @param dataPathSummaryStr the data path summary string if the added
@@ -570,147 +505,8 @@
@Override
public boolean addFlow(FlowPath flowPath, FlowId flowId,
String dataPathSummaryStr) {
- /*
- * TODO: Commented-out for now
- if (flowPath.flowId().value() == measurementFlowId) {
- modifiedMeasurementFlowTime = System.nanoTime();
- }
- */
-
- IFlowPath flowObj = null;
- boolean found = false;
- try {
- if ((flowObj = op.searchFlowPath(flowPath.flowId()))
- != null) {
- log.debug("Adding FlowPath with FlowId {}: found existing FlowPath",
- flowPath.flowId().toString());
- found = true;
- } else {
- flowObj = op.newFlowPath();
- log.debug("Adding FlowPath with FlowId {}: creating new FlowPath",
- flowPath.flowId().toString());
- }
- } catch (Exception e) {
- // TODO: handle exceptions
- op.rollback();
-
- StringWriter sw = new StringWriter();
- e.printStackTrace(new PrintWriter(sw));
- String stacktrace = sw.toString();
-
- log.error(":addFlow FlowId:{} failed: {}",
- flowPath.flowId().toString(),
- stacktrace);
- }
- if (flowObj == null) {
- log.error(":addFlow FlowId:{} failed: Flow object not created",
- flowPath.flowId().toString());
- op.rollback();
- return false;
- }
-
- //
- // Set the Flow key:
- // - flowId
- //
- flowObj.setFlowId(flowPath.flowId().toString());
- flowObj.setType("flow");
-
- //
- // Set the Flow attributes:
- // - flowPath.installerId()
- // - flowPath.flowPathFlags()
- // - flowPath.dataPath().srcPort()
- // - flowPath.dataPath().dstPort()
- // - flowPath.matchSrcMac()
- // - flowPath.matchDstMac()
- // - flowPath.matchEthernetFrameType()
- // - flowPath.matchVlanId()
- // - flowPath.matchVlanPriority()
- // - flowPath.matchSrcIPv4Net()
- // - flowPath.matchDstIPv4Net()
- // - flowPath.matchIpProto()
- // - flowPath.matchIpToS()
- // - flowPath.matchSrcTcpUdpPort()
- // - flowPath.matchDstTcpUdpPort()
- // - flowPath.flowEntryActions()
- //
- flowObj.setInstallerId(flowPath.installerId().toString());
- flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
- flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
- flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
- flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
- flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
- if (flowPath.flowEntryMatch().matchSrcMac()) {
- flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
- }
- if (flowPath.flowEntryMatch().matchDstMac()) {
- flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
- }
- if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
- flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
- }
- if (flowPath.flowEntryMatch().matchVlanId()) {
- flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
- }
- if (flowPath.flowEntryMatch().matchVlanPriority()) {
- flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
- }
- if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
- flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
- }
- if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
- flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
- }
- if (flowPath.flowEntryMatch().matchIpProto()) {
- flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
- }
- if (flowPath.flowEntryMatch().matchIpToS()) {
- flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
- }
- if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
- flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
- }
- if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
- flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
- }
- if (! flowPath.flowEntryActions().actions().isEmpty()) {
- flowObj.setActions(flowPath.flowEntryActions().toString());
- }
-
- if (dataPathSummaryStr != null) {
- flowObj.setDataPathSummary(dataPathSummaryStr);
- } else {
- flowObj.setDataPathSummary("");
- }
-
- if (found)
- flowObj.setUserState("FE_USER_MODIFY");
- else
- flowObj.setUserState("FE_USER_ADD");
-
- // Flow edges:
- // HeadFE
-
-
- //
- // Flow Entries:
- // flowPath.dataPath().flowEntries()
- //
- for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
- if (addFlowEntry(flowObj, flowEntry) == null) {
- op.rollback();
- return false;
- }
- }
- op.commit();
-
- //
- // TODO: We need a proper Flow ID allocation mechanism.
- //
- flowId.setValue(flowPath.flowId().value());
-
- return true;
+ return FlowDatabaseOperation.addFlow(this, dbHandler, flowPath, flowId,
+ dataPathSummaryStr);
}
/**
@@ -721,150 +517,8 @@
* @return the added Flow Entry object on success, otherwise null.
*/
private IFlowEntry addFlowEntry(IFlowPath flowObj, FlowEntry flowEntry) {
- // Flow edges
- // HeadFE (TODO)
-
- //
- // Assign the FlowEntry ID.
- //
- if ((flowEntry.flowEntryId() == null) ||
- (flowEntry.flowEntryId().value() == 0)) {
- long id = getNextFlowEntryId();
- flowEntry.setFlowEntryId(new FlowEntryId(id));
- }
-
- IFlowEntry flowEntryObj = null;
- boolean found = false;
- try {
- if ((flowEntryObj =
- op.searchFlowEntry(flowEntry.flowEntryId())) != null) {
- log.debug("Adding FlowEntry with FlowEntryId {}: found existing FlowEntry",
- flowEntry.flowEntryId().toString());
- found = true;
- } else {
- flowEntryObj = op.newFlowEntry();
- log.debug("Adding FlowEntry with FlowEntryId {}: creating new FlowEntry",
- flowEntry.flowEntryId().toString());
- }
- } catch (Exception e) {
- log.error(":addFlow FlowEntryId:{} failed",
- flowEntry.flowEntryId().toString());
- return null;
- }
- if (flowEntryObj == null) {
- log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
- flowEntry.flowEntryId().toString());
- return null;
- }
-
- //
- // Set the Flow Entry key:
- // - flowEntry.flowEntryId()
- //
- flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
- flowEntryObj.setType("flow_entry");
-
- //
- // Set the Flow Entry Edges and attributes:
- // - Switch edge
- // - InPort edge
- // - OutPort edge
- //
- // - flowEntry.dpid()
- // - flowEntry.flowEntryUserState()
- // - flowEntry.flowEntrySwitchState()
- // - flowEntry.flowEntryErrorState()
- // - flowEntry.matchInPort()
- // - flowEntry.matchSrcMac()
- // - flowEntry.matchDstMac()
- // - flowEntry.matchEthernetFrameType()
- // - flowEntry.matchVlanId()
- // - flowEntry.matchVlanPriority()
- // - flowEntry.matchSrcIPv4Net()
- // - flowEntry.matchDstIPv4Net()
- // - flowEntry.matchIpProto()
- // - flowEntry.matchIpToS()
- // - flowEntry.matchSrcTcpUdpPort()
- // - flowEntry.matchDstTcpUdpPort()
- // - flowEntry.actionOutputPort()
- // - flowEntry.actions()
- //
- ISwitchObject sw = op.searchSwitch(flowEntry.dpid().toString());
- flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
- flowEntryObj.setSwitch(sw);
- if (flowEntry.flowEntryMatch().matchInPort()) {
- IPortObject inport =
- op.searchPort(flowEntry.dpid().toString(),
- flowEntry.flowEntryMatch().inPort().value());
- flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
- flowEntryObj.setInPort(inport);
- }
- if (flowEntry.flowEntryMatch().matchSrcMac()) {
- flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
- }
- if (flowEntry.flowEntryMatch().matchDstMac()) {
- flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
- }
- if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
- flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
- }
- if (flowEntry.flowEntryMatch().matchVlanId()) {
- flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
- }
- if (flowEntry.flowEntryMatch().matchVlanPriority()) {
- flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
- }
- if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
- flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
- }
- if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
- flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
- }
- if (flowEntry.flowEntryMatch().matchIpProto()) {
- flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
- }
- if (flowEntry.flowEntryMatch().matchIpToS()) {
- flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
- }
- if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
- flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
- }
- if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
- flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
- }
-
- for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
- if (fa.actionOutput() != null) {
- IPortObject outport =
- op.searchPort(flowEntry.dpid().toString(),
- fa.actionOutput().port().value());
- flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
- flowEntryObj.setOutPort(outport);
- }
- }
- if (! flowEntry.flowEntryActions().isEmpty()) {
- flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
- }
-
- // TODO: Hacks with hard-coded state names!
- if (found)
- flowEntryObj.setUserState("FE_USER_MODIFY");
- else
- flowEntryObj.setUserState("FE_USER_ADD");
- flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
- //
- // TODO: Take care of the FlowEntryErrorState.
- //
-
- // Flow Entries edges:
- // Flow
- // NextFE (TODO)
- if (! found) {
- flowObj.addFlowEntry(flowEntryObj);
- flowEntryObj.setFlow(flowObj);
- }
-
- return flowEntryObj;
+ return FlowDatabaseOperation.addFlowEntry(this, dbHandler, flowObj,
+ flowEntry);
}
/**
@@ -874,64 +528,7 @@
*/
@Override
public boolean deleteAllFlows() {
- final ConcurrentLinkedQueue<FlowId> concurrentAllFlowIds =
- new ConcurrentLinkedQueue<FlowId>();
-
- // Get all Flow IDs
- Iterable<IFlowPath> allFlowPaths = op.getAllFlowPaths();
- for (IFlowPath flowPathObj : allFlowPaths) {
- if (flowPathObj == null)
- continue;
- String flowIdStr = flowPathObj.getFlowId();
- if (flowIdStr == null)
- continue;
- FlowId flowId = new FlowId(flowIdStr);
- concurrentAllFlowIds.add(flowId);
- }
-
- // Delete all flows one-by-one
- for (FlowId flowId : concurrentAllFlowIds)
- deleteFlow(flowId);
-
- /*
- * TODO: A faster mechanism to delete the Flow Paths by using
- * a number of threads. Commented-out for now.
- */
- /*
- //
- // Create the threads to delete the Flow Paths
- //
- List<Thread> threads = new LinkedList<Thread>();
- for (int i = 0; i < 10; i++) {
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- FlowId flowId = concurrentAllFlowIds.poll();
- if (flowId == null)
- return;
- deleteFlow(flowId);
- }
- }}, "Delete All Flow Paths");
- threads.add(thread);
- }
-
- // Start processing
- for (Thread thread : threads) {
- thread.start();
- }
-
- // Wait for all threads to complete
- for (Thread thread : threads) {
- try {
- thread.join();
- } catch (InterruptedException e) {
- log.debug("Exception waiting for a thread to delete a Flow Path: ", e);
- }
- }
- */
-
- return true;
+ return FlowDatabaseOperation.deleteAllFlows(dbHandler);
}
/**
@@ -942,58 +539,7 @@
*/
@Override
public boolean deleteFlow(FlowId flowId) {
- /*
- * TODO: Commented-out for now
- if (flowId.value() == measurementFlowId) {
- modifiedMeasurementFlowTime = System.nanoTime();
- }
- */
-
- IFlowPath flowObj = null;
- //
- // We just mark the entries for deletion,
- // and let the switches remove each individual entry after
- // it has been removed from the switches.
- //
- try {
- if ((flowObj = op.searchFlowPath(flowId))
- != null) {
- log.debug("Deleting FlowPath with FlowId {}: found existing FlowPath",
- flowId.toString());
- } else {
- log.debug("Deleting FlowPath with FlowId {}: FlowPath not found",
- flowId.toString());
- }
- } catch (Exception e) {
- // TODO: handle exceptions
- op.rollback();
- log.error(":deleteFlow FlowId:{} failed", flowId.toString());
- }
- if (flowObj == null) {
- op.commit();
- return true; // OK: No such flow
- }
-
- //
- // Find and mark for deletion all Flow Entries,
- // and the Flow itself.
- //
- flowObj.setUserState("FE_USER_DELETE");
- Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
- boolean empty = true; // TODO: an ugly hack
- for (IFlowEntry flowEntryObj : flowEntries) {
- empty = false;
- // flowObj.removeFlowEntry(flowEntryObj);
- // conn.utils().removeFlowEntry(conn, flowEntryObj);
- flowEntryObj.setUserState("FE_USER_DELETE");
- flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
- }
- // Remove from the database empty flows
- if (empty)
- op.removeFlowPath(flowObj);
- op.commit();
-
- return true;
+ return FlowDatabaseOperation.deleteFlow(dbHandler, flowId);
}
/**
@@ -1003,26 +549,7 @@
*/
@Override
public boolean clearAllFlows() {
- List<FlowId> allFlowIds = new LinkedList<FlowId>();
-
- // Get all Flow IDs
- Iterable<IFlowPath> allFlowPaths = op.getAllFlowPaths();
- for (IFlowPath flowPathObj : allFlowPaths) {
- if (flowPathObj == null)
- continue;
- String flowIdStr = flowPathObj.getFlowId();
- if (flowIdStr == null)
- continue;
- FlowId flowId = new FlowId(flowIdStr);
- allFlowIds.add(flowId);
- }
-
- // Clear all flows one-by-one
- for (FlowId flowId : allFlowIds) {
- clearFlow(flowId);
- }
-
- return true;
+ return FlowDatabaseOperation.clearAllFlows(dbHandler);
}
/**
@@ -1033,39 +560,7 @@
*/
@Override
public boolean clearFlow(FlowId flowId) {
- IFlowPath flowObj = null;
- try {
- if ((flowObj = op.searchFlowPath(flowId))
- != null) {
- log.debug("Clearing FlowPath with FlowId {}: found existing FlowPath",
- flowId.toString());
- } else {
- log.debug("Clearing FlowPath with FlowId {}: FlowPath not found",
- flowId.toString());
- }
- } catch (Exception e) {
- // TODO: handle exceptions
- op.rollback();
- log.error(":clearFlow FlowId:{} failed", flowId.toString());
- }
- if (flowObj == null) {
- op.commit();
- return true; // OK: No such flow
- }
-
- //
- // Remove all Flow Entries
- //
- Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
- for (IFlowEntry flowEntryObj : flowEntries) {
- flowObj.removeFlowEntry(flowEntryObj);
- op.removeFlowEntry(flowEntryObj);
- }
- // Remove the Flow itself
- op.removeFlowPath(flowObj);
- op.commit();
-
- return true;
+ return FlowDatabaseOperation.clearFlow(dbHandler, flowId);
}
/**
@@ -1076,33 +571,17 @@
*/
@Override
public FlowPath getFlow(FlowId flowId) {
- IFlowPath flowObj = null;
- try {
- if ((flowObj = op.searchFlowPath(flowId))
- != null) {
- log.debug("Get FlowPath with FlowId {}: found existing FlowPath",
- flowId.toString());
- } else {
- log.debug("Get FlowPath with FlowId {}: FlowPath not found",
- flowId.toString());
- }
- } catch (Exception e) {
- // TODO: handle exceptions
- op.rollback();
- log.error(":getFlow FlowId:{} failed", flowId.toString());
- }
- if (flowObj == null) {
- op.commit();
- return null; // Flow not found
- }
+ return FlowDatabaseOperation.getFlow(dbHandler, flowId);
+ }
- //
- // Extract the Flow state
- //
- FlowPath flowPath = extractFlowPath(flowObj);
- op.commit();
-
- return flowPath;
+ /**
+ * Get all installed flows by all installers.
+ *
+ * @return the Flow Paths if found, otherwise null.
+ */
+ @Override
+ public ArrayList<FlowPath> getAllFlows() {
+ return FlowDatabaseOperation.getAllFlows(dbHandler);
}
/**
@@ -1116,45 +595,8 @@
@Override
public ArrayList<FlowPath> getAllFlows(CallerId installerId,
DataPathEndpoints dataPathEndpoints) {
- //
- // TODO: The implementation below is not optimal:
- // We fetch all flows, and then return only the subset that match
- // the query conditions.
- // We should use the appropriate Titan/Gremlin query to filter-out
- // the flows as appropriate.
- //
- ArrayList<FlowPath> allFlows = getAllFlows();
- ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
- if (allFlows == null) {
- log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: no FlowPaths found", installerId, dataPathEndpoints);
- return flowPaths;
- }
-
- for (FlowPath flow : allFlows) {
- //
- // TODO: String-based comparison is sub-optimal.
- // We are using it for now to save us the extra work of
- // implementing the "equals()" and "hashCode()" methods.
- //
- if (! flow.installerId().toString().equals(installerId.toString()))
- continue;
- if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
- continue;
- }
- if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
- continue;
- }
- flowPaths.add(flow);
- }
-
- if (flowPaths.isEmpty()) {
- log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: no FlowPaths found", installerId, dataPathEndpoints);
- } else {
- log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: FlowPaths are found", installerId, dataPathEndpoints);
- }
-
- return flowPaths;
+ return FlowDatabaseOperation.getAllFlows(dbHandler, installerId,
+ dataPathEndpoints);
}
/**
@@ -1165,43 +607,7 @@
*/
@Override
public ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints) {
- //
- // TODO: The implementation below is not optimal:
- // We fetch all flows, and then return only the subset that match
- // the query conditions.
- // We should use the appropriate Titan/Gremlin query to filter-out
- // the flows as appropriate.
- //
- ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
- ArrayList<FlowPath> allFlows = getAllFlows();
-
- if (allFlows == null) {
- log.debug("Get FlowPaths for dataPathEndpoints{}: no FlowPaths found", dataPathEndpoints);
- return flowPaths;
- }
-
- for (FlowPath flow : allFlows) {
- //
- // TODO: String-based comparison is sub-optimal.
- // We are using it for now to save us the extra work of
- // implementing the "equals()" and "hashCode()" methods.
- //
- if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
- continue;
- }
- if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
- continue;
- }
- flowPaths.add(flow);
- }
-
- if (flowPaths.isEmpty()) {
- log.debug("Get FlowPaths for dataPathEndpoints{}: no FlowPaths found", dataPathEndpoints);
- } else {
- log.debug("Get FlowPaths for dataPathEndpoints{}: FlowPaths are found", dataPathEndpoints);
- }
-
- return flowPaths;
+ return FlowDatabaseOperation.getAllFlows(dbHandler, dataPathEndpoints);
}
/**
@@ -1212,344 +618,19 @@
* @return the Flow Paths if found, otherwise null.
*/
@Override
- public ArrayList<IFlowPath> getAllFlowsSummary(FlowId flowId, int maxFlows) {
-
- //
- // TODO: The implementation below is not optimal:
- // We fetch all flows, and then return only the subset that match
- // the query conditions.
- // We should use the appropriate Titan/Gremlin query to filter-out
- // the flows as appropriate.
- //
- //ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
- ArrayList<IFlowPath> flowPathsWithoutFlowEntries = getAllFlowsWithoutFlowEntries();
-
- Collections.sort(flowPathsWithoutFlowEntries,
- new Comparator<IFlowPath>(){
- @Override
- public int compare(IFlowPath first, IFlowPath second) {
- // TODO Auto-generated method stub
- long result = new FlowId(first.getFlowId()).value()
- - new FlowId(second.getFlowId()).value();
- if (result > 0) return 1;
- else if (result < 0) return -1;
- else return 0;
- }
- }
- );
-
- return flowPathsWithoutFlowEntries;
-
- /*
- ArrayList<FlowPath> allFlows = getAllFlows();
-
- if (allFlows == null) {
- log.debug("Get FlowPathsSummary for {} {}: no FlowPaths found", flowId, maxFlows);
- return flowPaths;
- }
-
- Collections.sort(allFlows);
-
- for (FlowPath flow : allFlows) {
- flow.setFlowEntryMatch(null);
-
- // start from desired flowId
- if (flow.flowId().value() < flowId.value()) {
- continue;
- }
-
- // Summarize by making null flow entry fields that are not relevant to report
- for (FlowEntry flowEntry : flow.dataPath().flowEntries()) {
- flowEntry.setFlowEntryActions(null);
- flowEntry.setFlowEntryMatch(null);
- }
-
- flowPaths.add(flow);
- if (maxFlows != 0 && flowPaths.size() >= maxFlows) {
- break;
- }
- }
-
- if (flowPaths.isEmpty()) {
- log.debug("Get FlowPathsSummary {} {}: no FlowPaths found", flowId, maxFlows);
- } else {
- log.debug("Get FlowPathsSummary for {} {}: FlowPaths were found", flowId, maxFlows);
- }
-
- return flowPaths;
- */
+ public ArrayList<IFlowPath> getAllFlowsSummary(FlowId flowId,
+ int maxFlows) {
+ return FlowDatabaseOperation.getAllFlowsSummary(dbHandler, flowId,
+ maxFlows);
}
/**
- * Get all installed flows by all installers.
- *
- * @return the Flow Paths if found, otherwise null.
- */
- @Override
- public ArrayList<FlowPath> getAllFlows() {
- Iterable<IFlowPath> flowPathsObj = null;
- ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
- try {
- if ((flowPathsObj = op.getAllFlowPaths()) != null) {
- log.debug("Get all FlowPaths: found FlowPaths");
- } else {
- log.debug("Get all FlowPaths: no FlowPaths found");
- }
- } catch (Exception e) {
- // TODO: handle exceptions
- op.rollback();
- log.error(":getAllFlowPaths failed");
- }
- if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
- op.commit();
- return flowPaths; // No Flows found
- }
-
- for (IFlowPath flowObj : flowPathsObj) {
- //
- // Extract the Flow state
- //
- FlowPath flowPath = extractFlowPath(flowObj);
- if (flowPath != null)
- flowPaths.add(flowPath);
- }
-
- op.commit();
-
- return flowPaths;
- }
-
- /**
* Get all Flows information, without the associated Flow Entries.
*
* @return all Flows information, without the associated Flow Entries.
*/
public ArrayList<IFlowPath> getAllFlowsWithoutFlowEntries() {
- Iterable<IFlowPath> flowPathsObj = null;
- ArrayList<IFlowPath> flowPathsObjArray = new ArrayList<IFlowPath>();
-
- op.commit();
-
- try {
- if ((flowPathsObj = op.getAllFlowPaths()) != null) {
- log.debug("Get all FlowPaths: found FlowPaths");
- } else {
- log.debug("Get all FlowPaths: no FlowPaths found");
- }
- } catch (Exception e) {
- // TODO: handle exceptions
- op.rollback();
- log.error(":getAllFlowPaths failed");
- }
- if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
- return new ArrayList<IFlowPath>(); // No Flows found
- }
-
- for (IFlowPath flowObj : flowPathsObj){
- flowPathsObjArray.add(flowObj);
- }
- /*
- ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
- for (IFlowPath flowObj : flowPathsObj) {
- //
- // Extract the Flow state
- //
- FlowPath flowPath = extractFlowPath(flowObj);
- if (flowPath != null)
- flowPaths.add(flowPath);
- }
- */
-
- //conn.endTx(Transaction.COMMIT);
-
- return flowPathsObjArray;
- }
-
- /**
- * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
- *
- * @param flowObj the object to extract the Flow Path State from.
- * @return the extracted Flow Path State.
- */
- private FlowPath extractFlowPath(IFlowPath flowObj) {
- //
- // Extract the Flow state
- //
- String flowIdStr = flowObj.getFlowId();
- String installerIdStr = flowObj.getInstallerId();
- Long flowPathFlags = flowObj.getFlowPathFlags();
- String srcSwitchStr = flowObj.getSrcSwitch();
- Short srcPortShort = flowObj.getSrcPort();
- String dstSwitchStr = flowObj.getDstSwitch();
- Short dstPortShort = flowObj.getDstPort();
-
- if ((flowIdStr == null) ||
- (installerIdStr == null) ||
- (flowPathFlags == null) ||
- (srcSwitchStr == null) ||
- (srcPortShort == null) ||
- (dstSwitchStr == null) ||
- (dstPortShort == null)) {
- // TODO: A work-around, becauuse of some bogus database objects
- return null;
- }
-
- FlowPath flowPath = new FlowPath();
- flowPath.setFlowId(new FlowId(flowIdStr));
- flowPath.setInstallerId(new CallerId(installerIdStr));
- flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
- flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
- flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
- flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
- flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
- //
- // Extract the match conditions common for all Flow Entries
- //
- {
- FlowEntryMatch match = new FlowEntryMatch();
- String matchSrcMac = flowObj.getMatchSrcMac();
- if (matchSrcMac != null)
- match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
- String matchDstMac = flowObj.getMatchDstMac();
- if (matchDstMac != null)
- match.enableDstMac(MACAddress.valueOf(matchDstMac));
- Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
- if (matchEthernetFrameType != null)
- match.enableEthernetFrameType(matchEthernetFrameType);
- Short matchVlanId = flowObj.getMatchVlanId();
- if (matchVlanId != null)
- match.enableVlanId(matchVlanId);
- Byte matchVlanPriority = flowObj.getMatchVlanPriority();
- if (matchVlanPriority != null)
- match.enableVlanPriority(matchVlanPriority);
- String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
- if (matchSrcIPv4Net != null)
- match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
- String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
- if (matchDstIPv4Net != null)
- match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
- Byte matchIpProto = flowObj.getMatchIpProto();
- if (matchIpProto != null)
- match.enableIpProto(matchIpProto);
- Byte matchIpToS = flowObj.getMatchIpToS();
- if (matchIpToS != null)
- match.enableIpToS(matchIpToS);
- Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
- if (matchSrcTcpUdpPort != null)
- match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
- Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
- if (matchDstTcpUdpPort != null)
- match.enableDstTcpUdpPort(matchDstTcpUdpPort);
-
- flowPath.setFlowEntryMatch(match);
- }
- //
- // Extract the actions for the first Flow Entry
- //
- {
- String actionsStr = flowObj.getActions();
- if (actionsStr != null) {
- FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
- flowPath.setFlowEntryActions(flowEntryActions);
- }
- }
-
- //
- // Extract all Flow Entries
- //
- Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
- for (IFlowEntry flowEntryObj : flowEntries) {
- FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
- if (flowEntry == null)
- continue;
- flowPath.dataPath().flowEntries().add(flowEntry);
- }
-
- return flowPath;
- }
-
- /**
- * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
- *
- * @param flowEntryObj the object to extract the Flow Entry State from.
- * @return the extracted Flow Entry State.
- */
- private FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
- String flowEntryIdStr = flowEntryObj.getFlowEntryId();
- String switchDpidStr = flowEntryObj.getSwitchDpid();
- String userState = flowEntryObj.getUserState();
- String switchState = flowEntryObj.getSwitchState();
-
- if ((flowEntryIdStr == null) ||
- (switchDpidStr == null) ||
- (userState == null) ||
- (switchState == null)) {
- // TODO: A work-around, becauuse of some bogus database objects
- return null;
- }
-
- FlowEntry flowEntry = new FlowEntry();
- flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
- flowEntry.setDpid(new Dpid(switchDpidStr));
-
- //
- // Extract the match conditions
- //
- FlowEntryMatch match = new FlowEntryMatch();
- Short matchInPort = flowEntryObj.getMatchInPort();
- if (matchInPort != null)
- match.enableInPort(new Port(matchInPort));
- String matchSrcMac = flowEntryObj.getMatchSrcMac();
- if (matchSrcMac != null)
- match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
- String matchDstMac = flowEntryObj.getMatchDstMac();
- if (matchDstMac != null)
- match.enableDstMac(MACAddress.valueOf(matchDstMac));
- Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
- if (matchEthernetFrameType != null)
- match.enableEthernetFrameType(matchEthernetFrameType);
- Short matchVlanId = flowEntryObj.getMatchVlanId();
- if (matchVlanId != null)
- match.enableVlanId(matchVlanId);
- Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
- if (matchVlanPriority != null)
- match.enableVlanPriority(matchVlanPriority);
- String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
- if (matchSrcIPv4Net != null)
- match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
- String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
- if (matchDstIPv4Net != null)
- match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
- Byte matchIpProto = flowEntryObj.getMatchIpProto();
- if (matchIpProto != null)
- match.enableIpProto(matchIpProto);
- Byte matchIpToS = flowEntryObj.getMatchIpToS();
- if (matchIpToS != null)
- match.enableIpToS(matchIpToS);
- Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
- if (matchSrcTcpUdpPort != null)
- match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
- Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
- if (matchDstTcpUdpPort != null)
- match.enableDstTcpUdpPort(matchDstTcpUdpPort);
- flowEntry.setFlowEntryMatch(match);
-
- //
- // Extract the actions
- //
- FlowEntryActions actions = new FlowEntryActions();
- String actionsStr = flowEntryObj.getActions();
- if (actionsStr != null)
- actions = new FlowEntryActions(actionsStr);
- flowEntry.setFlowEntryActions(actions);
- flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
- flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
- //
- // TODO: Take care of FlowEntryErrorState.
- //
- return flowEntry;
+ return FlowDatabaseOperation.getAllFlowsWithoutFlowEntries(dbHandler);
}
/**
@@ -1680,311 +761,9 @@
*/
public boolean installFlowEntry(IOFSwitch mySwitch, IFlowPath flowObj,
IFlowEntry flowEntryObj) {
- String flowEntryIdStr = flowEntryObj.getFlowEntryId();
- if (flowEntryIdStr == null)
- return false;
- FlowEntryId flowEntryId = new FlowEntryId(flowEntryIdStr);
- String userState = flowEntryObj.getUserState();
- if (userState == null)
- return false;
-
- //
- // Create the Open Flow Flow Modification Entry to push
- //
- OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory()
- .getMessage(OFType.FLOW_MOD);
- long cookie = flowEntryId.value();
-
- short flowModCommand = OFFlowMod.OFPFC_ADD;
- if (userState.equals("FE_USER_ADD")) {
- flowModCommand = OFFlowMod.OFPFC_ADD;
- } else if (userState.equals("FE_USER_MODIFY")) {
- flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
- } else if (userState.equals("FE_USER_DELETE")) {
- flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
- } else {
- // Unknown user state. Ignore the entry
- log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
- flowEntryId.toString(), userState);
- return false;
- }
-
- //
- // Fetch the match conditions.
- //
- // NOTE: The Flow matching conditions common for all Flow Entries are
- // used ONLY if a Flow Entry does NOT have the corresponding matching
- // condition set.
- //
- OFMatch match = new OFMatch();
- match.setWildcards(OFMatch.OFPFW_ALL);
-
- // Match the Incoming Port
- Short matchInPort = flowEntryObj.getMatchInPort();
- if (matchInPort != null) {
- match.setInputPort(matchInPort);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
- }
-
- // Match the Source MAC address
- String matchSrcMac = flowEntryObj.getMatchSrcMac();
- if (matchSrcMac == null)
- matchSrcMac = flowObj.getMatchSrcMac();
- if (matchSrcMac != null) {
- match.setDataLayerSource(matchSrcMac);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
- }
-
- // Match the Destination MAC address
- String matchDstMac = flowEntryObj.getMatchDstMac();
- if (matchDstMac == null)
- matchDstMac = flowObj.getMatchDstMac();
- if (matchDstMac != null) {
- match.setDataLayerDestination(matchDstMac);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
- }
-
- // Match the Ethernet Frame Type
- Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
- if (matchEthernetFrameType == null)
- matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
- if (matchEthernetFrameType != null) {
- match.setDataLayerType(matchEthernetFrameType);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
- }
-
- // Match the VLAN ID
- Short matchVlanId = flowEntryObj.getMatchVlanId();
- if (matchVlanId == null)
- matchVlanId = flowObj.getMatchVlanId();
- if (matchVlanId != null) {
- match.setDataLayerVirtualLan(matchVlanId);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
- }
-
- // Match the VLAN priority
- Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
- if (matchVlanPriority == null)
- matchVlanPriority = flowObj.getMatchVlanPriority();
- if (matchVlanPriority != null) {
- match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
- }
-
- // Match the Source IPv4 Network prefix
- String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
- if (matchSrcIPv4Net == null)
- matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
- if (matchSrcIPv4Net != null) {
- match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
- }
-
- // Natch the Destination IPv4 Network prefix
- String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
- if (matchDstIPv4Net == null)
- matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
- if (matchDstIPv4Net != null) {
- match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
- }
-
- // Match the IP protocol
- Byte matchIpProto = flowEntryObj.getMatchIpProto();
- if (matchIpProto == null)
- matchIpProto = flowObj.getMatchIpProto();
- if (matchIpProto != null) {
- match.setNetworkProtocol(matchIpProto);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
- }
-
- // Match the IP ToS (DSCP field, 6 bits)
- Byte matchIpToS = flowEntryObj.getMatchIpToS();
- if (matchIpToS == null)
- matchIpToS = flowObj.getMatchIpToS();
- if (matchIpToS != null) {
- match.setNetworkTypeOfService(matchIpToS);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
- }
-
- // Match the Source TCP/UDP port
- Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
- if (matchSrcTcpUdpPort == null)
- matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
- if (matchSrcTcpUdpPort != null) {
- match.setTransportSource(matchSrcTcpUdpPort);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
- }
-
- // Match the Destination TCP/UDP port
- Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
- if (matchDstTcpUdpPort == null)
- matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
- if (matchDstTcpUdpPort != null) {
- match.setTransportDestination(matchDstTcpUdpPort);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
- }
-
- //
- // Fetch the actions
- //
- Short actionOutputPort = null;
- List<OFAction> openFlowActions = new ArrayList<OFAction>();
- int actionsLen = 0;
- FlowEntryActions flowEntryActions = null;
- String actionsStr = flowEntryObj.getActions();
- if (actionsStr != null)
- flowEntryActions = new FlowEntryActions(actionsStr);
- for (FlowEntryAction action : flowEntryActions.actions()) {
- ActionOutput actionOutput = action.actionOutput();
- ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
- ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
- ActionStripVlan actionStripVlan = action.actionStripVlan();
- ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
- ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
- ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
- ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
- ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
- ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
- ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
- ActionEnqueue actionEnqueue = action.actionEnqueue();
-
- if (actionOutput != null) {
- actionOutputPort = actionOutput.port().value();
- // XXX: The max length is hard-coded for now
- OFActionOutput ofa =
- new OFActionOutput(actionOutput.port().value(),
- (short)0xffff);
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetVlanId != null) {
- OFActionVirtualLanIdentifier ofa =
- new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetVlanPriority != null) {
- OFActionVirtualLanPriorityCodePoint ofa =
- new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionStripVlan != null) {
- if (actionStripVlan.stripVlan() == true) {
- OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
- }
-
- if (actionSetEthernetSrcAddr != null) {
- OFActionDataLayerSource ofa =
- new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetEthernetDstAddr != null) {
- OFActionDataLayerDestination ofa =
- new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetIPv4SrcAddr != null) {
- OFActionNetworkLayerSource ofa =
- new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetIPv4DstAddr != null) {
- OFActionNetworkLayerDestination ofa =
- new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetIpToS != null) {
- OFActionNetworkTypeOfService ofa =
- new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetTcpUdpSrcPort != null) {
- OFActionTransportLayerSource ofa =
- new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetTcpUdpDstPort != null) {
- OFActionTransportLayerDestination ofa =
- new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionEnqueue != null) {
- OFActionEnqueue ofa =
- new OFActionEnqueue(actionEnqueue.port().value(),
- actionEnqueue.queueId());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
- }
-
- fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
- .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
- .setPriority(PRIORITY_DEFAULT)
- .setBufferId(OFPacketOut.BUFFER_ID_NONE)
- .setCookie(cookie)
- .setCommand(flowModCommand)
- .setMatch(match)
- .setActions(openFlowActions)
- .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
- fm.setOutPort(OFPort.OFPP_NONE.getValue());
- if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
- (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
- if (actionOutputPort != null)
- fm.setOutPort(actionOutputPort);
- }
-
- //
- // TODO: Set the following flag
- // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
- // See method ForwardingBase::pushRoute()
- //
-
- //
- // Write the message to the switch
- //
- log.debug("MEASUREMENT: Installing flow entry " + userState +
- " into switch DPID: " +
- mySwitch.getStringId() +
- " flowEntryId: " + flowEntryId.toString() +
- " srcMac: " + matchSrcMac + " dstMac: " + matchDstMac +
- " inPort: " + matchInPort + " outPort: " + actionOutputPort
- );
- try {
- messageDamper.write(mySwitch, fm, null);
- mySwitch.flush();
- //
- // TODO: We should use the OpenFlow Barrier mechanism
- // to check for errors, and update the SwitchState
- // for a flow entry after the Barrier message is
- // is received.
- //
- flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
- } catch (IOException e) {
- log.error("Failure writing flow mod from network map", e);
- return false;
- }
-
- return true;
+ return FlowSwitchOperation.installFlowEntry(
+ floodlightProvider.getOFMessageFactory(),
+ messageDamper, mySwitch, flowObj, flowEntryObj);
}
/**
@@ -1997,309 +776,9 @@
*/
public boolean installFlowEntry(IOFSwitch mySwitch, FlowPath flowPath,
FlowEntry flowEntry) {
- //
- // Create the OpenFlow Flow Modification Entry to push
- //
- OFFlowMod fm = (OFFlowMod) floodlightProvider.getOFMessageFactory()
- .getMessage(OFType.FLOW_MOD);
- long cookie = flowEntry.flowEntryId().value();
-
- short flowModCommand = OFFlowMod.OFPFC_ADD;
- if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_ADD) {
- flowModCommand = OFFlowMod.OFPFC_ADD;
- } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_MODIFY) {
- flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
- } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE) {
- flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
- } else {
- // Unknown user state. Ignore the entry
- log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
- flowEntry.flowEntryId().toString(),
- flowEntry.flowEntryUserState());
- return false;
- }
-
- //
- // Fetch the match conditions.
- //
- // NOTE: The Flow matching conditions common for all Flow Entries are
- // used ONLY if a Flow Entry does NOT have the corresponding matching
- // condition set.
- //
- OFMatch match = new OFMatch();
- match.setWildcards(OFMatch.OFPFW_ALL);
- FlowEntryMatch flowPathMatch = flowPath.flowEntryMatch();
- FlowEntryMatch flowEntryMatch = flowEntry.flowEntryMatch();
-
- // Match the Incoming Port
- Port matchInPort = flowEntryMatch.inPort();
- if (matchInPort != null) {
- match.setInputPort(matchInPort.value());
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
- }
-
- // Match the Source MAC address
- MACAddress matchSrcMac = flowEntryMatch.srcMac();
- if ((matchSrcMac == null) && (flowPathMatch != null)) {
- matchSrcMac = flowPathMatch.srcMac();
- }
- if (matchSrcMac != null) {
- match.setDataLayerSource(matchSrcMac.toString());
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
- }
-
- // Match the Destination MAC address
- MACAddress matchDstMac = flowEntryMatch.dstMac();
- if ((matchDstMac == null) && (flowPathMatch != null)) {
- matchDstMac = flowPathMatch.dstMac();
- }
- if (matchDstMac != null) {
- match.setDataLayerDestination(matchDstMac.toString());
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
- }
-
- // Match the Ethernet Frame Type
- Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
- if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
- matchEthernetFrameType = flowPathMatch.ethernetFrameType();
- }
- if (matchEthernetFrameType != null) {
- match.setDataLayerType(matchEthernetFrameType);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
- }
-
- // Match the VLAN ID
- Short matchVlanId = flowEntryMatch.vlanId();
- if ((matchVlanId == null) && (flowPathMatch != null)) {
- matchVlanId = flowPathMatch.vlanId();
- }
- if (matchVlanId != null) {
- match.setDataLayerVirtualLan(matchVlanId);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
- }
-
- // Match the VLAN priority
- Byte matchVlanPriority = flowEntryMatch.vlanPriority();
- if ((matchVlanPriority == null) && (flowPathMatch != null)) {
- matchVlanPriority = flowPathMatch.vlanPriority();
- }
- if (matchVlanPriority != null) {
- match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
- }
-
- // Match the Source IPv4 Network prefix
- IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
- if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
- matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
- }
- if (matchSrcIPv4Net != null) {
- match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
- }
-
- // Natch the Destination IPv4 Network prefix
- IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
- if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
- matchDstIPv4Net = flowPathMatch.dstIPv4Net();
- }
- if (matchDstIPv4Net != null) {
- match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
- }
-
- // Match the IP protocol
- Byte matchIpProto = flowEntryMatch.ipProto();
- if ((matchIpProto == null) && (flowPathMatch != null)) {
- matchIpProto = flowPathMatch.ipProto();
- }
- if (matchIpProto != null) {
- match.setNetworkProtocol(matchIpProto);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
- }
-
- // Match the IP ToS (DSCP field, 6 bits)
- Byte matchIpToS = flowEntryMatch.ipToS();
- if ((matchIpToS == null) && (flowPathMatch != null)) {
- matchIpToS = flowPathMatch.ipToS();
- }
- if (matchIpToS != null) {
- match.setNetworkTypeOfService(matchIpToS);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
- }
-
- // Match the Source TCP/UDP port
- Short matchSrcTcpUdpPort = flowEntryMatch.srcTcpUdpPort();
- if ((matchSrcTcpUdpPort == null) && (flowPathMatch != null)) {
- matchSrcTcpUdpPort = flowPathMatch.srcTcpUdpPort();
- }
- if (matchSrcTcpUdpPort != null) {
- match.setTransportSource(matchSrcTcpUdpPort);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
- }
-
- // Match the Destination TCP/UDP port
- Short matchDstTcpUdpPort = flowEntryMatch.dstTcpUdpPort();
- if ((matchDstTcpUdpPort == null) && (flowPathMatch != null)) {
- matchDstTcpUdpPort = flowPathMatch.dstTcpUdpPort();
- }
- if (matchDstTcpUdpPort != null) {
- match.setTransportDestination(matchDstTcpUdpPort);
- match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
- }
-
- //
- // Fetch the actions
- //
- Short actionOutputPort = null;
- List<OFAction> openFlowActions = new ArrayList<OFAction>();
- int actionsLen = 0;
- FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
- //
- for (FlowEntryAction action : flowEntryActions.actions()) {
- ActionOutput actionOutput = action.actionOutput();
- ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
- ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
- ActionStripVlan actionStripVlan = action.actionStripVlan();
- ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
- ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
- ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
- ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
- ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
- ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
- ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
- ActionEnqueue actionEnqueue = action.actionEnqueue();
-
- if (actionOutput != null) {
- actionOutputPort = actionOutput.port().value();
- // XXX: The max length is hard-coded for now
- OFActionOutput ofa =
- new OFActionOutput(actionOutput.port().value(),
- (short)0xffff);
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetVlanId != null) {
- OFActionVirtualLanIdentifier ofa =
- new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetVlanPriority != null) {
- OFActionVirtualLanPriorityCodePoint ofa =
- new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionStripVlan != null) {
- if (actionStripVlan.stripVlan() == true) {
- OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
- }
-
- if (actionSetEthernetSrcAddr != null) {
- OFActionDataLayerSource ofa =
- new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetEthernetDstAddr != null) {
- OFActionDataLayerDestination ofa =
- new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetIPv4SrcAddr != null) {
- OFActionNetworkLayerSource ofa =
- new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetIPv4DstAddr != null) {
- OFActionNetworkLayerDestination ofa =
- new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetIpToS != null) {
- OFActionNetworkTypeOfService ofa =
- new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetTcpUdpSrcPort != null) {
- OFActionTransportLayerSource ofa =
- new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionSetTcpUdpDstPort != null) {
- OFActionTransportLayerDestination ofa =
- new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
-
- if (actionEnqueue != null) {
- OFActionEnqueue ofa =
- new OFActionEnqueue(actionEnqueue.port().value(),
- actionEnqueue.queueId());
- openFlowActions.add(ofa);
- actionsLen += ofa.getLength();
- }
- }
-
- fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
- .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
- .setPriority(PRIORITY_DEFAULT)
- .setBufferId(OFPacketOut.BUFFER_ID_NONE)
- .setCookie(cookie)
- .setCommand(flowModCommand)
- .setMatch(match)
- .setActions(openFlowActions)
- .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
- fm.setOutPort(OFPort.OFPP_NONE.getValue());
- if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
- (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
- if (actionOutputPort != null)
- fm.setOutPort(actionOutputPort);
- }
-
- //
- // TODO: Set the following flag
- // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
- // See method ForwardingBase::pushRoute()
- //
-
- //
- // Write the message to the switch
- //
- try {
- messageDamper.write(mySwitch, fm, null);
- mySwitch.flush();
- //
- // TODO: We should use the OpenFlow Barrier mechanism
- // to check for errors, and update the SwitchState
- // for a flow entry after the Barrier message is
- // is received.
- //
- // TODO: The FlowEntry Object in Titan should be set
- // to FE_SWITCH_UPDATED.
- //
- } catch (IOException e) {
- log.error("Failure writing flow mod from network map", e);
- return false;
- }
- return true;
+ return FlowSwitchOperation.installFlowEntry(
+ floodlightProvider.getOFMessageFactory(),
+ messageDamper, mySwitch, flowPath, flowEntry);
}
/**
@@ -2318,39 +797,4 @@
//
return (installFlowEntry(mySwitch, flowPath, flowEntry));
}
-
- /**
- * Install a Flow Entry on a remote controller.
- *
- * TODO: We need it now: Jono
- * - For now it will make a REST call to the remote controller.
- * - Internally, it needs to know the name of the remote controller.
- *
- * @param flowPath the flow path for the flow entry to install.
- * @param flowEntry the flow entry to install.
- * @return true on success, otherwise false.
- */
- public boolean installRemoteFlowEntry(FlowPath flowPath,
- FlowEntry flowEntry) {
- // TODO: We need it now: Jono
- // - For now it will make a REST call to the remote controller.
- // - Internally, it needs to know the name of the remote controller.
- return true;
- }
-
- /**
- * Remove a flow entry on a remote controller.
- *
- * @param flowPath the flow path for the flow entry to remove.
- * @param flowEntry the flow entry to remove.
- * @return true on success, otherwise false.
- */
- public boolean removeRemoteFlowEntry(FlowPath flowPath,
- FlowEntry flowEntry) {
- //
- // The installRemoteFlowEntry() method implements both installation
- // and removal of flow entries.
- //
- return (installRemoteFlowEntry(flowPath, flowEntry));
- }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowSwitchOperation.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowSwitchOperation.java
new file mode 100644
index 0000000..3eea1e1
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowSwitchOperation.java
@@ -0,0 +1,676 @@
+package net.onrc.onos.ofcontroller.flowmanager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.util.MACAddress;
+import net.floodlightcontroller.util.OFMessageDamper;
+
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.util.*;
+import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
+
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.*;
+import org.openflow.protocol.factory.BasicFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class for performing Flow-related operations on the Switch.
+ */
+class FlowSwitchOperation {
+ private static Logger log = LoggerFactory.getLogger(FlowSwitchOperation.class);
+ //
+ // TODO: Values copied from elsewhere (class LearningSwitch).
+ // The local copy should go away!
+ //
+ public static final short PRIORITY_DEFAULT = 100;
+ public static final short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 0; // infinity
+ public static final short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
+
+ /**
+ * Install a Flow Entry on a switch.
+ *
+ * @param messageFactory the OpenFlow message factory to use.
+ * @maram messageDamper the OpenFlow message damper to use.
+ * @param mySwitch the switch to install the Flow Entry into.
+ * @param flowObj the flow path object for the flow entry to install.
+ * @param flowEntryObj the flow entry object to install.
+ * @return true on success, otherwise false.
+ */
+ static boolean installFlowEntry(BasicFactory messageFactory,
+ OFMessageDamper messageDamper,
+ IOFSwitch mySwitch, IFlowPath flowObj,
+ IFlowEntry flowEntryObj) {
+ String flowEntryIdStr = flowEntryObj.getFlowEntryId();
+ if (flowEntryIdStr == null)
+ return false;
+ FlowEntryId flowEntryId = new FlowEntryId(flowEntryIdStr);
+ String userState = flowEntryObj.getUserState();
+ if (userState == null)
+ return false;
+
+ //
+ // Create the Open Flow Flow Modification Entry to push
+ //
+ OFFlowMod fm = (OFFlowMod)messageFactory.getMessage(OFType.FLOW_MOD);
+ long cookie = flowEntryId.value();
+
+ short flowModCommand = OFFlowMod.OFPFC_ADD;
+ if (userState.equals("FE_USER_ADD")) {
+ flowModCommand = OFFlowMod.OFPFC_ADD;
+ } else if (userState.equals("FE_USER_MODIFY")) {
+ flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
+ } else if (userState.equals("FE_USER_DELETE")) {
+ flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
+ } else {
+ // Unknown user state. Ignore the entry
+ log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
+ flowEntryId.toString(), userState);
+ return false;
+ }
+
+ //
+ // Fetch the match conditions.
+ //
+ // NOTE: The Flow matching conditions common for all Flow Entries are
+ // used ONLY if a Flow Entry does NOT have the corresponding matching
+ // condition set.
+ //
+ OFMatch match = new OFMatch();
+ match.setWildcards(OFMatch.OFPFW_ALL);
+
+ // Match the Incoming Port
+ Short matchInPort = flowEntryObj.getMatchInPort();
+ if (matchInPort != null) {
+ match.setInputPort(matchInPort);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
+ }
+
+ // Match the Source MAC address
+ String matchSrcMac = flowEntryObj.getMatchSrcMac();
+ if (matchSrcMac == null)
+ matchSrcMac = flowObj.getMatchSrcMac();
+ if (matchSrcMac != null) {
+ match.setDataLayerSource(matchSrcMac);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
+ }
+
+ // Match the Destination MAC address
+ String matchDstMac = flowEntryObj.getMatchDstMac();
+ if (matchDstMac == null)
+ matchDstMac = flowObj.getMatchDstMac();
+ if (matchDstMac != null) {
+ match.setDataLayerDestination(matchDstMac);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
+ }
+
+ // Match the Ethernet Frame Type
+ Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+ if (matchEthernetFrameType == null)
+ matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
+ if (matchEthernetFrameType != null) {
+ match.setDataLayerType(matchEthernetFrameType);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+ }
+
+ // Match the VLAN ID
+ Short matchVlanId = flowEntryObj.getMatchVlanId();
+ if (matchVlanId == null)
+ matchVlanId = flowObj.getMatchVlanId();
+ if (matchVlanId != null) {
+ match.setDataLayerVirtualLan(matchVlanId);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
+ }
+
+ // Match the VLAN priority
+ Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
+ if (matchVlanPriority == null)
+ matchVlanPriority = flowObj.getMatchVlanPriority();
+ if (matchVlanPriority != null) {
+ match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
+ }
+
+ // Match the Source IPv4 Network prefix
+ String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+ if (matchSrcIPv4Net == null)
+ matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
+ if (matchSrcIPv4Net != null) {
+ match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
+ }
+
+ // Natch the Destination IPv4 Network prefix
+ String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+ if (matchDstIPv4Net == null)
+ matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
+ if (matchDstIPv4Net != null) {
+ match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
+ }
+
+ // Match the IP protocol
+ Byte matchIpProto = flowEntryObj.getMatchIpProto();
+ if (matchIpProto == null)
+ matchIpProto = flowObj.getMatchIpProto();
+ if (matchIpProto != null) {
+ match.setNetworkProtocol(matchIpProto);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
+ }
+
+ // Match the IP ToS (DSCP field, 6 bits)
+ Byte matchIpToS = flowEntryObj.getMatchIpToS();
+ if (matchIpToS == null)
+ matchIpToS = flowObj.getMatchIpToS();
+ if (matchIpToS != null) {
+ match.setNetworkTypeOfService(matchIpToS);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
+ }
+
+ // Match the Source TCP/UDP port
+ Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
+ if (matchSrcTcpUdpPort == null)
+ matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
+ if (matchSrcTcpUdpPort != null) {
+ match.setTransportSource(matchSrcTcpUdpPort);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+ }
+
+ // Match the Destination TCP/UDP port
+ Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
+ if (matchDstTcpUdpPort == null)
+ matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
+ if (matchDstTcpUdpPort != null) {
+ match.setTransportDestination(matchDstTcpUdpPort);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+ }
+
+ //
+ // Fetch the actions
+ //
+ Short actionOutputPort = null;
+ List<OFAction> openFlowActions = new ArrayList<OFAction>();
+ int actionsLen = 0;
+ FlowEntryActions flowEntryActions = null;
+ String actionsStr = flowEntryObj.getActions();
+ if (actionsStr != null)
+ flowEntryActions = new FlowEntryActions(actionsStr);
+ for (FlowEntryAction action : flowEntryActions.actions()) {
+ ActionOutput actionOutput = action.actionOutput();
+ ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
+ ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
+ ActionStripVlan actionStripVlan = action.actionStripVlan();
+ ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
+ ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
+ ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
+ ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
+ ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
+ ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
+ ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
+ ActionEnqueue actionEnqueue = action.actionEnqueue();
+
+ if (actionOutput != null) {
+ actionOutputPort = actionOutput.port().value();
+ // XXX: The max length is hard-coded for now
+ OFActionOutput ofa =
+ new OFActionOutput(actionOutput.port().value(),
+ (short)0xffff);
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanId != null) {
+ OFActionVirtualLanIdentifier ofa =
+ new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanPriority != null) {
+ OFActionVirtualLanPriorityCodePoint ofa =
+ new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionStripVlan != null) {
+ if (actionStripVlan.stripVlan() == true) {
+ OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+ }
+
+ if (actionSetEthernetSrcAddr != null) {
+ OFActionDataLayerSource ofa =
+ new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetEthernetDstAddr != null) {
+ OFActionDataLayerDestination ofa =
+ new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4SrcAddr != null) {
+ OFActionNetworkLayerSource ofa =
+ new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4DstAddr != null) {
+ OFActionNetworkLayerDestination ofa =
+ new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIpToS != null) {
+ OFActionNetworkTypeOfService ofa =
+ new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpSrcPort != null) {
+ OFActionTransportLayerSource ofa =
+ new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpDstPort != null) {
+ OFActionTransportLayerDestination ofa =
+ new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionEnqueue != null) {
+ OFActionEnqueue ofa =
+ new OFActionEnqueue(actionEnqueue.port().value(),
+ actionEnqueue.queueId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+ }
+
+ fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
+ .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
+ .setPriority(PRIORITY_DEFAULT)
+ .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+ .setCookie(cookie)
+ .setCommand(flowModCommand)
+ .setMatch(match)
+ .setActions(openFlowActions)
+ .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
+ fm.setOutPort(OFPort.OFPP_NONE.getValue());
+ if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
+ (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
+ if (actionOutputPort != null)
+ fm.setOutPort(actionOutputPort);
+ }
+
+ //
+ // TODO: Set the following flag
+ // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
+ // See method ForwardingBase::pushRoute()
+ //
+
+ //
+ // Write the message to the switch
+ //
+ log.debug("MEASUREMENT: Installing flow entry " + userState +
+ " into switch DPID: " +
+ mySwitch.getStringId() +
+ " flowEntryId: " + flowEntryId.toString() +
+ " srcMac: " + matchSrcMac + " dstMac: " + matchDstMac +
+ " inPort: " + matchInPort + " outPort: " + actionOutputPort
+ );
+ try {
+ messageDamper.write(mySwitch, fm, null);
+ mySwitch.flush();
+ //
+ // TODO: We should use the OpenFlow Barrier mechanism
+ // to check for errors, and update the SwitchState
+ // for a flow entry after the Barrier message is
+ // is received.
+ //
+ flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
+ } catch (IOException e) {
+ log.error("Failure writing flow mod from network map", e);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Install a Flow Entry on a switch.
+ *
+ * @param messageFactory the OpenFlow message factory to use.
+ * @maram messageDamper the OpenFlow message damper to use.
+ * @param mySwitch the switch to install the Flow Entry into.
+ * @param flowPath the flow path for the flow entry to install.
+ * @param flowEntry the flow entry to install.
+ * @return true on success, otherwise false.
+ */
+ static boolean installFlowEntry(BasicFactory messageFactory,
+ OFMessageDamper messageDamper,
+ IOFSwitch mySwitch, FlowPath flowPath,
+ FlowEntry flowEntry) {
+ //
+ // Create the OpenFlow Flow Modification Entry to push
+ //
+ OFFlowMod fm = (OFFlowMod)messageFactory.getMessage(OFType.FLOW_MOD);
+ long cookie = flowEntry.flowEntryId().value();
+
+ short flowModCommand = OFFlowMod.OFPFC_ADD;
+ if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_ADD) {
+ flowModCommand = OFFlowMod.OFPFC_ADD;
+ } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_MODIFY) {
+ flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
+ } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE) {
+ flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
+ } else {
+ // Unknown user state. Ignore the entry
+ log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
+ flowEntry.flowEntryId().toString(),
+ flowEntry.flowEntryUserState());
+ return false;
+ }
+
+ //
+ // Fetch the match conditions.
+ //
+ // NOTE: The Flow matching conditions common for all Flow Entries are
+ // used ONLY if a Flow Entry does NOT have the corresponding matching
+ // condition set.
+ //
+ OFMatch match = new OFMatch();
+ match.setWildcards(OFMatch.OFPFW_ALL);
+ FlowEntryMatch flowPathMatch = flowPath.flowEntryMatch();
+ FlowEntryMatch flowEntryMatch = flowEntry.flowEntryMatch();
+
+ // Match the Incoming Port
+ Port matchInPort = flowEntryMatch.inPort();
+ if (matchInPort != null) {
+ match.setInputPort(matchInPort.value());
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
+ }
+
+ // Match the Source MAC address
+ MACAddress matchSrcMac = flowEntryMatch.srcMac();
+ if ((matchSrcMac == null) && (flowPathMatch != null)) {
+ matchSrcMac = flowPathMatch.srcMac();
+ }
+ if (matchSrcMac != null) {
+ match.setDataLayerSource(matchSrcMac.toString());
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
+ }
+
+ // Match the Destination MAC address
+ MACAddress matchDstMac = flowEntryMatch.dstMac();
+ if ((matchDstMac == null) && (flowPathMatch != null)) {
+ matchDstMac = flowPathMatch.dstMac();
+ }
+ if (matchDstMac != null) {
+ match.setDataLayerDestination(matchDstMac.toString());
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
+ }
+
+ // Match the Ethernet Frame Type
+ Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
+ if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
+ matchEthernetFrameType = flowPathMatch.ethernetFrameType();
+ }
+ if (matchEthernetFrameType != null) {
+ match.setDataLayerType(matchEthernetFrameType);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+ }
+
+ // Match the VLAN ID
+ Short matchVlanId = flowEntryMatch.vlanId();
+ if ((matchVlanId == null) && (flowPathMatch != null)) {
+ matchVlanId = flowPathMatch.vlanId();
+ }
+ if (matchVlanId != null) {
+ match.setDataLayerVirtualLan(matchVlanId);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
+ }
+
+ // Match the VLAN priority
+ Byte matchVlanPriority = flowEntryMatch.vlanPriority();
+ if ((matchVlanPriority == null) && (flowPathMatch != null)) {
+ matchVlanPriority = flowPathMatch.vlanPriority();
+ }
+ if (matchVlanPriority != null) {
+ match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
+ }
+
+ // Match the Source IPv4 Network prefix
+ IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
+ if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
+ matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
+ }
+ if (matchSrcIPv4Net != null) {
+ match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
+ }
+
+ // Natch the Destination IPv4 Network prefix
+ IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
+ if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
+ matchDstIPv4Net = flowPathMatch.dstIPv4Net();
+ }
+ if (matchDstIPv4Net != null) {
+ match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
+ }
+
+ // Match the IP protocol
+ Byte matchIpProto = flowEntryMatch.ipProto();
+ if ((matchIpProto == null) && (flowPathMatch != null)) {
+ matchIpProto = flowPathMatch.ipProto();
+ }
+ if (matchIpProto != null) {
+ match.setNetworkProtocol(matchIpProto);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
+ }
+
+ // Match the IP ToS (DSCP field, 6 bits)
+ Byte matchIpToS = flowEntryMatch.ipToS();
+ if ((matchIpToS == null) && (flowPathMatch != null)) {
+ matchIpToS = flowPathMatch.ipToS();
+ }
+ if (matchIpToS != null) {
+ match.setNetworkTypeOfService(matchIpToS);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
+ }
+
+ // Match the Source TCP/UDP port
+ Short matchSrcTcpUdpPort = flowEntryMatch.srcTcpUdpPort();
+ if ((matchSrcTcpUdpPort == null) && (flowPathMatch != null)) {
+ matchSrcTcpUdpPort = flowPathMatch.srcTcpUdpPort();
+ }
+ if (matchSrcTcpUdpPort != null) {
+ match.setTransportSource(matchSrcTcpUdpPort);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+ }
+
+ // Match the Destination TCP/UDP port
+ Short matchDstTcpUdpPort = flowEntryMatch.dstTcpUdpPort();
+ if ((matchDstTcpUdpPort == null) && (flowPathMatch != null)) {
+ matchDstTcpUdpPort = flowPathMatch.dstTcpUdpPort();
+ }
+ if (matchDstTcpUdpPort != null) {
+ match.setTransportDestination(matchDstTcpUdpPort);
+ match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+ }
+
+ //
+ // Fetch the actions
+ //
+ Short actionOutputPort = null;
+ List<OFAction> openFlowActions = new ArrayList<OFAction>();
+ int actionsLen = 0;
+ FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
+ //
+ for (FlowEntryAction action : flowEntryActions.actions()) {
+ ActionOutput actionOutput = action.actionOutput();
+ ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
+ ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
+ ActionStripVlan actionStripVlan = action.actionStripVlan();
+ ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
+ ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
+ ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
+ ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
+ ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
+ ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
+ ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
+ ActionEnqueue actionEnqueue = action.actionEnqueue();
+
+ if (actionOutput != null) {
+ actionOutputPort = actionOutput.port().value();
+ // XXX: The max length is hard-coded for now
+ OFActionOutput ofa =
+ new OFActionOutput(actionOutput.port().value(),
+ (short)0xffff);
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanId != null) {
+ OFActionVirtualLanIdentifier ofa =
+ new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetVlanPriority != null) {
+ OFActionVirtualLanPriorityCodePoint ofa =
+ new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionStripVlan != null) {
+ if (actionStripVlan.stripVlan() == true) {
+ OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+ }
+
+ if (actionSetEthernetSrcAddr != null) {
+ OFActionDataLayerSource ofa =
+ new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetEthernetDstAddr != null) {
+ OFActionDataLayerDestination ofa =
+ new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4SrcAddr != null) {
+ OFActionNetworkLayerSource ofa =
+ new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIPv4DstAddr != null) {
+ OFActionNetworkLayerDestination ofa =
+ new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetIpToS != null) {
+ OFActionNetworkTypeOfService ofa =
+ new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpSrcPort != null) {
+ OFActionTransportLayerSource ofa =
+ new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionSetTcpUdpDstPort != null) {
+ OFActionTransportLayerDestination ofa =
+ new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+
+ if (actionEnqueue != null) {
+ OFActionEnqueue ofa =
+ new OFActionEnqueue(actionEnqueue.port().value(),
+ actionEnqueue.queueId());
+ openFlowActions.add(ofa);
+ actionsLen += ofa.getLength();
+ }
+ }
+
+ fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
+ .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
+ .setPriority(PRIORITY_DEFAULT)
+ .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+ .setCookie(cookie)
+ .setCommand(flowModCommand)
+ .setMatch(match)
+ .setActions(openFlowActions)
+ .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
+ fm.setOutPort(OFPort.OFPP_NONE.getValue());
+ if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
+ (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
+ if (actionOutputPort != null)
+ fm.setOutPort(actionOutputPort);
+ }
+
+ //
+ // TODO: Set the following flag
+ // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
+ // See method ForwardingBase::pushRoute()
+ //
+
+ //
+ // Write the message to the switch
+ //
+ try {
+ messageDamper.write(mySwitch, fm, null);
+ mySwitch.flush();
+ //
+ // TODO: We should use the OpenFlow Barrier mechanism
+ // to check for errors, and update the SwitchState
+ // for a flow entry after the Barrier message is
+ // is received.
+ //
+ // TODO: The FlowEntry Object in Titan should be set
+ // to FE_SWITCH_UPDATED.
+ //
+ } catch (IOException e) {
+ log.error("Failure writing flow mod from network map", e);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
index df11d6b..73f86b6 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
@@ -67,6 +67,13 @@
FlowPath getFlow(FlowId flowId);
/**
+ * Get all installed flows by all installers.
+ *
+ * @return the Flow Paths if found, otherwise null.
+ */
+ ArrayList<FlowPath> getAllFlows();
+
+ /**
* Get all previously added flows by a specific installer for a given
* data path endpoints.
*
@@ -95,13 +102,6 @@
ArrayList<IFlowPath> getAllFlowsSummary(FlowId flowId, int maxFlows);
/**
- * Get all installed flows by all installers.
- *
- * @return the Flow Paths if found, otherwise null.
- */
- ArrayList<FlowPath> getAllFlows();
-
- /**
* Add and maintain a shortest-path flow.
*
* NOTE: The Flow Path argument does NOT contain all flow entries.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java b/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
index bd0ca38..9585366 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
@@ -11,73 +11,72 @@
*/
public interface ITopologyNetService extends IFloodlightService {
/**
- * Get the shortest path from a source to a destination.
- *
- * @param src the source in the shortest path computation.
- * @param dest the destination in the shortest path computation.
- * @return the data path with the computed shortest path if
- * found, otherwise null.
- */
- DataPath getShortestPath(SwitchPort src, SwitchPort dest);
-
- /**
* Fetch the Switch and Ports info from the Titan Graph
* and return it for fast access during the shortest path
* computation.
*
- * After fetching the state, method @ref getTopoShortestPath()
+ * After fetching the state, method @ref getTopologyShortestPath()
* can be used for fast shortest path computation.
*
* Note: There is certain cost to fetch the state, hence it should
* be used only when there is a large number of shortest path
* computations that need to be done on the same topology.
- * Typically, a single call to @ref prepareShortestPathTopo()
+ * Typically, a single call to @ref newDatabaseTopology()
* should be followed by a large number of calls to
- * method @ref getTopoShortestPath().
- * After the last @ref getTopoShortestPath() call,
- * method @ref dropShortestPathTopo() should be used to release
+ * method @ref getTopologyShortestPath().
+ * After the last @ref getTopologyShortestPath() call,
+ * method @ref dropTopology() should be used to release
* the internal state that is not needed anymore:
*
- * Map<Long, ?> shortestPathTopo;
- * shortestPathTopo = prepareShortestPathTopo();
+ * Topology topology = topologyManager.newDatabaseTopology();
* for (int i = 0; i < 10000; i++) {
- * dataPath = getTopoShortestPath(shortestPathTopo, ...);
+ * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
* ...
* }
- * dropShortestPathTopo(shortestPathTopo);
+ * topologyManager.dropTopology(shortestPathTopo);
*
- * @return the Shortest Path info handler stored in a map.
+ * @return the allocated topology handler.
*/
- Map<Long, ?> prepareShortestPathTopo();
+ Topology newDatabaseTopology();
/**
- * Release the state that was populated by
- * method @ref prepareShortestPathTopo().
+ * Release the topology that was populated by
+ * method @ref newDatabaseTopology().
*
- * See the documentation for method @ref prepareShortestPathTopo()
+ * See the documentation for method @ref newDatabaseTopology()
* for additional information and usage.
*
- * @param shortestPathTopo the Shortest Path info handler to release.
+ * @param topology the topology to release.
*/
- void dropShortestPathTopo(Map<Long, ?> shortestPathTopo);
+ void dropTopology(Topology topology);
/**
* Get the shortest path from a source to a destination by
* using the pre-populated local topology state prepared
- * by method @ref prepareShortestPathTopo().
+ * by method @ref newDatabaseTopology().
*
- * See the documentation for method @ref prepareShortestPathTopo()
+ * See the documentation for method @ref newDatabaseTopology()
* for additional information and usage.
*
- * @param shortestPathTopo the Shortest Path info handler
- * to use.
+ * @param topology the topology handler to use.
* @param src the source in the shortest path computation.
* @param dest the destination in the shortest path computation.
* @return the data path with the computed shortest path if
* found, otherwise null.
*/
- DataPath getTopoShortestPath(Map<Long, ?> shortestPathTopo,
- SwitchPort src, SwitchPort dest);
+ DataPath getTopologyShortestPath(Topology topology,
+ SwitchPort src, SwitchPort dest);
+
+ /**
+ * Get the shortest path from a source to a destination by using
+ * the underlying database.
+ *
+ * @param src the source in the shortest path computation.
+ * @param dest the destination in the shortest path computation.
+ * @return the data path with the computed shortest path if
+ * found, otherwise null.
+ */
+ DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest);
/**
* Test whether a route exists from a source to a destination.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java b/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
new file mode 100644
index 0000000..1133d3d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
@@ -0,0 +1,325 @@
+package net.onrc.onos.ofcontroller.topology;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+
+import org.openflow.util.HexString;
+
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Vertex;
+
+/**
+ * A class for implementing the Shortest Path in a topology.
+ */
+public class ShortestPath {
+ /**
+ * Get the shortest path from a source to a destination by
+ * using the pre-populated local topology state prepared
+ * by method @ref TopologyManager.newDatabaseTopology().
+ *
+ * For additional documentation and usage, see method
+ * @ref TopologyManager.newDatabaseTopology()
+ *
+ * @param topology the topology handler to use.
+ * @param src the source in the shortest path computation.
+ * @param dest the destination in the shortest path computation.
+ * @return the data path with the computed shortest path if
+ * found, otherwise null.
+ */
+ public static DataPath getTopologyShortestPath(
+ Topology topology,
+ SwitchPort src, SwitchPort dest) {
+ DataPath result_data_path = new DataPath();
+
+ // Initialize the source and destination in the data path to return
+ result_data_path.setSrcPort(src);
+ result_data_path.setDstPort(dest);
+
+ String dpid_src = src.dpid().toString();
+ String dpid_dest = dest.dpid().toString();
+
+ // Get the source vertex
+ Node v_src = topology.getNode(src.dpid().value());
+ if (v_src == null) {
+ return null; // Source vertex not found
+ }
+
+ // Get the destination vertex
+ Node v_dest = topology.getNode(dest.dpid().value());
+ if (v_dest == null) {
+ return null; // Destination vertex not found
+ }
+
+ //
+ // Test whether we are computing a path from/to the same DPID.
+ // If "yes", then just add a single flow entry in the return result.
+ //
+ if (dpid_src.equals(dpid_dest)) {
+ FlowEntry flowEntry = new FlowEntry();
+ flowEntry.setDpid(src.dpid());
+ flowEntry.setInPort(src.port());
+ flowEntry.setOutPort(dest.port());
+ result_data_path.flowEntries().add(flowEntry);
+ return result_data_path;
+ }
+
+ //
+ // Implement the Shortest Path computation by using Breath First Search
+ //
+ Set<Node> visitedSet = new HashSet<Node>();
+ Queue<Node> processingList = new LinkedList<Node>();
+ Map<Node, Node.Link> previousVertexMap = new HashMap<Node, Node.Link>();
+ processingList.add(v_src);
+ visitedSet.add(v_src);
+ Boolean path_found = false;
+ while (! processingList.isEmpty()) {
+ Node nextVertex = processingList.poll();
+ if (v_dest == nextVertex) {
+ path_found = true;
+ break;
+ }
+ for (Node.Link link : nextVertex.links.values()) {
+ Node child = link.neighbor;
+ if (! visitedSet.contains(child)) {
+ previousVertexMap.put(child, link);
+ visitedSet.add(child);
+ processingList.add(child);
+ }
+ }
+ }
+ if (! path_found)
+ return null; // No path found
+
+ // Collect the path as a list of links
+ List<Node.Link> resultPath = new LinkedList<Node.Link>();
+ Node previousVertex = v_dest;
+ while (! v_src.equals(previousVertex)) {
+ Node.Link currentLink = previousVertexMap.get(previousVertex);
+ resultPath.add(currentLink);
+ previousVertex = currentLink.me;
+ }
+ Collections.reverse(resultPath);
+
+ //
+ // Loop through the result and prepare the return result
+ // as a list of Flow Entries.
+ //
+ Port inPort = new Port(src.port().value());
+ Port outPort;
+ for (Node.Link link: resultPath) {
+ // Setup the outgoing port, and add the Flow Entry
+ outPort = new Port(link.myPort);
+
+ FlowEntry flowEntry = new FlowEntry();
+ flowEntry.setDpid(new Dpid(link.me.nodeId));
+ flowEntry.setInPort(inPort);
+ flowEntry.setOutPort(outPort);
+ result_data_path.flowEntries().add(flowEntry);
+
+ // Setup the next incoming port
+ inPort = new Port(link.neighborPort);
+ }
+ if (resultPath.size() > 0) {
+ // Add the last Flow Entry
+ FlowEntry flowEntry = new FlowEntry();
+ flowEntry.setDpid(new Dpid(dest.dpid().value()));
+ flowEntry.setInPort(inPort);
+ flowEntry.setOutPort(dest.port());
+ result_data_path.flowEntries().add(flowEntry);
+ }
+
+ if (result_data_path.flowEntries().size() > 0)
+ return result_data_path;
+
+ return null;
+ }
+
+ /**
+ * Get the shortest path from a source to a destination by using
+ * the underlying Graph Database.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ * @param src the source in the shortest path computation.
+ * @param dest the destination in the shortest path computation.
+ * @return the data path with the computed shortest path if
+ * found, otherwise null.
+ */
+ public static DataPath getDatabaseShortestPath(GraphDBOperation dbHandler,
+ SwitchPort src, SwitchPort dest) {
+ DataPath result_data_path = new DataPath();
+
+ // Initialize the source and destination in the data path to return
+ result_data_path.setSrcPort(src);
+ result_data_path.setDstPort(dest);
+
+ String dpid_src = src.dpid().toString();
+ String dpid_dest = dest.dpid().toString();
+
+ // Get the source and destination switches
+ ISwitchObject srcSwitch =
+ dbHandler.searchActiveSwitch(dpid_src);
+ ISwitchObject destSwitch =
+ dbHandler.searchActiveSwitch(dpid_dest);
+ if (srcSwitch == null || destSwitch == null) {
+ return null;
+ }
+
+ //
+ // Test whether we are computing a path from/to the same DPID.
+ // If "yes", then just add a single flow entry in the return result.
+ //
+ if (dpid_src.equals(dpid_dest)) {
+ FlowEntry flowEntry = new FlowEntry();
+ flowEntry.setDpid(src.dpid());
+ flowEntry.setInPort(src.port());
+ flowEntry.setOutPort(dest.port());
+ result_data_path.flowEntries().add(flowEntry);
+ dbHandler.commit();
+ return result_data_path;
+ }
+
+ Vertex v_src = srcSwitch.asVertex();
+ Vertex v_dest = destSwitch.asVertex();
+
+ //
+ // Implement the Shortest Path computation by using Breath First Search
+ //
+ Set<Vertex> visitedSet = new HashSet<Vertex>();
+ Queue<Vertex> processingList = new LinkedList<Vertex>();
+ Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
+
+ processingList.add(v_src);
+ visitedSet.add(v_src);
+ Boolean path_found = false;
+ while (! processingList.isEmpty()) {
+ Vertex nextVertex = processingList.poll();
+ if (v_dest.equals(nextVertex)) {
+ path_found = true;
+ break;
+ }
+ for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
+ // Ignore inactive ports
+ if (! parentPort.getProperty("state").toString().equals("ACTIVE"))
+ continue;
+
+ for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
+ // Ignore inactive ports
+ if (! childPort.getProperty("state").toString().equals("ACTIVE"))
+ continue;
+
+ for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
+ // Ignore inactive switches
+ String state = child.getProperty("state").toString();
+ if (! state.equals(SwitchState.ACTIVE.toString()))
+ continue;
+
+ if (! visitedSet.contains(child)) {
+ previousVertexMap.put(parentPort, nextVertex);
+ previousVertexMap.put(childPort, parentPort);
+ previousVertexMap.put(child, childPort);
+ visitedSet.add(child);
+ processingList.add(child);
+ }
+ }
+ }
+ }
+ }
+ if (! path_found)
+ return null; // No path found
+
+ List<Vertex> resultPath = new LinkedList<Vertex>();
+ Vertex previousVertex = v_dest;
+ resultPath.add(v_dest);
+ while (! v_src.equals(previousVertex)) {
+ Vertex currentVertex = previousVertexMap.get(previousVertex);
+ resultPath.add(currentVertex);
+ previousVertex = currentVertex;
+ }
+ Collections.reverse(resultPath);
+
+
+ //
+ // Loop through the result and prepare the return result
+ // as a list of Flow Entries.
+ //
+ long nodeId = 0;
+ short portId = 0;
+ Port inPort = new Port(src.port().value());
+ Port outPort = new Port();
+ int idx = 0;
+ for (Vertex v: resultPath) {
+ String type = v.getProperty("type").toString();
+ // System.out.println("type: " + type);
+ if (type.equals("port")) {
+ //String number = v.getProperty("number").toString();
+ // System.out.println("number: " + number);
+
+ Object obj = v.getProperty("number");
+ // String class_str = obj.getClass().toString();
+ if (obj instanceof Short) {
+ portId = (Short)obj;
+ } else if (obj instanceof Integer) {
+ Integer int_nodeId = (Integer)obj;
+ portId = int_nodeId.shortValue();
+ // int int_nodeId = (Integer)obj;
+ // portId = (short)int_nodeId.;
+ }
+ } else if (type.equals("switch")) {
+ String dpid = v.getProperty("dpid").toString();
+ nodeId = HexString.toLong(dpid);
+
+ // System.out.println("dpid: " + dpid);
+ }
+ idx++;
+ if (idx == 1) {
+ continue;
+ }
+ int mod = idx % 3;
+ if (mod == 0) {
+ // Setup the incoming port
+ inPort = new Port(portId);
+ continue;
+ }
+ if (mod == 2) {
+ // Setup the outgoing port, and add the Flow Entry
+ outPort = new Port(portId);
+
+ FlowEntry flowEntry = new FlowEntry();
+ flowEntry.setDpid(new Dpid(nodeId));
+ flowEntry.setInPort(inPort);
+ flowEntry.setOutPort(outPort);
+ result_data_path.flowEntries().add(flowEntry);
+ continue;
+ }
+ }
+ if (idx > 0) {
+ // Add the last Flow Entry
+ FlowEntry flowEntry = new FlowEntry();
+ flowEntry.setDpid(new Dpid(nodeId));
+ flowEntry.setInPort(inPort);
+ flowEntry.setOutPort(dest.port());
+ result_data_path.flowEntries().add(flowEntry);
+ }
+
+ dbHandler.commit();
+ if (result_data_path.flowEntries().size() > 0)
+ return result_data_path;
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
new file mode 100644
index 0000000..a2f2c21
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
@@ -0,0 +1,174 @@
+package net.onrc.onos.ofcontroller.topology;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+
+import org.openflow.util.HexString;
+
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Vertex;
+
+/**
+ * A class for storing Node and Link information for fast computation
+ * of shortest paths.
+ */
+class Node {
+ /**
+ * A class for storing Link information for fast computation of shortest
+ * paths.
+ */
+ class Link {
+ public Node me; // The node this link originates from
+ public Node neighbor; // The neighbor node on the other side
+ public short myPort; // Local port number for the link
+ public short neighborPort; // Neighbor port number for the link
+
+ /**
+ * Link constructor.
+ *
+ * @param me the node this link originates from.
+ * @param the neighbor node on the other side of the link.
+ * @param myPort local port number for the link.
+ * @param neighborPort neighrobr port number for the link.
+ */
+ public Link(Node me, Node neighbor, short myPort, short neighborPort) {
+ this.me = me;
+ this.neighbor = neighbor;
+ this.myPort = myPort;
+ this.neighborPort = neighborPort;
+ }
+ };
+
+ public long nodeId; // The node ID
+ public HashMap<Short, Link> links; // The links originating from this node
+
+ /**
+ * Node constructor.
+ *
+ * @param nodeId the node ID.
+ */
+ public Node(long nodeId) {
+ this.nodeId = nodeId;
+ links = new HashMap<Short, Link>();
+ }
+
+ /**
+ * Add a neighbor.
+ *
+ * A new link to the neighbor will be created.
+ *
+ * @param neighbor the neighbor to add.
+ * @param myPort the local port number for the link to the neighbor.
+ * @param neighborPort the neighbor port number for the link.
+ */
+ public void addNeighbor(Node neighbor, short myPort, short neighborPort) {
+ Link link = new Link(this, neighbor, myPort, neighborPort);
+ links.put(myPort, link);
+ }
+};
+
+/**
+ * A class for storing topology information.
+ */
+public class Topology {
+ private Map<Long, Node> nodesMap; // The dpid->Node mapping
+
+ public Topology() {
+ nodesMap = new HashMap<Long, Node>();
+ }
+
+ /**
+ * Get a node for a give Node ID.
+ *
+ * @param nodeId the Node ID to use.
+ * @return the corresponding Node if found, otherwise null.
+ */
+ Node getNode(long nodeId) {
+ return nodesMap.get(nodeId);
+ }
+
+ /**
+ * Read topology state from the database.
+ *
+ * @param dbHandler the Graph Database handler to use.
+ */
+ public void readFromDatabase(GraphDBOperation dbHandler) {
+ //
+ // Fetch the relevant info from the Switch and Port vertices
+ // from the Titan Graph.
+ //
+ Iterable<ISwitchObject> activeSwitches = dbHandler.getActiveSwitches();
+ for (ISwitchObject switchObj : activeSwitches) {
+ Vertex nodeVertex = switchObj.asVertex();
+ //
+ // The Switch info
+ //
+ String nodeDpid = nodeVertex.getProperty("dpid").toString();
+ long nodeId = HexString.toLong(nodeDpid);
+ Node me = nodesMap.get(nodeId);
+ if (me == null) {
+ me = new Node(nodeId);
+ nodesMap.put(nodeId, me);
+ }
+
+ //
+ // The local Port info
+ //
+ for (Vertex myPortVertex : nodeVertex.getVertices(Direction.OUT, "on")) {
+ // Ignore inactive ports
+ if (! myPortVertex.getProperty("state").toString().equals("ACTIVE"))
+ continue;
+
+ short myPort = 0;
+ Object obj = myPortVertex.getProperty("number");
+ if (obj instanceof Short) {
+ myPort = (Short)obj;
+ } else if (obj instanceof Integer) {
+ Integer int_nodeId = (Integer)obj;
+ myPort = int_nodeId.shortValue();
+ }
+
+ //
+ // The neighbor Port info
+ //
+ for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
+ // Ignore inactive ports
+ if (! neighborPortVertex.getProperty("state").toString().equals("ACTIVE"))
+ continue;
+
+ short neighborPort = 0;
+ obj = neighborPortVertex.getProperty("number");
+ if (obj instanceof Short) {
+ neighborPort = (Short)obj;
+ } else if (obj instanceof Integer) {
+ Integer int_nodeId = (Integer)obj;
+ neighborPort = int_nodeId.shortValue();
+ }
+ //
+ // The neighbor Switch info
+ //
+ for (Vertex neighborVertex : neighborPortVertex.getVertices(Direction.IN, "on")) {
+ // Ignore inactive switches
+ String state = neighborVertex.getProperty("state").toString();
+ if (! state.equals(SwitchState.ACTIVE.toString()))
+ continue;
+
+ String neighborDpid = neighborVertex.getProperty("dpid").toString();
+ long neighborId = HexString.toLong(neighborDpid);
+ Node neighbor = nodesMap.get(neighborId);
+ if (neighbor == null) {
+ neighbor = new Node(neighborId);
+ nodesMap.put(neighborId, neighbor);
+ }
+ me.addNeighbor(neighbor, myPort, neighborPort);
+ }
+ }
+ }
+ }
+ dbHandler.commit();
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
index 618ae39..81ff599 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
@@ -1,99 +1,34 @@
package net.onrc.onos.ofcontroller.topology;
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+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.onrc.onos.datagrid.IDatagridService;
import net.onrc.onos.graph.GraphDBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.floodlightlistener.INetworkGraphService;
import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.Port;
import net.onrc.onos.ofcontroller.util.SwitchPort;
-import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Vertex;
-
-
-/**
- * A class for storing Node and Link information for fast computation
- * of shortest paths.
- */
-class Node {
- /**
- * A class for storing Link information for fast computation of shortest
- * paths.
- */
- class Link {
- public Node me; // The node this link originates from
- public Node neighbor; // The neighbor node on the other side
- public short myPort; // Local port number for the link
- public short neighborPort; // Neighbor port number for the link
-
- /**
- * Link constructor.
- *
- * @param me the node this link originates from.
- * @param the neighbor node on the other side of the link.
- * @param myPort local port number for the link.
- * @param neighborPort neighrobr port number for the link.
- */
- public Link(Node me, Node neighbor, short myPort, short neighborPort) {
- this.me = me;
- this.neighbor = neighbor;
- this.myPort = myPort;
- this.neighborPort = neighborPort;
- }
- };
-
- public long nodeId; // The node ID
- public HashMap<Short, Link> links; // The links originating from this node
-
- /**
- * Node constructor.
- *
- * @param nodeId the node ID.
- */
- public Node(long nodeId) {
- this.nodeId = nodeId;
- links = new HashMap<Short, Link>();
- }
-
- /**
- * Add a neighbor.
- *
- * A new link to the neighbor will be created.
- *
- * @param neighbor the neighbor to add.
- * @param myPort the local port number for the link to the neighbor.
- * @param neighborPort the neighbor port number for the link.
- */
- public void addNeighbor(Node neighbor, short myPort, short neighborPort) {
- Link link = new Link(this, neighbor, myPort, neighborPort);
- links.put(myPort, link);
- }
-};
-
/**
* A class for implementing Topology Network Service.
*/
-public class TopologyManager implements ITopologyNetService {
-
- /** The logger. */
+public class TopologyManager implements IFloodlightModule,
+ ITopologyNetService {
private static Logger log = LoggerFactory.getLogger(TopologyManager.class);
-
- protected GraphDBOperation op;
+ protected IFloodlightProviderService floodlightProvider;
+
+ protected GraphDBOperation dbHandler;
/**
@@ -113,6 +48,16 @@
}
/**
+ * Constructor for a given database operation handler.
+ *
+ * @param dbHandler the database operation handler to use for the
+ * initialization.
+ */
+ public TopologyManager(GraphDBOperation dbHandler) {
+ this.dbHandler = dbHandler;
+ }
+
+ /**
* Init the module.
*
* @param config the database configuration file to use for
@@ -120,27 +65,93 @@
*/
public void init(String config) {
try {
- op = new GraphDBOperation(config);
+ dbHandler = new GraphDBOperation(config);
} catch (Exception e) {
log.error(e.getMessage());
}
}
/**
- * Close the service. It will close the corresponding database connection.
+ * Shutdown the Topology Manager operation.
*/
- public void close() {
- op.close();
+ public void finalize() {
+ close();
}
/**
- * Set the database operation handler.
- *
- * @param init_op the database operation handler to use for the
- * initialization.
+ * Close the service. It will close the corresponding database connection.
*/
- public void setDbOperationHandler(GraphDBOperation init_op) {
- op = init_op;
+ public void close() {
+ dbHandler.close();
+ }
+
+ /**
+ * Get the collection of offered module services.
+ *
+ * @return the collection of offered module services.
+ */
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(ITopologyNetService.class);
+ return l;
+ }
+
+ /**
+ * Get the collection of implemented services.
+ *
+ * @return the collection of implemented services.
+ */
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService>
+ getServiceImpls() {
+ Map<Class<? extends IFloodlightService>,
+ IFloodlightService> m =
+ new HashMap<Class<? extends IFloodlightService>,
+ IFloodlightService>();
+ m.put(ITopologyNetService.class, this);
+ return m;
+ }
+
+ /**
+ * Get the collection of modules this module depends on.
+ *
+ * @return the collection of modules this module depends on.
+ */
+ @Override
+ public Collection<Class<? extends IFloodlightService>>
+ getModuleDependencies() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IFloodlightProviderService.class);
+ l.add(INetworkGraphService.class);
+ l.add(IDatagridService.class);
+ return l;
+ }
+
+ /**
+ * Initialize the module.
+ *
+ * @param context the module context to use for the initialization.
+ */
+ @Override
+ public void init(FloodlightModuleContext context)
+ throws FloodlightModuleException {
+ floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+
+ String conf = "";
+ this.init(conf);
+ }
+
+ /**
+ * Startup module operation.
+ *
+ * @param context the module context to use for the startup.
+ */
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+
}
/**
@@ -148,248 +159,70 @@
* and return it for fast access during the shortest path
* computation.
*
- * After fetching the state, method @ref getTopoShortestPath()
+ * After fetching the state, method @ref getTopologyShortestPath()
* can be used for fast shortest path computation.
*
* Note: There is certain cost to fetch the state, hence it should
* be used only when there is a large number of shortest path
* computations that need to be done on the same topology.
- * Typically, a single call to @ref prepareShortestPathTopo()
+ * Typically, a single call to @ref newDatabaseTopology()
* should be followed by a large number of calls to
- * method @ref getTopoShortestPath().
- * After the last @ref getTopoShortestPath() call,
- * method @ref dropShortestPathTopo() should be used to release
+ * method @ref getTopologyShortestPath().
+ * After the last @ref getTopologyShortestPath() call,
+ * method @ref dropTopology() should be used to release
* the internal state that is not needed anymore:
*
- * Map<Long, ?> shortestPathTopo;
- * shortestPathTopo = prepareShortestPathTopo();
+ * Topology topology = topologyManager.newDatabaseTopology();
* for (int i = 0; i < 10000; i++) {
- * dataPath = getTopoShortestPath(shortestPathTopo, ...);
+ * dataPath = topologyManager.getTopologyShortestPath(topology, ...);
* ...
* }
- * dropShortestPathTopo(shortestPathTopo);
+ * topologyManager.dropTopology(shortestPathTopo);
*
- * @return the Shortest Path info handler stored in a map.
+ * @return the allocated topology handler.
*/
- public Map<Long, ?> prepareShortestPathTopo() {
- Map<Long, Node> shortestPathTopo = new HashMap<Long, Node>();
+ public Topology newDatabaseTopology() {
+ Topology topology = new Topology();
+ topology.readFromDatabase(dbHandler);
- //
- // Fetch the relevant info from the Switch and Port vertices
- // from the Titan Graph.
- //
- Iterable<ISwitchObject> nodes = op.getActiveSwitches();
- for (ISwitchObject switchObj : nodes) {
- Vertex nodeVertex = switchObj.asVertex();
- //
- // The Switch info
- //
- String nodeDpid = nodeVertex.getProperty("dpid").toString();
- long nodeId = HexString.toLong(nodeDpid);
- Node me = shortestPathTopo.get(nodeId);
- if (me == null) {
- me = new Node(nodeId);
- shortestPathTopo.put(nodeId, me);
- }
-
- //
- // The local Port info
- //
- for (Vertex myPortVertex : nodeVertex.getVertices(Direction.OUT, "on")) {
- // Ignore inactive ports
- if (! myPortVertex.getProperty("state").toString().equals("ACTIVE"))
- continue;
-
- short myPort = 0;
- Object obj = myPortVertex.getProperty("number");
- if (obj instanceof Short) {
- myPort = (Short)obj;
- } else if (obj instanceof Integer) {
- Integer int_nodeId = (Integer)obj;
- myPort = int_nodeId.shortValue();
- }
-
- //
- // The neighbor Port info
- //
- for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
- // Ignore inactive ports
- if (! neighborPortVertex.getProperty("state").toString().equals("ACTIVE"))
- continue;
-
- short neighborPort = 0;
- obj = neighborPortVertex.getProperty("number");
- if (obj instanceof Short) {
- neighborPort = (Short)obj;
- } else if (obj instanceof Integer) {
- Integer int_nodeId = (Integer)obj;
- neighborPort = int_nodeId.shortValue();
- }
- //
- // The neighbor Switch info
- //
- for (Vertex neighborVertex : neighborPortVertex.getVertices(Direction.IN, "on")) {
- // Ignore inactive switches
- String state = neighborVertex.getProperty("state").toString();
- if (! state.equals(SwitchState.ACTIVE.toString()))
- continue;
-
- String neighborDpid = neighborVertex.getProperty("dpid").toString();
- long neighborId = HexString.toLong(neighborDpid);
- Node neighbor = shortestPathTopo.get(neighborId);
- if (neighbor == null) {
- neighbor = new Node(neighborId);
- shortestPathTopo.put(neighborId, neighbor);
- }
- me.addNeighbor(neighbor, myPort, neighborPort);
- }
- }
- }
- }
- op.commit();
-
- return shortestPathTopo;
+ return topology;
}
/**
- * Release the state that was populated by
- * method @ref prepareShortestPathTopo().
+ * Release the topology that was populated by
+ * method @ref newDatabaseTopology().
*
- * See the documentation for method @ref prepareShortestPathTopo()
+ * See the documentation for method @ref newDatabaseTopology()
* for additional information and usage.
*
- * @param shortestPathTopo the Shortest Path info handler to release.
+ * @param topology the topology to release.
*/
- public void dropShortestPathTopo(Map<Long, ?> shortestPathTopo) {
- shortestPathTopo = null;
+ public void dropTopology(Topology topology) {
+ topology = null;
}
/**
* Get the shortest path from a source to a destination by
* using the pre-populated local topology state prepared
- * by method @ref prepareShortestPathTopo().
+ * by method @ref newDatabaseTopology().
*
- * See the documentation for method @ref prepareShortestPathTopo()
+ * See the documentation for method @ref newDatabaseTopology()
* for additional information and usage.
*
- * @param shortestPathTopoHandler the Shortest Path info handler
- * to use.
+ * @param topology the topology handler to use.
* @param src the source in the shortest path computation.
* @param dest the destination in the shortest path computation.
* @return the data path with the computed shortest path if
* found, otherwise null.
*/
- public DataPath getTopoShortestPath(Map<Long, ?> shortestPathTopoHandler,
- SwitchPort src, SwitchPort dest) {
- @SuppressWarnings("unchecked")
- Map<Long, Node> shortestPathTopo = (Map<Long, Node>)shortestPathTopoHandler;
- DataPath result_data_path = new DataPath();
-
- // Initialize the source and destination in the data path to return
- result_data_path.setSrcPort(src);
- result_data_path.setDstPort(dest);
-
- String dpid_src = src.dpid().toString();
- String dpid_dest = dest.dpid().toString();
-
- // Get the source vertex
- Node v_src = shortestPathTopo.get(src.dpid().value());
- if (v_src == null) {
- return null; // Source vertex not found
- }
-
- // Get the destination vertex
- Node v_dest = shortestPathTopo.get(dest.dpid().value());
- if (v_dest == null) {
- return null; // Destination vertex not found
- }
-
- //
- // Test whether we are computing a path from/to the same DPID.
- // If "yes", then just add a single flow entry in the return result.
- //
- if (dpid_src.equals(dpid_dest)) {
- FlowEntry flowEntry = new FlowEntry();
- flowEntry.setDpid(src.dpid());
- flowEntry.setInPort(src.port());
- flowEntry.setOutPort(dest.port());
- result_data_path.flowEntries().add(flowEntry);
- return result_data_path;
- }
-
- //
- // Implement the Shortest Path computation by using Breath First Search
- //
- Set<Node> visitedSet = new HashSet<Node>();
- Queue<Node> processingList = new LinkedList<Node>();
- Map<Node, Node.Link> previousVertexMap = new HashMap<Node, Node.Link>();
- processingList.add(v_src);
- visitedSet.add(v_src);
- Boolean path_found = false;
- while (! processingList.isEmpty()) {
- Node nextVertex = processingList.poll();
- if (v_dest == nextVertex) {
- path_found = true;
- break;
- }
- for (Node.Link link : nextVertex.links.values()) {
- Node child = link.neighbor;
- if (! visitedSet.contains(child)) {
- previousVertexMap.put(child, link);
- visitedSet.add(child);
- processingList.add(child);
- }
- }
- }
- if (! path_found)
- return null; // No path found
-
- // Collect the path as a list of links
- List<Node.Link> resultPath = new LinkedList<Node.Link>();
- Node previousVertex = v_dest;
- while (! v_src.equals(previousVertex)) {
- Node.Link currentLink = previousVertexMap.get(previousVertex);
- resultPath.add(currentLink);
- previousVertex = currentLink.me;
- }
- Collections.reverse(resultPath);
-
- //
- // Loop through the result and prepare the return result
- // as a list of Flow Entries.
- //
- Port inPort = new Port(src.port().value());
- Port outPort;
- for (Node.Link link: resultPath) {
- // Setup the outgoing port, and add the Flow Entry
- outPort = new Port(link.myPort);
-
- FlowEntry flowEntry = new FlowEntry();
- flowEntry.setDpid(new Dpid(link.me.nodeId));
- flowEntry.setInPort(inPort);
- flowEntry.setOutPort(outPort);
- result_data_path.flowEntries().add(flowEntry);
-
- // Setup the next incoming port
- inPort = new Port(link.neighborPort);
- }
- if (resultPath.size() > 0) {
- // Add the last Flow Entry
- FlowEntry flowEntry = new FlowEntry();
- flowEntry.setDpid(new Dpid(dest.dpid().value()));
- flowEntry.setInPort(inPort);
- flowEntry.setOutPort(dest.port());
- result_data_path.flowEntries().add(flowEntry);
- }
-
- if (result_data_path.flowEntries().size() > 0)
- return result_data_path;
-
- return null;
+ public DataPath getTopologyShortestPath(Topology topology,
+ SwitchPort src, SwitchPort dest) {
+ return ShortestPath.getTopologyShortestPath(topology, src, dest);
}
/**
- * Get the shortest path from a source to a destination.
+ * Get the shortest path from a source to a destination by using
+ * the underlying database.
*
* @param src the source in the shortest path computation.
* @param dest the destination in the shortest path computation.
@@ -397,167 +230,8 @@
* found, otherwise null.
*/
@Override
- public DataPath getShortestPath(SwitchPort src, SwitchPort dest) {
- DataPath result_data_path = new DataPath();
-
- // Initialize the source and destination in the data path to return
- result_data_path.setSrcPort(src);
- result_data_path.setDstPort(dest);
-
- String dpid_src = src.dpid().toString();
- String dpid_dest = dest.dpid().toString();
-
- // Get the source and destination switches
- ISwitchObject srcSwitch =
- op.searchActiveSwitch(dpid_src);
- ISwitchObject destSwitch =
- op.searchActiveSwitch(dpid_dest);
- if (srcSwitch == null || destSwitch == null) {
- return null;
- }
-
- //
- // Test whether we are computing a path from/to the same DPID.
- // If "yes", then just add a single flow entry in the return result.
- //
- if (dpid_src.equals(dpid_dest)) {
- FlowEntry flowEntry = new FlowEntry();
- flowEntry.setDpid(src.dpid());
- flowEntry.setInPort(src.port());
- flowEntry.setOutPort(dest.port());
- result_data_path.flowEntries().add(flowEntry);
- op.commit();
- return result_data_path;
- }
-
- Vertex v_src = srcSwitch.asVertex();
- Vertex v_dest = destSwitch.asVertex();
-
- //
- // Implement the Shortest Path computation by using Breath First Search
- //
- Set<Vertex> visitedSet = new HashSet<Vertex>();
- Queue<Vertex> processingList = new LinkedList<Vertex>();
- Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
-
- processingList.add(v_src);
- visitedSet.add(v_src);
- Boolean path_found = false;
- while (! processingList.isEmpty()) {
- Vertex nextVertex = processingList.poll();
- if (v_dest.equals(nextVertex)) {
- path_found = true;
- break;
- }
- for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
- // Ignore inactive ports
- if (! parentPort.getProperty("state").toString().equals("ACTIVE"))
- continue;
-
- for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
- // Ignore inactive ports
- if (! childPort.getProperty("state").toString().equals("ACTIVE"))
- continue;
-
- for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
- // Ignore inactive switches
- String state = child.getProperty("state").toString();
- if (! state.equals(SwitchState.ACTIVE.toString()))
- continue;
-
- if (! visitedSet.contains(child)) {
- previousVertexMap.put(parentPort, nextVertex);
- previousVertexMap.put(childPort, parentPort);
- previousVertexMap.put(child, childPort);
- visitedSet.add(child);
- processingList.add(child);
- }
- }
- }
- }
- }
- if (! path_found)
- return null; // No path found
-
- List<Vertex> resultPath = new LinkedList<Vertex>();
- Vertex previousVertex = v_dest;
- resultPath.add(v_dest);
- while (! v_src.equals(previousVertex)) {
- Vertex currentVertex = previousVertexMap.get(previousVertex);
- resultPath.add(currentVertex);
- previousVertex = currentVertex;
- }
- Collections.reverse(resultPath);
-
-
- //
- // Loop through the result and prepare the return result
- // as a list of Flow Entries.
- //
- long nodeId = 0;
- short portId = 0;
- Port inPort = new Port(src.port().value());
- Port outPort = new Port();
- int idx = 0;
- for (Vertex v: resultPath) {
- String type = v.getProperty("type").toString();
- // System.out.println("type: " + type);
- if (type.equals("port")) {
- //String number = v.getProperty("number").toString();
- // System.out.println("number: " + number);
-
- Object obj = v.getProperty("number");
- // String class_str = obj.getClass().toString();
- if (obj instanceof Short) {
- portId = (Short)obj;
- } else if (obj instanceof Integer) {
- Integer int_nodeId = (Integer)obj;
- portId = int_nodeId.shortValue();
- // int int_nodeId = (Integer)obj;
- // portId = (short)int_nodeId.;
- }
- } else if (type.equals("switch")) {
- String dpid = v.getProperty("dpid").toString();
- nodeId = HexString.toLong(dpid);
-
- // System.out.println("dpid: " + dpid);
- }
- idx++;
- if (idx == 1) {
- continue;
- }
- int mod = idx % 3;
- if (mod == 0) {
- // Setup the incoming port
- inPort = new Port(portId);
- continue;
- }
- if (mod == 2) {
- // Setup the outgoing port, and add the Flow Entry
- outPort = new Port(portId);
-
- FlowEntry flowEntry = new FlowEntry();
- flowEntry.setDpid(new Dpid(nodeId));
- flowEntry.setInPort(inPort);
- flowEntry.setOutPort(outPort);
- result_data_path.flowEntries().add(flowEntry);
- continue;
- }
- }
- if (idx > 0) {
- // Add the last Flow Entry
- FlowEntry flowEntry = new FlowEntry();
- flowEntry.setDpid(new Dpid(nodeId));
- flowEntry.setInPort(inPort);
- flowEntry.setOutPort(dest.port());
- result_data_path.flowEntries().add(flowEntry);
- }
-
- op.commit();
- if (result_data_path.flowEntries().size() > 0)
- return result_data_path;
-
- return null;
+ public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
+ return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
}
/**
@@ -569,7 +243,7 @@
*/
@Override
public Boolean routeExists(SwitchPort src, SwitchPort dest) {
- DataPath dataPath = getShortestPath(src, dest);
+ DataPath dataPath = getDatabaseShortestPath(src, dest);
return (dataPath != null);
}
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
index a730719..1cb39b3 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
@@ -37,8 +37,9 @@
Port dstPort = new Port(Short.parseShort(dstPortStr));
DataPath result =
- topologyNetService.getShortestPath(new SwitchPort(srcDpid, srcPort),
- new SwitchPort(dstDpid, dstPort));
+ topologyNetService.getDatabaseShortestPath(
+ new SwitchPort(srcDpid, srcPort),
+ new SwitchPort(dstDpid, dstPort));
if (result != null) {
return result;
} else {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
index e807b56..7c6597d 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
@@ -105,8 +105,8 @@
* computation.
*
* NOTE: This method assumes the DataPath was created by
- * using FlowManager::getShortestPath() so the inPort and outPort
- * of the Flow Entries are set.
+ * using the TopologyManager shortest path computation, so the inPort
+ * and outPort of the Flow Entries are set.
* NOTE: This method is a temporary solution and will be removed
* in the future.
*
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
index 5a1549b..8a8779b 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
@@ -15,10 +15,12 @@
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
+import net.onrc.onos.datagrid.IDatagridService;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
+import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
import net.onrc.onos.ofcontroller.topology.TopologyManager;
import net.onrc.onos.ofcontroller.util.*;
@@ -38,12 +40,14 @@
/**
* @author Toshio Koide
*/
+@Ignore
@RunWith(PowerMockRunner.class)
-@PrepareForTest({FlowManager.class, GraphDBOperation.class, System.class, Executors.class})
+@PrepareForTest({FlowManager.class, FlowDatabaseOperation.class, GraphDBOperation.class, System.class, Executors.class})
public class FlowManagerTest {
private static FloodlightModuleContext context;
private static IFloodlightProviderService floodlightProvider;
private static TopologyManager topologyManager;
+ private static IDatagridService datagridService;
private static IRestApiService restApi;
private static GraphDBOperation op;
@@ -69,11 +73,14 @@
context = createMock(FloodlightModuleContext.class);
floodlightProvider = createMock(IFloodlightProviderService.class);
topologyManager = createMock(TopologyManager.class);
+ datagridService = createMock(IDatagridService.class);
restApi = createMock(IRestApiService.class);
op = createMock(GraphDBOperation.class);
// setup expectations
expect(context.getServiceImpl(IFloodlightProviderService.class)).andReturn(floodlightProvider);
+ expect(context.getServiceImpl(ITopologyNetService.class)).andReturn(topologyManager);
+ expect(context.getServiceImpl(IDatagridService.class)).andReturn(datagridService);
expect(context.getServiceImpl(IRestApiService.class)).andReturn(restApi);
expectNew(GraphDBOperation.class, new Class<?>[] {String.class}, EasyMock.isA(String.class)).andReturn(op);
expectNew(TopologyManager.class, new Class<?>[] {String.class}, EasyMock.isA(String.class)).andReturn(topologyManager);
@@ -696,7 +703,7 @@
// verify the test
verifyAll();
- assertEquals(2, md.size());
+ assertEquals(4, md.size());
assertTrue(md.contains(IFloodlightProviderService.class));
assertTrue(md.contains(IRestApiService.class));
}
@@ -976,22 +983,4 @@
public final void testRemoveFlowEntrySuccessNormally() {
fail("not yet implemented");
}
-
- /**
- * Test method for {@link FlowManager#installRemoteFlowEntry(FlowPath, FlowEntry)}.
- * The method seems to be not implemented and not used for now.
- */
- @Ignore @Test
- public final void testInstallRemoteFlowEntrySuccessNormally() {
- fail("not yet implemented");
- }
-
- /**
- * Test method for {@link FlowManager#removeRemoteFlowEntry(FlowPath, FlowEntry)}.
- * The method seems to be not implemented and not used for now.
- */
- @Ignore @Test
- public final void testRemoveRemoteFlowEntrySuccessNormally() {
- fail("not yet implemented");
- }
}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
index fbec59e..09d0a00 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
@@ -64,8 +64,7 @@
TestDatabaseManager.populateTestData(titanGraph);
// Prepare the TopologyManager instance
- topologyManager = new TopologyManager();
- topologyManager.setDbOperationHandler(oper);
+ topologyManager = new TopologyManager(oper);
}
/**
@@ -78,12 +77,12 @@
}
/**
- * Test method TopologyManager.getTopoShortestPath()
+ * Test method TopologyManager.getTopologyShortestPath()
*
- * @see net.onrc.onos.ofcontroller.topology.TopologyManager#getTopoShortestPath
+ * @see net.onrc.onos.ofcontroller.topology.TopologyManager#getTopologyShortestPath
*/
@Test
- public void test_getTopoShortestPath() {
+ public void test_getTopologyShortestPath() {
DataPath dataPath = null;
String srcDpidStr = "00:00:00:00:00:00:0a:01";
String dstDpidStr = "00:00:00:00:00:00:0a:06";
@@ -103,11 +102,10 @@
//
// Test a valid Shortest-Path computation
//
- Map<Long, ?> shortestPathTopo =
- topologyManager.prepareShortestPathTopo();
- dataPath = topologyManager.getTopoShortestPath(shortestPathTopo,
- srcSwitchPort,
- dstSwitchPort);
+ Topology topology = topologyManager.newDatabaseTopology();
+ dataPath = topologyManager.getTopologyShortestPath(topology,
+ srcSwitchPort,
+ dstSwitchPort);
assertTrue(dataPath != null);
String dataPathSummaryStr = dataPath.dataPathSummary();
// System.out.println(dataPathSummaryStr);
@@ -134,21 +132,21 @@
String noSuchDpidStr = "ff:ff:00:00:00:00:0a:06";
Dpid noSuchDstDpid = new Dpid(noSuchDpidStr);
SwitchPort noSuchDstSwitchPort = new SwitchPort(noSuchDstDpid, dstPort);
- dataPath = topologyManager.getTopoShortestPath(shortestPathTopo,
- srcSwitchPort,
- noSuchDstSwitchPort);
+ dataPath = topologyManager.getTopologyShortestPath(topology,
+ srcSwitchPort,
+ noSuchDstSwitchPort);
assertTrue(dataPath == null);
- topologyManager.dropShortestPathTopo(shortestPathTopo);
+ topologyManager.dropTopology(topology);
}
/**
- * Test method TopologyManager.getShortestPath()
+ * Test method TopologyManager.getDatabaseShortestPath()
*
- * @see net.onrc.onos.ofcontroller.routing.TopologyManager#getShortestPath
+ * @see net.onrc.onos.ofcontroller.routing.TopologyManager#getDatabaseShortestPath
*/
@Test
- public void test_getShortestPath() {
+ public void test_getDatabaseShortestPath() {
DataPath dataPath = null;
String srcDpidStr = "00:00:00:00:00:00:0a:01";
String dstDpidStr = "00:00:00:00:00:00:0a:06";
@@ -168,8 +166,8 @@
//
// Test a valid Shortest-Path computation
//
- dataPath = topologyManager.getShortestPath(srcSwitchPort,
- dstSwitchPort);
+ dataPath = topologyManager.getDatabaseShortestPath(srcSwitchPort,
+ dstSwitchPort);
assertTrue(dataPath != null);
String dataPathSummaryStr = dataPath.dataPathSummary();
// System.out.println(dataPathSummaryStr);
@@ -197,8 +195,8 @@
Dpid noSuchDstDpid = new Dpid(noSuchDpidStr);
SwitchPort noSuchDstSwitchPort = new SwitchPort(noSuchDstDpid, dstPort);
- dataPath = topologyManager.getShortestPath(srcSwitchPort,
- noSuchDstSwitchPort);
+ dataPath = topologyManager.getDatabaseShortestPath(srcSwitchPort,
+ noSuchDstSwitchPort);
assertTrue(dataPath == null);
}