Merge in refactored FlowManager API which caused confict as I had updated Forwarding recently
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
index a67ce7a..a96f5dc 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
@@ -31,15 +31,11 @@
/**
* 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.
* @return true on success, otherwise false.
*/
- static boolean addFlow(FlowManager flowManager,
- GraphDBOperation dbHandler,
- FlowPath flowPath, FlowId flowId) {
+ static boolean addFlow(GraphDBOperation dbHandler, FlowPath flowPath) {
IFlowPath flowObj = null;
boolean found = false;
try {
@@ -173,32 +169,25 @@
if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE)
continue; // Skip: all Flow Entries were deleted earlier
- if (addFlowEntry(flowManager, dbHandler, flowObj, flowEntry) == null) {
+ if (addFlowEntry(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,
+ static IFlowEntry addFlowEntry(GraphDBOperation dbHandler,
IFlowPath flowObj,
FlowEntry flowEntry) {
// Flow edges
@@ -507,91 +496,6 @@
}
/**
- * 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.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
index feb80e1..47ef3b7 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
@@ -32,19 +32,6 @@
import org.slf4j.LoggerFactory;
/**
- * A class for storing a pair of Flow Path and a Flow Entry.
- */
-class FlowPathEntryPair {
- protected FlowPath flowPath;
- protected FlowEntry flowEntry;
-
- protected FlowPathEntryPair(FlowPath flowPath, FlowEntry flowEntry) {
- this.flowPath = flowPath;
- this.flowEntry = flowEntry;
- }
-}
-
-/**
* Class for FlowPath Maintenance.
* This class listens for FlowEvents to:
* - Maintain a local cache of the Network Topology.
@@ -207,7 +194,7 @@
* Process the events (if any)
*/
private void processEvents() {
- List<FlowPathEntryPair> modifiedFlowEntries;
+ Collection<FlowEntry> modifiedFlowEntries;
if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
flowEntryEvents.isEmpty()) {
@@ -225,17 +212,16 @@
}
// Extract the modified Flow Entries
- modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths);
+ modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
// Assign missing Flow Entry IDs
assignFlowEntryId(modifiedFlowEntries);
//
- // Push the modified Flow Entries to switches, datagrid and database
+ // Push the modified state to the Flow Manager
//
- flowManager.pushModifiedFlowEntriesToSwitches(modifiedFlowEntries);
- flowManager.pushModifiedFlowEntriesToDatagrid(modifiedFlowEntries);
- flowManager.pushModifiedFlowPathsToDatabase(modifiedFlowPaths.values());
+ flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
+ modifiedFlowEntries);
//
// Remove Flow Entries that were deleted
@@ -254,20 +240,20 @@
/**
* Extract the modified Flow Entries.
+ *
+ * @param modifiedFlowPaths the Flow Paths to process.
+ * @return a collection with the modified Flow Entries.
*/
- private List<FlowPathEntryPair> extractModifiedFlowEntries(
- Map<Long, FlowPath> modifiedFlowPaths) {
- List<FlowPathEntryPair> modifiedFlowEntries =
- new LinkedList<FlowPathEntryPair>();
+ private Collection<FlowEntry> extractModifiedFlowEntries(
+ Collection<FlowPath> modifiedFlowPaths) {
+ List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
// Extract only the modified Flow Entries
- for (FlowPath flowPath : modifiedFlowPaths.values()) {
+ for (FlowPath flowPath : modifiedFlowPaths) {
for (FlowEntry flowEntry : flowPath.flowEntries()) {
if (flowEntry.flowEntrySwitchState() ==
FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
- FlowPathEntryPair flowPair =
- new FlowPathEntryPair(flowPath, flowEntry);
- modifiedFlowEntries.add(flowPair);
+ modifiedFlowEntries.add(flowEntry);
}
}
}
@@ -276,8 +262,11 @@
/**
* Assign the Flow Entry ID as needed.
+ *
+ * @param modifiedFlowEnries the collection of Flow Entries that need
+ * Flow Entry ID assigned.
*/
- private void assignFlowEntryId(List<FlowPathEntryPair> modifiedFlowEntries) {
+ private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
if (modifiedFlowEntries.isEmpty())
return;
@@ -286,9 +275,7 @@
//
// Assign the Flow Entry ID only for Flow Entries for my switches
//
- for (FlowPathEntryPair flowPair : modifiedFlowEntries) {
- FlowEntry flowEntry = flowPair.flowEntry;
- // Update the Flow Entries only for my switches
+ for (FlowEntry flowEntry : modifiedFlowEntries) {
IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
if (mySwitch == null)
continue;
@@ -412,7 +399,6 @@
* Process the Flow Entry events.
*/
private void processFlowEntryEvents() {
- FlowPathEntryPair flowPair;
FlowPath flowPath;
FlowEntry updatedFlowEntry;
@@ -431,7 +417,6 @@
flowEntry);
continue;
}
- flowPair = new FlowPathEntryPair(flowPath, updatedFlowEntry);
modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
}
unmatchedFlowEntryAdd = remainingUpdates;
@@ -468,7 +453,6 @@
break;
}
// Add the updated entry to the list of updated Flow Entries
- flowPair = new FlowPathEntryPair(flowPath, updatedFlowEntry);
modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
break;
@@ -488,7 +472,6 @@
// Flow Entry not found: ignore it
break;
}
- flowPair = new FlowPathEntryPair(flowPath, updatedFlowEntry);
modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
break;
}
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 7f43fe9..f4b1f8f 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -4,6 +4,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
@@ -210,11 +211,17 @@
* Add a flow.
*
* @param flowPath the Flow Path to install.
- * @param flowId the return-by-reference Flow ID as assigned internally.
- * @return true on success, otherwise false.
+ * @return the Flow ID on success, otherwise null.
*/
@Override
- public boolean addFlow(FlowPath flowPath, FlowId flowId) {
+ public FlowId addFlow(FlowPath flowPath) {
+
+ // Allocate the Flow ID if necessary
+ if (! flowPath.flowId().isValid()) {
+ long id = getNextFlowEntryId();
+ flowPath.setFlowId(new FlowId(id));
+ }
+
//
// NOTE: We need to explicitly initialize some of the state,
// in case the application didn't do it.
@@ -228,35 +235,11 @@
flowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
}
- if (FlowDatabaseOperation.addFlow(this, dbHandlerApi, flowPath, flowId)) {
+ if (FlowDatabaseOperation.addFlow(dbHandlerApi, flowPath)) {
datagridService.notificationSendFlowAdded(flowPath);
- return true;
+ return flowPath.flowId();
}
- return false;
- }
-
- /**
- * Add a flow entry to the Network MAP.
- *
- * @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.
- */
- private IFlowEntry addFlowEntry(IFlowPath flowObj, FlowEntry flowEntry) {
- return FlowDatabaseOperation.addFlowEntry(this, dbHandlerInner,
- flowObj, flowEntry);
- }
-
- /**
- * Delete a flow entry from the Network MAP.
- *
- * @param flowObj the corresponding Flow Path object for the Flow Entry.
- * @param flowEntry the Flow Entry to delete.
- * @return true on success, otherwise false.
- */
- private boolean deleteFlowEntry(IFlowPath flowObj, FlowEntry flowEntry) {
- return FlowDatabaseOperation.deleteFlowEntry(dbHandlerInner,
- flowObj, flowEntry);
+ return null;
}
/**
@@ -310,33 +293,6 @@
}
/**
- * Get all previously added flows by a specific installer for a given
- * data path endpoints.
- *
- * @param installerId the Caller ID of the installer of the flow to get.
- * @param dataPathEndpoints the data path endpoints of the flow to get.
- * @return the Flow Paths if found, otherwise null.
- */
- @Override
- public ArrayList<FlowPath> getAllFlows(CallerId installerId,
- DataPathEndpoints dataPathEndpoints) {
- return FlowDatabaseOperation.getAllFlows(dbHandlerApi, installerId,
- dataPathEndpoints);
- }
-
- /**
- * Get all installed flows by all installers for given data path endpoints.
- *
- * @param dataPathEndpoints the data path endpoints of the flows to get.
- * @return the Flow Paths if found, otherwise null.
- */
- @Override
- public ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints) {
- return FlowDatabaseOperation.getAllFlows(dbHandlerApi,
- dataPathEndpoints);
- }
-
- /**
* Get summary of all installed flows by all installers in a given range.
*
* @param flowId the Flow ID of the first flow in the flow range to get.
@@ -349,29 +305,6 @@
return FlowDatabaseOperation.getAllFlowsSummary(dbHandlerApi, flowId,
maxFlows);
}
-
- /**
- * Add and maintain a shortest-path flow.
- *
- * NOTE: The Flow Path argument does NOT contain flow entries.
- *
- * @param flowPath the Flow Path with the endpoints and the match
- * conditions to install.
- * @return the added shortest-path flow on success, otherwise null.
- */
- @Override
- public FlowPath addAndMaintainShortestPathFlow(FlowPath flowPath) {
- //
- // Don't do the shortest path computation here.
- // Instead, let the Flow reconciliation thread take care of it.
- //
-
- FlowId flowId = new FlowId();
- if (! addFlow(flowPath, flowId))
- return null;
-
- return (flowPath);
- }
/**
* Get the collection of my switches.
@@ -402,6 +335,63 @@
}
/**
+ * Inform the Flow Manager that a collection of Flow Entries have been
+ * pushed to a switch.
+ *
+ * @param entries the collection of <IOFSwitch, FlowEntry> pairs
+ * that have been pushed.
+ */
+ public void flowEntriesPushedToSwitch(
+ Collection<Pair<IOFSwitch, FlowEntry>> entries) {
+
+ //
+ // Process all entries
+ //
+ for (Pair<IOFSwitch, FlowEntry> entry : entries) {
+ IOFSwitch sw = entry.first;
+ FlowEntry flowEntry = entry.second;
+
+ //
+ // Mark the Flow Entry that it has been pushed to the switch
+ //
+ flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
+
+ //
+ // Write the Flow Entry to the Datagrid
+ //
+ switch (flowEntry.flowEntryUserState()) {
+ case FE_USER_ADD:
+ datagridService.notificationSendFlowEntryAdded(flowEntry);
+ break;
+ case FE_USER_MODIFY:
+ datagridService.notificationSendFlowEntryUpdated(flowEntry);
+ break;
+ case FE_USER_DELETE:
+ datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
+ break;
+ }
+ }
+ }
+
+ /**
+ * Push modified Flow-related state as appropriate.
+ *
+ * @param modifiedFlowPaths the collection of modified Flow Paths.
+ * @param modifiedFlowEntries the collection of modified Flow Entries.
+ */
+ void pushModifiedFlowState(Collection<FlowPath> modifiedFlowPaths,
+ Collection<FlowEntry> modifiedFlowEntries) {
+ //
+ // Push the modified Flow state:
+ // - Flow Entries to switches and the datagrid
+ // - Flow Paths to the database
+ //
+ pushModifiedFlowEntriesToSwitches(modifiedFlowEntries);
+ pushModifiedFlowPathsToDatabase(modifiedFlowPaths);
+ cleanupDeletedFlowEntriesFromDatagrid(modifiedFlowEntries);
+ }
+
+ /**
* Push modified Flow Entries to switches.
*
* NOTE: Only the Flow Entries to switches controlled by this instance
@@ -409,99 +399,88 @@
*
* @param modifiedFlowEntries the collection of modified Flow Entries.
*/
- public void pushModifiedFlowEntriesToSwitches(
- Collection<FlowPathEntryPair> modifiedFlowEntries) {
+ private void pushModifiedFlowEntriesToSwitches(
+ Collection<FlowEntry> modifiedFlowEntries) {
if (modifiedFlowEntries.isEmpty())
return;
+ List<Pair<IOFSwitch, FlowEntry>> entries =
+ new LinkedList<Pair<IOFSwitch, FlowEntry>>();
+
Map<Long, IOFSwitch> mySwitches = getMySwitches();
- for (FlowPathEntryPair flowPair : modifiedFlowEntries) {
- FlowEntry flowEntry = flowPair.flowEntry;
-
+ //
+ // Create a collection of my Flow Entries to push
+ //
+ for (FlowEntry flowEntry : modifiedFlowEntries) {
IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
if (mySwitch == null)
continue;
- log.debug("Pushing Flow Entry To Switch: {}", flowEntry.toString());
-
//
- // Push the Flow Entry into the switch
+ // Assign Flow Entry IDs if missing.
//
- if (! pusher.add(mySwitch, flowEntry)) {
- String logMsg = "Cannot install Flow Entry " +
- flowEntry.flowEntryId() +
- " from Flow Path " + flowEntry.flowId() +
- " on switch " + flowEntry.dpid();
- log.error(logMsg);
- continue;
+ // NOTE: This is an additional safeguard, in case the
+ // mySwitches set has changed (after the Flow Entry IDs
+ // assignments by the caller).
+ //
+ if (! flowEntry.isValidFlowEntryId()) {
+ long id = getNextFlowEntryId();
+ flowEntry.setFlowEntryId(new FlowEntryId(id));
}
- //
- // NOTE: Here we assume that the switch has been
- // successfully updated.
- //
- flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
+ log.debug("Pushing Flow Entry To Switch: {}", flowEntry.toString());
+ entries.add(new Pair<IOFSwitch, FlowEntry>(mySwitch, flowEntry));
}
+
+ pusher.pushFlowEntries(entries);
}
/**
- * Push modified Flow Entries to the datagrid.
+ * Cleanup deleted Flow Entries from the datagrid.
+ *
+ * NOTE: We cleanup only the Flow Entries that are not for our switches.
+ * This is needed to handle the case a switch going down:
+ * It has no Master controller instance, hence no controller instance
+ * will cleanup its flow entries.
+ * This is sub-optimal: we need to elect a controller instance to handle
+ * the cleanup of such orphaned flow entries.
*
* @param modifiedFlowEntries the collection of modified Flow Entries.
*/
- public void pushModifiedFlowEntriesToDatagrid(
- Collection<FlowPathEntryPair> modifiedFlowEntries) {
+ private void cleanupDeletedFlowEntriesFromDatagrid(
+ Collection<FlowEntry> modifiedFlowEntries) {
if (modifiedFlowEntries.isEmpty())
return;
Map<Long, IOFSwitch> mySwitches = getMySwitches();
- for (FlowPathEntryPair flowPair : modifiedFlowEntries) {
- FlowEntry flowEntry = flowPair.flowEntry;
-
+ for (FlowEntry flowEntry : modifiedFlowEntries) {
+ //
+ // Process only Flow Entries that should be deleted and have
+ // a valid Flow Entry ID.
+ //
if (! flowEntry.isValidFlowEntryId())
continue;
-
- IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
-
- //
- // TODO: For now Flow Entries are removed by all instances,
- // even if this Flow Entry is not for our switches.
- //
- // This is needed to handle the case a switch going down:
- // it has no Master controller instance, hence no
- // controller instance will cleanup its flow entries.
- // This is sub-optimal: we need to elect a controller
- // instance to handle the cleanup of such orphaned flow
- // entries.
- //
- if (mySwitch == null) {
- if (flowEntry.flowEntryUserState() !=
- FlowEntryUserState.FE_USER_DELETE) {
- continue;
- }
+ if (flowEntry.flowEntryUserState() !=
+ FlowEntryUserState.FE_USER_DELETE) {
+ continue;
}
- log.debug("Pushing Flow Entry To Datagrid: {}", flowEntry.toString());
+ //
+ // NOTE: The deletion of Flow Entries for my switches is handled
+ // elsewhere.
+ //
+ IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
+ if (mySwitch != null)
+ continue;
+
+ log.debug("Pushing cleanup of Flow Entry To Datagrid: {}", flowEntry.toString());
+
//
// Write the Flow Entry to the Datagrid
//
- switch (flowEntry.flowEntryUserState()) {
- case FE_USER_ADD:
- if (mySwitch == null)
- break; // Install only flow entries for my switches
- datagridService.notificationSendFlowEntryAdded(flowEntry);
- break;
- case FE_USER_MODIFY:
- if (mySwitch == null)
- break; // Install only flow entries for my switches
- datagridService.notificationSendFlowEntryUpdated(flowEntry);
- break;
- case FE_USER_DELETE:
- datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
- break;
- }
+ datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
}
}
@@ -556,7 +535,7 @@
*
* @param modifiedFlowPaths the collection of Flow Paths to push.
*/
- void pushModifiedFlowPathsToDatabase(
+ private void pushModifiedFlowPathsToDatabase(
Collection<FlowPath> modifiedFlowPaths) {
//
// We only add the Flow Paths to the Database Queue.
@@ -579,8 +558,6 @@
if (modifiedFlowPaths.isEmpty())
return;
- FlowId dummyFlowId = new FlowId();
-
Map<Long, IOFSwitch> mySwitches = getMySwitches();
for (FlowPath flowPath : modifiedFlowPaths) {
@@ -594,6 +571,27 @@
continue;
//
+ // Delete the Flow Path from the Network Map
+ //
+ if (flowPath.flowPathUserState() ==
+ FlowPathUserState.FP_USER_DELETE) {
+ log.debug("Deleting Flow Path From Database: {}",
+ flowPath.toString());
+
+ try {
+ if (! FlowDatabaseOperation.deleteFlow(
+ dbHandlerInner,
+ flowPath.flowId())) {
+ log.error("Cannot delete Flow Path {} from Network Map",
+ flowPath.flowId());
+ }
+ } catch (Exception e) {
+ log.error("Exception deleting Flow Path from Network MAP: {}", e);
+ }
+ continue;
+ }
+
+ //
// Test whether all Flow Entries are valid
//
boolean allValid = true;
@@ -616,8 +614,7 @@
// Write the Flow Path to the Network Map
//
try {
- if (! FlowDatabaseOperation.addFlow(this, dbHandlerInner,
- flowPath, dummyFlowId)) {
+ if (! FlowDatabaseOperation.addFlow(dbHandlerInner, flowPath)) {
String logMsg = "Cannot write to Network Map Flow Path " +
flowPath.flowId();
log.error(logMsg);
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 8d2b797..a25602d 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
@@ -1,15 +1,18 @@
package net.onrc.onos.ofcontroller.flowmanager;
import java.util.ArrayList;
+import java.util.Collection;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.onrc.onos.ofcontroller.topology.Topology;
import net.onrc.onos.ofcontroller.util.CallerId;
import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
import net.onrc.onos.ofcontroller.util.FlowEntryId;
import net.onrc.onos.ofcontroller.util.FlowId;
import net.onrc.onos.ofcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.util.Pair;
/**
* Interface for providing Flow Service to other modules.
@@ -18,14 +21,10 @@
/**
* Add a flow.
*
- * Internally, ONOS will automatically register the installer for
- * receiving Flow Path Notifications for that path.
- *
* @param flowPath the Flow Path to install.
- * @param flowId the return-by-reference Flow ID as assigned internally.
- * @return true on success, otherwise false.
+ * @return the Flow ID on success, otherwise null.
*/
- boolean addFlow(FlowPath flowPath, FlowId flowId);
+ FlowId addFlow(FlowPath flowPath);
/**
* Delete all previously added flows.
@@ -58,25 +57,6 @@
ArrayList<FlowPath> getAllFlows();
/**
- * Get all previously added flows by a specific installer for a given
- * data path endpoints.
- *
- * @param installerId the Caller ID of the installer of the flow to get.
- * @param dataPathEndpoints the data path endpoints of the flow to get.
- * @return the Flow Paths if found, otherwise null.
- */
- ArrayList<FlowPath> getAllFlows(CallerId installerId,
- DataPathEndpoints dataPathEndpoints);
-
- /**
- * Get all installed flows by all installers for given data path endpoints.
- *
- * @param dataPathEndpoints the data path endpoints of the flows to get.
- * @return the Flow Paths if found, otherwise null.
- */
- ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints);
-
- /**
* Get summary of all installed flows by all installers.
*
* @param flowId starting flow Id of the range
@@ -84,21 +64,6 @@
* @return the Flow Paths if found, otherwise null.
*/
ArrayList<FlowPath> getAllFlowsSummary(FlowId flowId, int maxFlows);
-
- /**
- * Add and maintain a shortest-path flow.
- *
- * NOTE: The Flow Path argument does NOT contain all flow entries.
- * Instead, it contains a single dummy flow entry that is used to
- * store the matching condition(s).
- * That entry is replaced by the appropriate entries from the
- * internally performed shortest-path computation.
- *
- * @param flowPath the Flow Path with the endpoints and the match
- * conditions to install.
- * @return the added shortest-path flow on success, otherwise null.
- */
- FlowPath addAndMaintainShortestPathFlow(FlowPath flowPath);
/**
* Get the network topology.
@@ -106,7 +71,7 @@
* @return the network topology.
*/
Topology getTopology();
-
+
/**
* Get a globally unique flow ID from the flow service.
* NOTE: Not currently guaranteed to be globally unique.
@@ -122,4 +87,14 @@
* @param flowEntryId the Flow Entry ID of the expired Flow Entry.
*/
public void flowEntryOnSwitchExpired(IOFSwitch sw, FlowEntryId flowEntryId);
+
+ /**
+ * Inform the Flow Manager that a collection of Flow Entries have been
+ * pushed to a switch.
+ *
+ * @param entries the collection of <IOFSwitch, FlowEntry> pairs
+ * that have been pushed.
+ */
+ public void flowEntriesPushedToSwitch(
+ Collection<Pair<IOFSwitch, FlowEntry>> entries);
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
index 0926f91..9afaaec 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
@@ -64,9 +64,9 @@
// Process the request
if (flowPath != null) {
- if (flowService.addFlow(flowPath, result) != true) {
- result = new FlowId(); // Error: Return empty Flow Id
- }
+ FlowId addedFlowId = flowService.addFlow(flowPath);
+ if (addedFlowId != null)
+ result = addedFlowId;
}
return result;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddShortestPathFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddShortestPathFlowResource.java
index 7a4e88c..4d03623 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddShortestPathFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddShortestPathFlowResource.java
@@ -64,13 +64,9 @@
// Process the request
if (flowPath != null) {
- FlowPath addedFlowPath =
- flowService.addAndMaintainShortestPathFlow(flowPath);
- if (addedFlowPath == null) {
- result = new FlowId(); // Error: Return empty Flow Id
- } else {
- result = addedFlowPath.flowId();
- }
+ FlowId addedFlowId = flowService.addFlow(flowPath);
+ if (addedFlowId != null)
+ result = addedFlowId;
}
return result;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
index 81d26dd..c358263 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
@@ -20,8 +20,6 @@
router.attach("/add-shortest-path/json", AddShortestPathFlowResource.class);
router.attach("/delete/{flow-id}/json", DeleteFlowResource.class);
router.attach("/get/{flow-id}/json", GetFlowByIdResource.class);
- router.attach("/getall-by-installer-id/{installer-id}/{src-dpid}/{src-port}/{dst-dpid}/{dst-port}/json", GetAllFlowsByInstallerIdResource.class);
- router.attach("/getall-by-endpoints/{src-dpid}/{src-port}/{dst-dpid}/{dst-port}/json", GetAllFlowsByEndpointsResource.class);
router.attach("/getall/json", GetAllFlowsResource.class);
router.attach("/getsummary/{flow-id}/{max-flows}/json", GetSummaryFlowsResource.class);
return router;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByEndpointsResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByEndpointsResource.java
deleted file mode 100644
index 1ac98c0..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByEndpointsResource.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import java.util.ArrayList;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager REST API implementation: Get all Flow state for given
- * source and destination switches and ports.
- *
- * The "{src-dpid}" request attribute value is the source DPID of the flows to
- * get.
- * The "{src-port}" request attribute value is the source port of the flows to
- * get.
- * The "{dst-dpid}" request attribute value is the destination DPID of the
- * flows to get.
- * The "{dst-port}" request attribute value is the destination port of the
- * flows to get.
- *
- * GET /wm/flow/getall-by-endpoints/{src-dpid}/{src-port}/{dst-dpid}/{dst-port}/json"
- */
-public class GetAllFlowsByEndpointsResource extends ServerResource {
- protected final static Logger log = LoggerFactory.getLogger(GetAllFlowsByEndpointsResource.class);
-
- /**
- * Implement the API.
- *
- * @return the collection of Flow states if any found, otherwise null.
- */
- @Get("json")
- public ArrayList<FlowPath> retrieve() {
- ArrayList<FlowPath> result = null;
-
- IFlowService flowService =
- (IFlowService)getContext().getAttributes().
- get(IFlowService.class.getCanonicalName());
-
- if (flowService == null) {
- log.debug("ONOS Flow Service not found");
- return result;
- }
-
- // Extract the arguments
- String srcDpidStr = (String) getRequestAttributes().get("src-dpid");
- String srcPortStr = (String) getRequestAttributes().get("src-port");
- String dstDpidStr = (String) getRequestAttributes().get("dst-dpid");
- String dstPortStr = (String) getRequestAttributes().get("dst-port");
-
- log.debug("Get All Flows Endpoints: " + srcDpidStr + "--" +
- srcPortStr + "--" + dstDpidStr + "--" + dstPortStr);
-
- Dpid srcDpid = new Dpid(srcDpidStr);
- Port srcPort = new Port(Short.parseShort(srcPortStr));
- Dpid dstDpid = new Dpid(dstDpidStr);
- Port dstPort = new Port(Short.parseShort(dstPortStr));
- SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
- SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
- DataPathEndpoints dataPathEndpoints =
- new DataPathEndpoints(srcSwitchPort, dstSwitchPort);
-
- result = flowService.getAllFlows(dataPathEndpoints);
-
- return result;
- }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByInstallerIdResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByInstallerIdResource.java
deleted file mode 100644
index 870548e..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByInstallerIdResource.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import java.util.ArrayList;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.util.CallerId;
-import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager REST API implementation: Get all Flow state for a given
- * Installer ID and given source and destination switches and ports.
- *
- * The "{installer-id}" request attribute value is the Installer ID of the
- * flows to get.
- * The "{src-dpid}" request attribute value is the source DPID of the flows to
- * get.
- * The "{src-port}" request attribute value is the source port of the flows to
- * get.
- * The "{dst-dpid}" request attribute value is the destination DPID of the
- * flows to get.
- * The "{dst-port}" request attribute value is the destination port of the
- * flows to get.
- *
- * GET /wm/flow/getall-by-installer-id/{installer-id}/{src-dpid}/{src-port}/{dst-dpid}/{dst-port}/json"
- */
-public class GetAllFlowsByInstallerIdResource extends ServerResource {
- protected final static Logger log = LoggerFactory.getLogger(GetAllFlowsByInstallerIdResource.class);
-
- /**
- * Implement the API.
- *
- * @return the collection of Flow states if any found, otherwise null.
- */
- @Get("json")
- public ArrayList<FlowPath> retrieve() {
- ArrayList<FlowPath> result = null;
-
- IFlowService flowService =
- (IFlowService)getContext().getAttributes().
- get(IFlowService.class.getCanonicalName());
-
- if (flowService == null) {
- log.debug("ONOS Flow Service not found");
- return result;
- }
-
- // Extract the arguments
- String installerIdStr = (String) getRequestAttributes().get("installer-id");
- String srcDpidStr = (String) getRequestAttributes().get("src-dpid");
- String srcPortStr = (String) getRequestAttributes().get("src-port");
- String dstDpidStr = (String) getRequestAttributes().get("dst-dpid");
- String dstPortStr = (String) getRequestAttributes().get("dst-port");
-
- log.debug("Get All Flow By Installer: " + installerIdStr +
- " Endpoints: " +
- srcDpidStr + "--" + srcPortStr + "--" +
- dstDpidStr + "--" + dstPortStr);
-
- CallerId installerId = new CallerId(installerIdStr);
- Dpid srcDpid = new Dpid(srcDpidStr);
- Port srcPort = new Port(Short.parseShort(srcPortStr));
- Dpid dstDpid = new Dpid(dstDpidStr);
- Port dstPort = new Port(Short.parseShort(dstPortStr));
- SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
- SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
- DataPathEndpoints dataPathEndpoints =
- new DataPathEndpoints(srcSwitchPort, dstSwitchPort);
-
- result = flowService.getAllFlows(installerId, dataPathEndpoints);
-
- return result;
- }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
index 438f478..c3c7107 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
@@ -3,9 +3,11 @@
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -27,6 +29,7 @@
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.floodlightcontroller.util.MACAddress;
import net.floodlightcontroller.util.OFMessageDamper;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
import net.onrc.onos.ofcontroller.util.FlowEntryAction;
import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
import net.onrc.onos.ofcontroller.util.FlowEntry;
@@ -35,6 +38,7 @@
import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
import net.onrc.onos.ofcontroller.util.IPv4Net;
+import net.onrc.onos.ofcontroller.util.Pair;
import net.onrc.onos.ofcontroller.util.Port;
/**
@@ -51,6 +55,7 @@
*/
public class FlowPusher implements IFlowPusherService, IOFMessageListener {
private final static Logger log = LoggerFactory.getLogger(FlowPusher.class);
+ protected volatile IFlowService flowManager;
// NOTE: Below are moved from FlowManager.
// TODO: Values copied from elsewhere (class LearningSwitch).
@@ -267,6 +272,7 @@
this.threadPool = modContext.getServiceImpl(IThreadPoolService.class);
IFloodlightProviderService flservice = modContext.getServiceImpl(IFloodlightProviderService.class);
flservice.addOFMessageListener(OFType.BARRIER_REPLY, this);
+ flowManager = modContext.getServiceImpl(IFlowService.class);
if (damper != null) {
messageDamper = damper;
@@ -443,9 +449,46 @@
return true;
}
-
+
@Override
- public boolean add(IOFSwitch sw, FlowEntry flowEntry) {
+ public void pushFlowEntries(
+ Collection<Pair<IOFSwitch, FlowEntry>> entries) {
+
+ List<Pair<IOFSwitch, FlowEntry>> pushedEntries =
+ new LinkedList<Pair<IOFSwitch, FlowEntry>>();
+
+ for (Pair<IOFSwitch, FlowEntry> entry : entries) {
+ if (add(entry.first, entry.second)) {
+ pushedEntries.add(entry);
+ }
+ }
+
+ //
+ // 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.
+ // Only after inform the Flow Manager that the entry is pushed.
+ //
+ flowManager.flowEntriesPushedToSwitch(pushedEntries);
+ }
+
+ @Override
+ public void pushFlowEntry(IOFSwitch sw, FlowEntry flowEntry) {
+ Collection<Pair<IOFSwitch, FlowEntry>> entries =
+ new LinkedList<Pair<IOFSwitch, FlowEntry>>();
+
+ entries.add(new Pair<IOFSwitch, FlowEntry>(sw, flowEntry));
+ pushFlowEntries(entries);
+ }
+
+ /**
+ * Create a message from FlowEntry and add it to the queue of the switch.
+ * @param sw Switch to which message is pushed.
+ * @param flowEntry FlowEntry object used for creating message.
+ * @return true if message is successfully added to a queue.
+ */
+ private boolean add(IOFSwitch sw, FlowEntry flowEntry) {
//
// Create the OpenFlow Flow Modification Entry to push
//
@@ -709,17 +752,7 @@
+ matchSrcMac + " dstMac: " + matchDstMac + " inPort: "
+ matchInPort + " outPort: " + actionOutputPort);
- //
- // 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.
- //
-
- return add(sw,fm);
+ return add(sw, fm);
}
@Override
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
index c357e7c..7d5527b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
@@ -246,7 +246,7 @@
return;
}
- pusher.add(sw, flowEntry);
+ pusher.pushFlowEntry(sw, flowEntry);
}
/**
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowPusherService.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowPusherService.java
index 2f550a7..6bf20d9 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowPusherService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/IFlowPusherService.java
@@ -1,5 +1,7 @@
package net.onrc.onos.ofcontroller.flowprogrammer;
+import java.util.Collection;
+
import org.openflow.protocol.OFBarrierReply;
import org.openflow.protocol.OFMessage;
@@ -7,6 +9,7 @@
import net.floodlightcontroller.core.internal.OFMessageFuture;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.Pair;
/**
* FlowPusherService is a service to send message to switches in proper rate.
@@ -47,6 +50,9 @@
/**
* Add a message to the queue of the switch.
+ *
+ * Note: Notification is NOT delivered for the pushed message.
+ *
* @param sw Switch to which message is pushed.
* @param msg Message object to be added.
* @return true if message is successfully added to a queue.
@@ -54,12 +60,28 @@
boolean add(IOFSwitch sw, OFMessage msg);
/**
- * Create a message from FlowEntry and add it to the queue of the switch.
+ * Push a collection of Flow Entries to the corresponding switches.
+ *
+ * Note: Notification is delivered for the Flow Entries that
+ * are pushed successfully.
+ *
+ * @param entries the collection of <IOFSwitch, FlowEntry> pairs
+ * to push.
+ */
+ void pushFlowEntries(Collection<Pair<IOFSwitch, FlowEntry>> entries);
+
+ /**
+ * Create a message from FlowEntry and add it to the queue of the
+ * switch.
+ *
+ * Note: Notification is delivered for the Flow Entries that
+ * are pushed successfully.
+ *
* @param sw Switch to which message is pushed.
* @param flowEntry FlowEntry object used for creating message.
* @return true if message is successfully added to a queue.
*/
- boolean add(IOFSwitch sw, FlowEntry flowEntry);
+ void pushFlowEntry(IOFSwitch sw, FlowEntry flowEntry);
/**
* Set sending rate to a switch.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoInterruptResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoInterruptResource.java
new file mode 100644
index 0000000..3c2920d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoInterruptResource.java
@@ -0,0 +1,44 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+
+/**
+ * FlowProgrammer REST API implementation: Interrupt synchronization to a switch.
+ *
+ * GET /wm/fprog/synchronizer/interrupt/{dpid}/json"
+ */
+public class DoInterruptResource extends SynchronizerResource {
+
+ /**
+ * Implement the API.
+ *
+ * @return true if succeeded, false if failed.
+ */
+ @Get("json")
+ public boolean retrieve() {
+ if (! init()) {
+ return false;
+ }
+
+ long dpid;
+ try {
+ dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+ } catch (NumberFormatException e) {
+ log.error("Invalid number format");
+ return false;
+ }
+
+ IOFSwitch sw = provider.getSwitches().get(dpid);
+ if (sw == null) {
+ log.error("Invalid dpid");
+ return false;
+ }
+
+ synchronizer.interrupt(sw);
+
+ return true;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoSynchronizeResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoSynchronizeResource.java
new file mode 100644
index 0000000..dc8d431
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoSynchronizeResource.java
@@ -0,0 +1,44 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+
+/**
+ * FlowProgrammer REST API implementation: Begin synchronization to a switch.
+ *
+ * GET /wm/fprog/synchronizer/sync/{dpid}/json"
+ */
+public class DoSynchronizeResource extends SynchronizerResource {
+ /**
+ * Implement the API.
+ *
+ * @return true if succeeded, false if failed.
+ */
+ @Get("json")
+ public boolean retrieve() {
+ if (! init()) {
+ return false;
+ }
+
+ long dpid;
+ try {
+ dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+ } catch (NumberFormatException e) {
+ log.error("Invalid number format");
+ return false;
+ }
+
+ IOFSwitch sw = provider.getSwitches().get(dpid);
+ if (sw == null) {
+ log.error("Invalid dpid");
+ return false;
+ }
+
+ synchronizer.synchronize(sw);
+
+ return true;
+ }
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
index 00d7fc9..22450f7 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
@@ -15,6 +15,8 @@
router.attach("/pusher/suspend/{dpid}/json", SuspendPusherResource.class);
router.attach("/pusher/resume/{dpid}/json", ResumePusherResource.class);
router.attach("/pusher/barrier/{dpid}/json", SendBarrierResource.class);
+ router.attach("/synchronizer/sync/{dpid}/json", DoSynchronizeResource.class);
+ router.attach("/synchronizer/interrupt/{dpid}/json", DoInterruptResource.class);
return router;
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SynchronizerResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SynchronizerResource.java
new file mode 100644
index 0000000..12bf8f3
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SynchronizerResource.java
@@ -0,0 +1,35 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.onrc.onos.ofcontroller.flowprogrammer.IFlowSyncService;
+
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SynchronizerResource extends ServerResource {
+ protected final static Logger log = LoggerFactory.getLogger(SynchronizerResource.class);
+
+ protected IFloodlightProviderService provider;
+ protected IFlowSyncService synchronizer;
+
+ protected boolean init() {
+ provider = (IFloodlightProviderService)
+ getContext().getAttributes().
+ get(IFloodlightProviderService.class.getCanonicalName());
+ if (provider == null) {
+ log.debug("ONOS FloodlightProvider not found");
+ return false;
+ }
+
+ synchronizer = (IFlowSyncService)
+ getContext().getAttributes().
+ get(IFlowSyncService.class.getCanonicalName());
+ if (synchronizer == null) {
+ log.debug("ONOS FlowSyncService not found");
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
index ea6e384..b6dffd8 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
@@ -186,10 +186,11 @@
CallerId callerId = new CallerId("Forwarding");
- FlowId flowId = new FlowId(flowService.getNextFlowEntryId());
+ //FlowId flowId = new FlowId(flowService.getNextFlowEntryId());
FlowPath flowPath = new FlowPath();
- flowPath.setFlowId(flowId);
+ //flowPath.setFlowId(flowId);
flowPath.setInstallerId(callerId);
+
flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
flowPath.setFlowEntryMatch(new FlowEntryMatch());
@@ -199,8 +200,9 @@
// forwarding other stuff like ARP.
flowPath.flowEntryMatch().enableEthernetFrameType(Ethernet.TYPE_IPv4);
flowPath.setDataPath(dataPath);
-
- flowService.addFlow(flowPath, flowId);
+
+ FlowId flowId = flowService.addFlow(flowPath);
+ //flowService.addFlow(flowPath, flowId);
DataPath reverseDataPath = new DataPath();
@@ -208,10 +210,10 @@
reverseDataPath.setSrcPort(dstSwitchPort);
reverseDataPath.setDstPort(srcSwitchPort);
- FlowId reverseFlowId = new FlowId(flowService.getNextFlowEntryId());
+ //FlowId reverseFlowId = new FlowId(flowService.getNextFlowEntryId());
// TODO implement copy constructor for FlowPath
FlowPath reverseFlowPath = new FlowPath();
- reverseFlowPath.setFlowId(reverseFlowId);
+ //reverseFlowPath.setFlowId(reverseFlowId);
reverseFlowPath.setInstallerId(callerId);
reverseFlowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
reverseFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
@@ -224,9 +226,9 @@
reverseFlowPath.dataPath().srcPort().dpid().toString();
// TODO what happens if no path exists?
- flowService.addFlow(reverseFlowPath, reverseFlowId);
+ //flowService.addFlow(reverseFlowPath, reverseFlowId);
+ FlowId reverseFlowId = flowService.addFlow(reverseFlowPath);
-
Port outPort = shortestPath.flowEntries().get(0).outPort();
forwardPacket(pi, sw, outPort.value());
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/Pair.java b/src/main/java/net/onrc/onos/ofcontroller/util/Pair.java
new file mode 100644
index 0000000..2245758
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/Pair.java
@@ -0,0 +1,20 @@
+package net.onrc.onos.ofcontroller.util;
+
+/**
+ * A generic class representing a pair of two values.
+ */
+public class Pair<F, S> {
+ public F first; // The first value in the pair
+ public S second; // The second value in the pair
+
+ /**
+ * Constructor for a pair of two values.
+ *
+ * @param first the first value in the pair.
+ * @param second the second value in the pair.
+ */
+ public Pair(F first, S second) {
+ this.first = first;
+ this.second = second;
+ }
+}