blob: 087bff8d103891359ee3ff29cfc82ff6d062b99e [file] [log] [blame]
package net.onrc.onos.core.intent.runtime;
import java.util.ArrayList;
import java.util.Collection;
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.Set;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.core.intent.FlowEntry;
import net.onrc.onos.core.intent.Intent;
import net.onrc.onos.core.intent.IntentOperation;
import net.onrc.onos.core.intent.IntentOperation.Operator;
import net.onrc.onos.core.intent.IntentOperationList;
import net.onrc.onos.core.intent.PathIntent;
import net.onrc.onos.core.intent.ShortestPathIntent;
import net.onrc.onos.core.topology.LinkEvent;
//import net.onrc.onos.core.topology.Topology;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Brian O'Connor <bocon@onlab.us>
*/
public class PlanCalcRuntime {
// Topology graph;
private static final Logger log = LoggerFactory.getLogger(PlanCalcRuntime.class);
public PlanCalcRuntime(/*Topology graph*/) {
// this.graph = graph;
}
public List<Set<FlowEntry>> computePlan(IntentOperationList intentOps) {
long start = System.nanoTime();
List<Collection<FlowEntry>> flowEntries = computeFlowEntries(intentOps);
long step1 = System.nanoTime();
List<Set<FlowEntry>> plan = buildPhases(flowEntries);
long step2 = System.nanoTime();
log.debug("MEASUREMENT: Compute flow entries: {} ns, Build phases: {} ns",
(step1 - start), (step2 - step1));
return plan;
}
private List<Collection<FlowEntry>> computeFlowEntries(IntentOperationList intentOps) {
List<Collection<FlowEntry>> flowEntries = new LinkedList<>();
for (IntentOperation i : intentOps) {
if (!(i.intent instanceof PathIntent)) {
log.warn("Not a path intent: {}", i);
continue;
}
PathIntent intent = (PathIntent) i.intent;
Intent parent = intent.getParentIntent();
long srcPort, dstPort;
long lastDstSw = -1, lastDstPort = -1;
MACAddress srcMac, dstMac;
if (parent instanceof ShortestPathIntent) {
ShortestPathIntent pathIntent = (ShortestPathIntent) parent;
// Switch srcSwitch = graph.getSwitch(pathIntent.getSrcSwitchDpid());
// srcPort = srcSwitch.getPort(pathIntent.getSrcPortNumber());
srcPort = pathIntent.getSrcPortNumber();
srcMac = MACAddress.valueOf(pathIntent.getSrcMac());
dstMac = MACAddress.valueOf(pathIntent.getDstMac());
// Switch dstSwitch = graph.getSwitch(pathIntent.getDstSwitchDpid());
lastDstSw = pathIntent.getDstSwitchDpid();
// lastDstPort = dstSwitch.getPort(pathIntent.getDstPortNumber());
lastDstPort = pathIntent.getDstPortNumber();
} else {
log.warn("Unsupported Intent: {}", parent);
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();
long sw = linkEvent.getSrc().getDpid();
// dstPort = link.getSrcPort();
dstPort = linkEvent.getSrc().getNumber();
FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac, i.operator);
entries.add(fe);
// srcPort = link.getDstPort();
srcPort = linkEvent.getDst().getNumber();
}
if (lastDstSw >= 0 && lastDstPort >= 0) {
//Switch sw = lastDstPort.getSwitch();
long sw = lastDstSw;
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;
}
private List<Set<FlowEntry>> buildPhases(List<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);
}
switch (e.getOperator()) {
case ADD:
i += 1;
break;
case REMOVE:
i -= 1;
break;
default:
break;
}
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 (Map.Entry<FlowEntry, Integer> entry : map.entrySet()) {
FlowEntry e = entry.getKey();
Integer i = entry.getValue();
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;
}
}