Update rerouting features
- add REROUTE_REQ state to Intent class
- add static methods to PathIntent class to create IDs
- add getPathIntentId() to ShortestPathIntent class to retrieve low-level intent
- add mapping of inserting or replacing high level ids to lower level ids.
- change high level intent state to REROUTE_REQ if the state was INST_ACK and the intent was requested rerouting
Change-Id: I50970a0255e2b19451aaedb7dc3c19015031e5d0
diff --git a/src/main/java/net/onrc/onos/intent/ErrorIntent.java b/src/main/java/net/onrc/onos/intent/ErrorIntent.java
index 3365350..27daaa3 100644
--- a/src/main/java/net/onrc/onos/intent/ErrorIntent.java
+++ b/src/main/java/net/onrc/onos/intent/ErrorIntent.java
@@ -22,7 +22,7 @@
}
public ErrorIntent(ErrorType errorType, String message, Intent parentIntent) {
- this.id = parentIntent.getId();
+ super(parentIntent.getId());
this.errorType = errorType;
this.message = message;
this.parentIntent = parentIntent;
diff --git a/src/main/java/net/onrc/onos/intent/Intent.java b/src/main/java/net/onrc/onos/intent/Intent.java
index 20088bd..9a40325 100644
--- a/src/main/java/net/onrc/onos/intent/Intent.java
+++ b/src/main/java/net/onrc/onos/intent/Intent.java
@@ -12,10 +12,11 @@
DEL_REQ,
DEL_PENDING,
DEL_ACK,
+ REROUTE_REQ,
}
- protected String id;
- protected IntentState state = IntentState.CREATED;
+ private String id;
+ private IntentState state = IntentState.CREATED;
/**
* Default constructor for Kryo deserialization
@@ -48,7 +49,22 @@
@Override
public int hashCode() {
- return id.hashCode();
+ return (id == null) ? 0 : id.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if ((obj == null) || (getClass() != obj.getClass()))
+ return false;
+ Intent other = (Intent) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
}
@Override
diff --git a/src/main/java/net/onrc/onos/intent/IntentOperation.java b/src/main/java/net/onrc/onos/intent/IntentOperation.java
index 93a9f88..57d2667 100644
--- a/src/main/java/net/onrc/onos/intent/IntentOperation.java
+++ b/src/main/java/net/onrc/onos/intent/IntentOperation.java
@@ -23,16 +23,16 @@
ERROR,
}
- public IntentOperation() {}
+ public Operator operator;
+ public Intent intent;
+
+ protected IntentOperation() {}
public IntentOperation(Operator operator, Intent intent) {
this.operator = operator;
this.intent = intent;
}
- public Operator operator;
- public Intent intent;
-
@Override
public String toString() {
return operator.toString() + ", (" + intent.toString() + ")";
diff --git a/src/main/java/net/onrc/onos/intent/PathIntent.java b/src/main/java/net/onrc/onos/intent/PathIntent.java
index e000828..28e2dd3 100644
--- a/src/main/java/net/onrc/onos/intent/PathIntent.java
+++ b/src/main/java/net/onrc/onos/intent/PathIntent.java
@@ -10,6 +10,15 @@
protected double bandwidth;
protected Intent parentIntent;
+ public static String createFirstId(String parentId) {
+ return String.format("pi%s___0", parentId);
+ }
+
+ public static String createNextId(String currentId) {
+ String parts[] = currentId.split("___");
+ return String.format("%s___%d", parts[0], Long.valueOf(parts[1])+1);
+ }
+
/**
* Default constructor for Kryo deserialization
*/
diff --git a/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java b/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java
index 4198b18..5b14fce 100644
--- a/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java
+++ b/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java
@@ -13,6 +13,7 @@
protected long dstSwitchDpid;
protected long dstPortNumber;
protected long dstMacAddress;
+ protected String pathIntentId = null;
/**
* Default constructor for Kryo deserialization
@@ -56,10 +57,18 @@
return dstMacAddress;
}
+ public void setPathIntent(PathIntent pathIntent) {
+ pathIntentId = pathIntent.getId();
+ }
+
+ public String getPathIntentId() {
+ return pathIntentId;
+ }
+
@Override
public String toString() {
return String.format("id:%s, state:%s, srcDpid:%s, srcPort:%d, srcMac:%s, dstDpid:%s, dstPort:%d, dstMac:%s",
- getId(), state,
+ getId(), getState(),
new Dpid(srcSwitchDpid), srcPortNumber, MACAddress.valueOf(srcMacAddress),
new Dpid(dstSwitchDpid), dstPortNumber, MACAddress.valueOf(dstMacAddress));
}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
index 201e97d..043a006 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
@@ -8,6 +8,7 @@
import net.onrc.onos.intent.ErrorIntent;
import net.onrc.onos.intent.ErrorIntent.ErrorType;
import net.onrc.onos.intent.Intent;
+import net.onrc.onos.intent.Intent.IntentState;
import net.onrc.onos.intent.IntentOperation;
import net.onrc.onos.intent.IntentOperation.Operator;
import net.onrc.onos.intent.IntentOperationList;
@@ -63,13 +64,13 @@
pathIntentOpList.add(Operator.ERROR, new ErrorIntent(
ErrorType.SWITCH_NOT_FOUND,
"Switch not found.",
- intentOp.intent));
+ spIntent));
continue;
}
double bandwidth = 0.0;
ConstrainedBFSTree tree = null;
- if (intentOp.intent instanceof ConstrainedShortestPathIntent) {
+ if (spIntent instanceof ConstrainedShortestPathIntent) {
bandwidth = ((ConstrainedShortestPathIntent) intentOp.intent).getBandwidth();
tree = new ConstrainedBFSTree(srcSwitch, pathIntents, bandwidth);
}
@@ -82,18 +83,36 @@
}
Path path = tree.getPath(dstSwitch);
if (path == null) {
- log.error("Path not found: {}", intentOp.intent.toString());
+ log.error("Path not found: {}", spIntent.toString());
pathIntentOpList.add(Operator.ERROR, new ErrorIntent(
ErrorType.PATH_NOT_FOUND,
"Path not found.",
- intentOp.intent));
+ spIntent));
continue;
}
- PathIntent pathIntent = new PathIntent("pi" + intentOp.intent.getId(), path, bandwidth, intentOp.intent);
+
+ // generate new path-intent ID
+ String oldPathIntentId = spIntent.getPathIntentId();
+ String newPathIntentId;
+ if (oldPathIntentId == null)
+ newPathIntentId = PathIntent.createFirstId(spIntent.getId());
+ else {
+ newPathIntentId = PathIntent.createNextId(oldPathIntentId);
+
+ // Request removal of low-level intent if it exists.
+ pathIntentOpList.add(Operator.REMOVE, new Intent(oldPathIntentId));
+ }
+
+ // create new path-intent
+ PathIntent pathIntent = new PathIntent(newPathIntentId, path, bandwidth, spIntent);
+ pathIntent.setState(IntentState.INST_REQ);
+ spIntent.setPathIntent(pathIntent);
pathIntentOpList.add(Operator.ADD, pathIntent);
+
break;
case REMOVE:
- pathIntentOpList.add(Operator.REMOVE, new Intent("pi" + intentOp.intent.getId()));
+ pathIntentOpList.add(Operator.REMOVE, new Intent(
+ ((ShortestPathIntent) intentOp.intent).getPathIntentId()));
break;
case ERROR:
// just ignore
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
index 6bdca51..b5521e2 100755
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
@@ -13,7 +13,6 @@
import net.floodlightcontroller.core.module.IFloodlightService;
import net.onrc.onos.datagrid.IDatagridService;
import net.onrc.onos.datagrid.IEventChannel;
-import net.onrc.onos.intent.Intent;
import net.onrc.onos.intent.Intent.IntentState;
import net.onrc.onos.intent.IntentMap;
import net.onrc.onos.intent.IntentOperation;
@@ -60,11 +59,9 @@
if (oldPaths.isEmpty())
return;
+
IntentOperationList reroutingOperation = new IntentOperationList();
for (PathIntent pathIntent : oldPaths) {
- // TODO use Operator.UPDATE instead of REMOVE and ADD in order to
- // optimize
- reroutingOperation.add(Operator.REMOVE, new Intent(pathIntent.getParentIntent().getId()));
reroutingOperation.add(Operator.ADD, pathIntent.getParentIntent());
}
executeIntentOperations(reroutingOperation);
@@ -123,21 +120,26 @@
// update the map of high-level intents
highLevelIntents.executeOperations(list);
- // prepare high-level intents' state changes
+ // change states of high-level intents
HashMap<String, IntentState> states = new HashMap<>();
for (IntentOperation op : list) {
String id = op.intent.getId();
- states.put(id, IntentState.INST_REQ);
+ if (op.intent.getState().equals(IntentState.INST_ACK))
+ states.put(id, IntentState.REROUTE_REQ);
+ else
+ states.put(id, IntentState.INST_REQ);
}
+ highLevelIntents.changeStates(states);
// calculate path-intents (low-level operations)
IntentOperationList pathIntentOperations = runtime.calcPathIntents(list, pathIntents);
- // persist calculated low-level operations
+ // persist calculated low-level operations into data store
long key = persistIntent.getKey();
persistIntent.persistIfLeader(key, pathIntentOperations);
// remove error-intents and reflect them to high-level intents
+ states.clear();
Iterator<IntentOperation> i = pathIntentOperations.iterator();
while (i.hasNext()) {
IntentOperation op = i.next();
@@ -185,7 +187,7 @@
Collection<DeviceEvent> addedDeviceEvents,
Collection<DeviceEvent> removedDeviceEvents) {
// TODO need optimization.
- // This reroutes only if when some links are removed for now.
+ // Only high-level intents that affected by link down are rerouted.
reroutePaths(removedLinkEvents);
}
}
\ No newline at end of file
diff --git a/src/test/java/net/onrc/onos/intent/PathIntentTest.java b/src/test/java/net/onrc/onos/intent/PathIntentTest.java
index a465118..3c76f3f 100644
--- a/src/test/java/net/onrc/onos/intent/PathIntentTest.java
+++ b/src/test/java/net/onrc/onos/intent/PathIntentTest.java
@@ -29,6 +29,18 @@
}
@Test
+ public void testCreateFirstId() {
+ String id = PathIntent.createFirstId("100");
+ assertEquals("pi100___0", id);
+ }
+
+ @Test
+ public void testCreateNextId() {
+ String id = PathIntent.createNextId("pi100___999");
+ assertEquals("pi100___1000", id);
+ }
+
+ @Test
public void test() {
KryoFactory factory = new KryoFactory();
Kryo kryo = factory.newKryo();
diff --git a/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java b/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
index 698f790..00da877 100755
--- a/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
+++ b/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
@@ -1,5 +1,6 @@
package net.onrc.onos.intent.runtime;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -11,7 +12,9 @@
import net.onrc.onos.intent.ConstrainedShortestPathIntent;
import net.onrc.onos.intent.FlowEntry;
import net.onrc.onos.intent.Intent;
+import net.onrc.onos.intent.Intent.IntentState;
import net.onrc.onos.intent.IntentOperation.Operator;
+import net.onrc.onos.intent.IntentOperation;
import net.onrc.onos.intent.IntentOperationList;
import net.onrc.onos.intent.MockNetworkGraph;
import net.onrc.onos.intent.PathIntent;
@@ -217,25 +220,21 @@
showResult((PathIntentMap) runtime1.getPathIntents());
System.out.println(plan);
+ // TODO this state changes should be triggered by notification of plan module
+ HashMap<String, IntentState> states = new HashMap<>();
+ states.put("1", IntentState.INST_ACK);
+ states.put("2", IntentState.INST_ACK);
+ states.put("3", IntentState.INST_ACK);
+ runtime1.getHighLevelIntents().changeStates(states);
+
// link down
((MockNetworkGraph)g).removeLink(1L, 2L, 9L, 1L); // This link is used by the intent "1"
- LinkEvent linkEvent = new LinkEvent(1L, 2L, 9L, 1L);
- removedLinkEvents.clear();
- removedLinkEvents.add(linkEvent);
- runtime1.networkGraphEvents(
- addedSwitchEvents,
- removedSwitchEvents,
- addedPortEvents,
- removedPortEvents,
- addedLinkEvents,
- removedLinkEvents,
- addedDeviceEvents,
- removedDeviceEvents);
-
((MockNetworkGraph)g).removeLink(9L, 1L, 1L, 2L);
- linkEvent = new LinkEvent(9L, 1L, 1L, 2L);
+ LinkEvent linkEvent1 = new LinkEvent(1L, 2L, 9L, 1L);
+ LinkEvent linkEvent2 = new LinkEvent(9L, 1L, 1L, 2L);
removedLinkEvents.clear();
- removedLinkEvents.add(linkEvent);
+ removedLinkEvents.add(linkEvent1);
+ removedLinkEvents.add(linkEvent2);
runtime1.networkGraphEvents(
addedSwitchEvents,
removedSwitchEvents,