blob: 781b0cadb9c5fce1c029f284be4cfe575d1afc9d [file] [log] [blame]
Jonathan Hartaa380972014-04-03 10:24:46 -07001package net.onrc.onos.core.intent.runtime;
Brian O'Connor7f8e3012014-02-15 23:59:29 -08002
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.Collections;
6import java.util.HashMap;
7import java.util.HashSet;
Brian O'Connor8a52cdd2014-02-25 15:35:25 -08008import java.util.LinkedList;
Brian O'Connor7f8e3012014-02-15 23:59:29 -08009import java.util.List;
10import java.util.Map;
11import java.util.Set;
12
13import net.floodlightcontroller.util.MACAddress;
Jonathan Hartaa380972014-04-03 10:24:46 -070014import net.onrc.onos.core.intent.FlowEntry;
15import net.onrc.onos.core.intent.Intent;
16import net.onrc.onos.core.intent.IntentOperation;
Jonathan Harta99ec672014-04-03 11:30:34 -070017import net.onrc.onos.core.intent.IntentOperation.Operator;
Jonathan Hartaa380972014-04-03 10:24:46 -070018import net.onrc.onos.core.intent.IntentOperationList;
19import net.onrc.onos.core.intent.PathIntent;
20import net.onrc.onos.core.intent.ShortestPathIntent;
Jonathan Hart472062d2014-04-03 10:56:48 -070021import net.onrc.onos.core.topology.LinkEvent;
Jonathan Hart472062d2014-04-03 10:56:48 -070022
Brian O'Connor8a52cdd2014-02-25 15:35:25 -080023import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
Komal Shah399a2922014-05-28 01:57:40 -070025//import net.onrc.onos.core.topology.Topology;
Brian O'Connor8a52cdd2014-02-25 15:35:25 -080026
Brian O'Connor7f8e3012014-02-15 23:59:29 -080027/**
Brian O'Connor7f8e3012014-02-15 23:59:29 -080028 * @author Brian O'Connor <bocon@onlab.us>
Brian O'Connor7f8e3012014-02-15 23:59:29 -080029 */
30
31public class PlanCalcRuntime {
Toshio Koided9fa2a82014-02-19 17:35:18 -080032
Jonathan Harte37e4e22014-05-13 19:12:02 -070033 // Topology graph;
Ray Milkeyec838942014-04-09 11:28:43 -070034 private static final Logger log = LoggerFactory.getLogger(PlanCalcRuntime.class);
Brian O'Connor12861f72014-02-19 20:40:32 -080035
Jonathan Harte37e4e22014-05-13 19:12:02 -070036 public PlanCalcRuntime(/*Topology graph*/) {
Ray Milkey269ffb92014-04-03 14:43:30 -070037// this.graph = graph;
Brian O'Connor12861f72014-02-19 20:40:32 -080038 }
39
40 public List<Set<FlowEntry>> computePlan(IntentOperationList intentOps) {
Ray Milkey269ffb92014-04-03 14:43:30 -070041 long start = System.nanoTime();
42 List<Collection<FlowEntry>> flowEntries = computeFlowEntries(intentOps);
43 long step1 = System.nanoTime();
44 List<Set<FlowEntry>> plan = buildPhases(flowEntries);
45 long step2 = System.nanoTime();
Pavlin Radoslavov964f8ae2014-04-18 16:44:14 -070046 log.debug("MEASUREMENT: Compute flow entries: {} ns, Build phases: {} ns",
Ray Milkey269ffb92014-04-03 14:43:30 -070047 (step1 - start), (step2 - step1));
48 return plan;
Brian O'Connor12861f72014-02-19 20:40:32 -080049 }
50
Brian O'Connor8a52cdd2014-02-25 15:35:25 -080051 private List<Collection<FlowEntry>> computeFlowEntries(IntentOperationList intentOps) {
Ray Milkey269ffb92014-04-03 14:43:30 -070052 List<Collection<FlowEntry>> flowEntries = new LinkedList<>();
53 for (IntentOperation i : intentOps) {
54 if (!(i.intent instanceof PathIntent)) {
55 log.warn("Not a path intent: {}", i);
56 continue;
57 }
58 PathIntent intent = (PathIntent) i.intent;
59 Intent parent = intent.getParentIntent();
60 long srcPort, dstPort;
TeruU30c0c932014-05-15 16:47:41 -070061 long lastDstSw = -1, lastDstPort = -1, firstSrcSw = -1;
Ray Milkey269ffb92014-04-03 14:43:30 -070062 MACAddress srcMac, dstMac;
TeruU30c0c932014-05-15 16:47:41 -070063 int idleTimeout = 0, hardTimeout = 0, firstSwitchIdleTimeout = 0, firstSwitchHardTimeout = 0;
TeruU9e530662014-05-18 11:49:37 -070064 Long cookieId = null;
Komal Shah399a2922014-05-28 01:57:40 -070065 int srcIP, dstIP;
Ray Milkey269ffb92014-04-03 14:43:30 -070066 if (parent instanceof ShortestPathIntent) {
67 ShortestPathIntent pathIntent = (ShortestPathIntent) parent;
Ray Milkey269ffb92014-04-03 14:43:30 -070068 srcPort = pathIntent.getSrcPortNumber();
Ray Milkey269ffb92014-04-03 14:43:30 -070069// Switch dstSwitch = graph.getSwitch(pathIntent.getDstSwitchDpid());
Komal Shah399a2922014-05-28 01:57:40 -070070
71 // srcMacAddress
72 if (pathIntent.getSrcMac() != ShortestPathIntent.EMPTYMACADDRESS) {
73 srcMac = MACAddress.valueOf(pathIntent.getSrcMac());
74 } else {
75 srcMac = null;
76 }
77
78 // dstMacAddress
79 if (pathIntent.getDstMac() != ShortestPathIntent.EMPTYMACADDRESS) {
Jonathan Hart20c801c2014-06-02 11:11:07 -070080 dstMac = MACAddress.valueOf(pathIntent.getDstMac());
Komal Shah399a2922014-05-28 01:57:40 -070081 } else {
82 dstMac = null;
83 }
84
85 // srcIp
86 srcIP = pathIntent.getSrcIp();
87 // dstIp
88 dstIP = pathIntent.getDstIp();
89
90 // Switch dstSwitch = graph.getSwitch(pathIntent.getDstSwitchDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -070091 lastDstSw = pathIntent.getDstSwitchDpid();
TeruU30c0c932014-05-15 16:47:41 -070092 firstSrcSw = pathIntent.getSrcSwitchDpid();
Ray Milkey269ffb92014-04-03 14:43:30 -070093// lastDstPort = dstSwitch.getPort(pathIntent.getDstPortNumber());
94 lastDstPort = pathIntent.getDstPortNumber();
TeruU30c0c932014-05-15 16:47:41 -070095 idleTimeout = pathIntent.getIdleTimeout();
96 hardTimeout = pathIntent.getHardTimeout();
97 firstSwitchIdleTimeout = pathIntent.getFirstSwitchIdleTimeout();
Jonathan Hart33e1f302014-05-30 14:37:09 -070098 firstSwitchHardTimeout = pathIntent.getFirstSwitchHardTimeout();
TeruU9e530662014-05-18 11:49:37 -070099 try {
100 cookieId = Long.valueOf(pathIntent.getId());
101 } catch (NumberFormatException e) {
102 log.trace("NumberFormatException : ", e);
103 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700104 } else {
105 log.warn("Unsupported Intent: {}", parent);
106 continue;
107 }
108 List<FlowEntry> entries = new ArrayList<>();
109 for (LinkEvent linkEvent : intent.getPath()) {
110// Link link = graph.getLink(linkEvent.getSrc().getDpid(),
111// linkEvent.getSrc().getNumber(),
112// linkEvent.getDst().getDpid(),
113// linkEvent.getDst().getNumber());
114// Switch sw = link.getSrcSwitch();
115 long sw = linkEvent.getSrc().getDpid();
116// dstPort = link.getSrcPort();
117 dstPort = linkEvent.getSrc().getNumber();
Komal Shah399a2922014-05-28 01:57:40 -0700118 FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac,
119 srcIP, dstIP, i.operator);
TeruU30c0c932014-05-15 16:47:41 -0700120 if (sw != firstSrcSw) {
121 fe.setIdleTimeout(idleTimeout);
122 fe.setHardTimeout(hardTimeout);
123 } else {
124 fe.setIdleTimeout(firstSwitchIdleTimeout);
125 fe.setHardTimeout(firstSwitchHardTimeout);
126 }
TeruU9e530662014-05-18 11:49:37 -0700127 if (cookieId != null) {
128 log.trace("cookieId is set: {}", cookieId);
129 fe.setFlowEntryId(cookieId);
130 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700131 entries.add(fe);
Komal Shah399a2922014-05-28 01:57:40 -0700132 // srcPort = link.getDstPort();
Ray Milkey269ffb92014-04-03 14:43:30 -0700133 srcPort = linkEvent.getDst().getNumber();
134 }
135 if (lastDstSw >= 0 && lastDstPort >= 0) {
136 //Switch sw = lastDstPort.getSwitch();
137 long sw = lastDstSw;
138 dstPort = lastDstPort;
Komal Shah399a2922014-05-28 01:57:40 -0700139 FlowEntry fe = new FlowEntry(sw, srcPort, dstPort, srcMac, dstMac,
140 srcIP, dstIP, i.operator);
TeruUe3bbe2f2014-05-28 16:11:30 -0700141 if (cookieId != null) {
142 log.trace("cookieId is set: {}", cookieId);
143 fe.setFlowEntryId(cookieId);
144 }
TeruUe5d0bf12014-05-28 17:50:02 -0700145 if (sw != firstSrcSw) {
146 fe.setIdleTimeout(idleTimeout);
147 fe.setHardTimeout(hardTimeout);
148 } else {
149 fe.setIdleTimeout(firstSwitchIdleTimeout);
150 fe.setHardTimeout(firstSwitchHardTimeout);
151 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700152 entries.add(fe);
153 }
154 // install flow entries in reverse order
155 Collections.reverse(entries);
156 flowEntries.add(entries);
157 }
158 return flowEntries;
Brian O'Connor12861f72014-02-19 20:40:32 -0800159 }
Toshio Koided9fa2a82014-02-19 17:35:18 -0800160
TeruU30c0c932014-05-15 16:47:41 -0700161 // This method is for a testing purpose. Please leave it right now.
162 private List<Set<FlowEntry>> simpleBuildPhases(List<Collection<FlowEntry>> flowEntries) {
163 List<Set<FlowEntry>> plan = new ArrayList<>();
164 Set<FlowEntry> phase = new HashSet<>();
165 for (Collection<FlowEntry> c : flowEntries) {
166 phase.addAll(c);
167 }
168 plan.add(phase);
169
170 return plan;
171 }
172
Brian O'Connor8a52cdd2014-02-25 15:35:25 -0800173 private List<Set<FlowEntry>> buildPhases(List<Collection<FlowEntry>> flowEntries) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700174 Map<FlowEntry, Integer> map = new HashMap<>();
175 List<Set<FlowEntry>> plan = new ArrayList<>();
176 for (Collection<FlowEntry> c : flowEntries) {
177 for (FlowEntry e : c) {
178 Integer i = map.get(e);
179 if (i == null) {
180 i = Integer.valueOf(0);
181 }
182 switch (e.getOperator()) {
183 case ADD:
184 i += 1;
185 break;
186 case REMOVE:
187 i -= 1;
188 break;
189 default:
190 break;
191 }
192 map.put(e, i);
193 // System.out.println(e + " " + e.getOperator());
194 }
195 }
Toshio Koidebf875662014-02-24 12:19:15 -0800196
Ray Milkey269ffb92014-04-03 14:43:30 -0700197 // really simple first iteration of plan
198 //TODO: optimize the map in phases
199 Set<FlowEntry> phase = new HashSet<>();
Pavlin Radoslavov45a0ad32014-04-10 12:16:40 -0700200 for (Map.Entry<FlowEntry, Integer> entry : map.entrySet()) {
201 FlowEntry e = entry.getKey();
202 Integer i = entry.getValue();
Ray Milkey269ffb92014-04-03 14:43:30 -0700203 if (i == 0) {
204 continue;
205 } else if (i > 0) {
206 e.setOperator(Operator.ADD);
207 } else if (i < 0) {
208 e.setOperator(Operator.REMOVE);
209 }
210 phase.add(e);
211 }
212 plan.add(phase);
Toshio Koidebf875662014-02-24 12:19:15 -0800213
Ray Milkey269ffb92014-04-03 14:43:30 -0700214 return plan;
Brian O'Connor12861f72014-02-19 20:40:32 -0800215 }
Brian O'Connor7f8e3012014-02-15 23:59:29 -0800216}