Added Intent Subscriber and Module
Module is used to drive plan computation and installation
Also, added support for ADD/REMOVE in plan computation
Change-Id: Ib88eae8b13a1f5ed1503c5ff7762980f8ed032ac
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
index 18e962f..63892cb 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
@@ -12,9 +12,10 @@
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.intent.FlowEntry;
import net.onrc.onos.intent.Intent;
+import net.onrc.onos.intent.IntentOperation;
+import net.onrc.onos.intent.IntentOperation.Operator;
import net.onrc.onos.intent.IntentOperationList;
import net.onrc.onos.intent.PathIntent;
-import net.onrc.onos.intent.PathIntentMap;
import net.onrc.onos.intent.ShortestPathIntent;
import net.onrc.onos.ofcontroller.networkgraph.Link;
import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
@@ -29,88 +30,103 @@
*/
public class PlanCalcRuntime {
- NetworkGraph graph;
- protected PathIntentMap intents;
- protected Set<Collection<FlowEntry>> flowEntries;
- protected List<Set<FlowEntry>> plan;
- public PlanCalcRuntime(NetworkGraph graph) {
- this.graph = graph;
- this.flowEntries = new HashSet<>();
- this.plan = new ArrayList<>();
- this.intents = new PathIntentMap();
+ NetworkGraph graph;
+
+ public PlanCalcRuntime(NetworkGraph graph) {
+ this.graph = graph;
+ }
+
+ public List<Set<FlowEntry>> computePlan(IntentOperationList intentOps) {
+ Set<Collection<FlowEntry>> flowEntries = computeFlowEntries(intentOps);
+ return buildPhases(flowEntries);
+ }
+
+ private Set<Collection<FlowEntry>> computeFlowEntries(IntentOperationList intentOps) {
+ Set<Collection<FlowEntry>> flowEntries = new HashSet<>();
+ for(IntentOperation i : intentOps) {
+ PathIntent intent = (PathIntent) i.intent;
+ Intent parent = intent.getParentIntent();
+ Port srcPort, dstPort, lastDstPort = null;
+ MACAddress srcMac, dstMac;
+ if(parent instanceof ShortestPathIntent) {
+ ShortestPathIntent pathIntent = (ShortestPathIntent) parent;
+ Switch srcSwitch = graph.getSwitch(pathIntent.getSrcSwitchDpid());
+ srcPort = srcSwitch.getPort(pathIntent.getSrcPortNumber());
+ srcMac = MACAddress.valueOf(pathIntent.getSrcMac());
+ dstMac = MACAddress.valueOf(pathIntent.getDstMac());
+ Switch dstSwitch = graph.getSwitch(pathIntent.getDstSwitchDpid());
+ lastDstPort = dstSwitch.getPort(pathIntent.getDstPortNumber());
+ }
+ else {
+ // TODO: log this error
+ continue;
+ }
+ List<FlowEntry> entries = new ArrayList<>();
+ for(LinkEvent linkEvent : intent.getPath()) {
+ Link link = graph.getLink(linkEvent.getSrc().getDpid(),
+ linkEvent.getSrc().getNumber(),
+ linkEvent.getDst().getDpid(),
+ linkEvent.getDst().getNumber());
+ Switch sw = link.getSrcSwitch();
+ dstPort = link.getSrcPort();
+ FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac, i.operator);
+ entries.add(fe);
+ srcPort = link.getDstPort();
+ }
+ if(lastDstPort != null) {
+ Switch sw = lastDstPort.getSwitch();
+ dstPort = lastDstPort;
+ FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac, i.operator);
+ entries.add(fe);
+ }
+ // install flow entries in reverse order
+ Collections.reverse(entries);
+ flowEntries.add(entries);
}
+ return flowEntries;
+ }
- public void addIntents(IntentOperationList intentOpList) {
- intents.executeOperations(intentOpList);
- computeFlowEntries();
- constructPlan();
- }
-
- public List<Set<FlowEntry>> getPlan() {
- return plan;
- }
-
- public void computeFlowEntries() {
- for(Intent i : intents.getAllIntents()) {
- PathIntent intent = (PathIntent)i;
- Intent parent = intent.getParentIntent();
- Port srcPort, dstPort, lastDstPort = null;
- MACAddress srcMac, dstMac;
- if(parent instanceof ShortestPathIntent) {
- ShortestPathIntent pathIntent = (ShortestPathIntent) parent;
- Switch srcSwitch = graph.getSwitch(pathIntent.getSrcSwitchDpid());
- srcPort = srcSwitch.getPort(pathIntent.getSrcPortNumber());
- srcMac = MACAddress.valueOf(pathIntent.getSrcMac());
- dstMac = MACAddress.valueOf(pathIntent.getDstMac());
- Switch dstSwitch = graph.getSwitch(pathIntent.getDstSwitchDpid());
- lastDstPort = dstSwitch.getPort(pathIntent.getDstPortNumber());
- }
- else {
- // TODO: log this error
- continue;
- }
- List<FlowEntry> entries = new ArrayList<>();
- for(LinkEvent linkEvent : intent.getPath()) {
- Link link = graph.getLink(linkEvent.getSrc().getDpid(),
- linkEvent.getSrc().getNumber(),
- linkEvent.getDst().getDpid(),
- linkEvent.getDst().getNumber());
- Switch sw = link.getSrcSwitch();
- dstPort = link.getSrcPort();
- FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac);
- entries.add(fe);
- srcPort = link.getDstPort();
- }
- if(lastDstPort != null) {
- Switch sw = lastDstPort.getSwitch();
- dstPort = lastDstPort;
- FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac);
- entries.add(fe);
- }
- // install flow entries in reverse order
- Collections.reverse(entries);
- flowEntries.add(entries);
+ private List<Set<FlowEntry>> buildPhases(Set<Collection<FlowEntry>> flowEntries) {
+ Map<FlowEntry, Integer> map = new HashMap<>();
+ List<Set<FlowEntry>> plan = new ArrayList<>();
+ for(Collection<FlowEntry> c : flowEntries) {
+ for(FlowEntry e : c) {
+ Integer i = map.get(e);
+ if(i == null) {
+ i = Integer.valueOf(0);
}
- }
-
- public void constructPlan() {
- Map<FlowEntry, Integer> map = new HashMap<>();
- for(Collection<FlowEntry> c : flowEntries) {
- for(FlowEntry e: c) {
- Integer i = map.get(e);
- if(i == null) {
- map.put(e, 1);
- }
- else {
- i += 1;
- }
-
- }
+ switch(e.getOperator()) {
+ case ADD:
+ i += 1;
+ break;
+ case REMOVE:
+ i -= 1;
+ break;
}
-
- // really simple first iteration of plan
- //TODO: optimize the map in phases
- plan.add(map.keySet());
+ map.put(e, i);
+ System.out.println(e + " " + e.getOperator());
+ }
}
+
+ // really simple first iteration of plan
+ //TODO: optimize the map in phases
+ Set<FlowEntry> phase = new HashSet<>();
+ for(FlowEntry e : map.keySet()) {
+ Integer i = map.get(e);
+ if(i == 0) {
+ continue;
+ }
+ else if(i > 0) {
+ e.setOperator(Operator.ADD);
+ }
+ else if(i < 0) {
+ e.setOperator(Operator.REMOVE);
+ }
+ phase.add(e);
+ }
+ plan.add(phase);
+
+ return plan;
+ }
}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
new file mode 100644
index 0000000..df4c762
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
@@ -0,0 +1,116 @@
+package net.onrc.onos.intent.runtime;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+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.datagrid.IEventChannelListener;
+import net.onrc.onos.intent.FlowEntry;
+import net.onrc.onos.intent.IntentOperationList;
+import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+
+public class PlanInstallModule implements IFloodlightModule {
+ protected volatile IFloodlightProviderService floodlightProvider;
+ protected volatile NetworkGraph networkGraph;
+ protected volatile IDatagridService datagridService;
+ protected volatile IFlowPusherService flowPusher;
+ private PlanCalcRuntime planCalc;
+ private PlanInstallRuntime planInstall;
+ private EventListener eventListener;
+
+ private static final String PATH_INTENT_CHANNEL_NAME = "onos.pathintent";
+
+ @Override
+ public void init(FloodlightModuleContext context)
+ throws FloodlightModuleException {
+ floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+ //networkGraph = context.getServiceImpl(INetworkGraphService.class);
+ datagridService = context.getServiceImpl(IDatagridService.class);
+ flowPusher = context.getServiceImpl(IFlowPusherService.class);
+ planCalc = new PlanCalcRuntime(networkGraph);
+ planInstall = new PlanInstallRuntime(networkGraph, floodlightProvider, flowPusher);
+ eventListener = new EventListener();
+ }
+
+ class EventListener extends Thread
+ implements IEventChannelListener<Long, IntentOperationList> {
+
+ private BlockingQueue<IntentOperationList> intentQueue = new LinkedBlockingQueue<>();
+
+ @Override
+ public void run() {
+ while(true) {
+ try {
+ IntentOperationList intents = intentQueue.take();
+ //TODO: drain the remaining intent lists
+ processIntents(intents);
+ } catch (InterruptedException e) {
+ //TODO: log the exception
+ }
+ }
+ }
+
+ private void processIntents(IntentOperationList intents) {
+ List<Set<FlowEntry>> plan = planCalc.computePlan(intents);
+ planInstall.installPlan(plan);
+ }
+
+ @Override
+ public void entryAdded(IntentOperationList value) {
+ intentQueue.add(value);
+ }
+
+ @Override
+ public void entryRemoved(IntentOperationList value) {
+ // This channel is a queue, so this method is not needed
+ }
+
+ @Override
+ public void entryUpdated(IntentOperationList value) {
+ // This channel is a queue, so this method is not needed
+ }
+ }
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+ eventListener.start();
+ datagridService.addListener(PATH_INTENT_CHANNEL_NAME,
+ new EventListener(),
+ Long.class,
+ IntentOperationList.class);
+ }
+
+ @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);
+ l.add(IFlowPusherService.class);
+ return l;
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathInstallRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallRuntime.java
similarity index 81%
rename from src/main/java/net/onrc/onos/intent/runtime/PathInstallRuntime.java
rename to src/main/java/net/onrc/onos/intent/runtime/PlanInstallRuntime.java
index 0b74cfc..3e4ff4a 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PathInstallRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallRuntime.java
@@ -18,22 +18,23 @@
*
*/
-public class PathInstallRuntime {
+public class PlanInstallRuntime {
NetworkGraph graph;
IFlowPusherService pusher;
IFloodlightProviderService provider;
- protected List<Set<FlowEntry>> plan;
- public PathInstallRuntime(NetworkGraph graph) {
+ public PlanInstallRuntime(NetworkGraph graph,
+ IFloodlightProviderService provider,
+ IFlowPusherService pusher) {
this.graph = graph;
+ this.provider = provider;
+ this.pusher = pusher;
}
public void installPlan(List<Set<FlowEntry>> plan) {
- this.plan = plan;
Map<Long,IOFSwitch> switches = provider.getSwitches();
for(Set<FlowEntry> phase : plan) {
- Set<Pair<IOFSwitch, net.onrc.onos.ofcontroller.util.FlowEntry>> entries
- = new HashSet<>();
+ Set<Pair<IOFSwitch, net.onrc.onos.ofcontroller.util.FlowEntry>> entries = new HashSet<>();
// convert flow entries and create pairs
for(FlowEntry entry : phase) {
entries.add(new Pair<>(switches.get(entry.getSwitch().getDpid()),