| package net.onrc.onos.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.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.ShortestPathIntent; |
| import net.onrc.onos.ofcontroller.networkgraph.LinkEvent; |
| //import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph; |
| |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * |
| * @author Brian O'Connor <bocon@onlab.us> |
| * |
| */ |
| |
| public class PlanCalcRuntime { |
| |
| // NetworkGraph graph; |
| private final static Logger log = LoggerFactory.getLogger(PlanCalcRuntime.class); |
| |
| public PlanCalcRuntime(/*NetworkGraph 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.error("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(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; |
| } |
| } |