blob: 320126c6518a019b530924964212a4d7d36dcf97 [file] [log] [blame]
Jonathan Hartaa380972014-04-03 10:24:46 -07001package net.onrc.onos.core.intent.runtime;
Toshio Koide4f308732014-02-18 15:19:48 -08002
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.HashMap;
Toshio Koide798bc1b2014-02-20 14:02:40 -08006import java.util.HashSet;
Toshio Koidedf2eab92014-02-20 11:24:59 -08007import java.util.Iterator;
Toshio Koidebf875662014-02-24 12:19:15 -08008import java.util.LinkedList;
Toshio Koide4f308732014-02-18 15:19:48 -08009import java.util.Map;
Toshio Koide066506e2014-02-20 19:52:09 -080010import java.util.Map.Entry;
TeruUf9111652014-05-14 23:10:35 -070011import java.util.Set;
12import java.util.concurrent.ConcurrentHashMap;
Toshio Koide93be5d62014-02-23 19:30:57 -080013import java.util.concurrent.locks.ReentrantLock;
Toshio Koide4f308732014-02-18 15:19:48 -080014
15import net.floodlightcontroller.core.module.FloodlightModuleContext;
16import net.floodlightcontroller.core.module.FloodlightModuleException;
17import net.floodlightcontroller.core.module.IFloodlightModule;
18import net.floodlightcontroller.core.module.IFloodlightService;
Pavlin Radoslavov13669052014-05-13 10:33:39 -070019import net.floodlightcontroller.restserver.IRestApiService;
Jonathan Hart6df90172014-04-03 10:13:11 -070020import net.onrc.onos.core.datagrid.IDatagridService;
21import net.onrc.onos.core.datagrid.IEventChannel;
22import net.onrc.onos.core.datagrid.IEventChannelListener;
Jonathan Hartaa380972014-04-03 10:24:46 -070023import net.onrc.onos.core.intent.Intent;
Jonathan Harta99ec672014-04-03 11:30:34 -070024import net.onrc.onos.core.intent.Intent.IntentState;
Jonathan Hartaa380972014-04-03 10:24:46 -070025import net.onrc.onos.core.intent.IntentMap;
26import net.onrc.onos.core.intent.IntentOperation;
Jonathan Harta99ec672014-04-03 11:30:34 -070027import net.onrc.onos.core.intent.IntentOperation.Operator;
Jonathan Hartaa380972014-04-03 10:24:46 -070028import net.onrc.onos.core.intent.IntentOperationList;
29import net.onrc.onos.core.intent.PathIntent;
30import net.onrc.onos.core.intent.PathIntentMap;
31import net.onrc.onos.core.intent.ShortestPathIntent;
Pavlin Radoslavov13669052014-05-13 10:33:39 -070032import net.onrc.onos.core.intent.runtime.web.IntentWebRoutable;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070033import net.onrc.onos.core.registry.IControllerRegistryService;
Jonathan Hart472062d2014-04-03 10:56:48 -070034import net.onrc.onos.core.topology.DeviceEvent;
Jonathan Harte37e4e22014-05-13 19:12:02 -070035import net.onrc.onos.core.topology.ITopologyListener;
36import net.onrc.onos.core.topology.ITopologyService;
Jonathan Hart472062d2014-04-03 10:56:48 -070037import net.onrc.onos.core.topology.LinkEvent;
38import net.onrc.onos.core.topology.PortEvent;
39import net.onrc.onos.core.topology.SwitchEvent;
Toshio Koide4f308732014-02-18 15:19:48 -080040
Jonathan Harta99ec672014-04-03 11:30:34 -070041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
Toshio Koide0c9106d2014-02-19 15:26:38 -080044/**
45 * @author Toshio Koide (t-koide@onlab.us)
46 */
Jonathan Harte37e4e22014-05-13 19:12:02 -070047public class PathCalcRuntimeModule implements IFloodlightModule, IPathCalcRuntimeService, ITopologyListener, IEventChannelListener<Long, IntentStateList> {
Pavlin Radoslavovfee80982014-04-10 12:12:04 -070048 static class PerfLog {
Ray Milkey269ffb92014-04-03 14:43:30 -070049 private String step;
50 private long time;
Toshio Koidebf875662014-02-24 12:19:15 -080051
Ray Milkey269ffb92014-04-03 14:43:30 -070052 public PerfLog(String step) {
53 this.step = step;
54 this.time = System.nanoTime();
55 }
Toshio Koidebf875662014-02-24 12:19:15 -080056
Ray Milkey269ffb92014-04-03 14:43:30 -070057 public void logThis() {
Pavlin Radoslavov964f8ae2014-04-18 16:44:14 -070058 log.debug("Time:{}, Step:{}", time, step);
Ray Milkey269ffb92014-04-03 14:43:30 -070059 }
60 }
Toshio Koidebf875662014-02-24 12:19:15 -080061
Pavlin Radoslavov53ad5e32014-04-10 14:24:26 -070062 static class PerfLogger {
Ray Milkey269ffb92014-04-03 14:43:30 -070063 private LinkedList<PerfLog> logData = new LinkedList<>();
Toshio Koidebf875662014-02-24 12:19:15 -080064
Ray Milkey269ffb92014-04-03 14:43:30 -070065 public PerfLogger(String logPhase) {
66 log("start_" + logPhase);
67 }
Toshio Koidebf875662014-02-24 12:19:15 -080068
Ray Milkey269ffb92014-04-03 14:43:30 -070069 public void log(String step) {
70 logData.add(new PerfLog(step));
71 }
Toshio Koide27ffd412014-02-18 19:15:27 -080072
Ray Milkey269ffb92014-04-03 14:43:30 -070073 public void flushLog() {
74 log("finish");
Ray Milkey5df613b2014-04-15 10:50:56 -070075 for (PerfLog perfLog : logData) {
76 perfLog.logThis();
Ray Milkey269ffb92014-04-03 14:43:30 -070077 }
78 logData.clear();
79 }
80 }
Toshio Koide4f308732014-02-18 15:19:48 -080081
Ray Milkey269ffb92014-04-03 14:43:30 -070082 private PathCalcRuntime runtime;
83 private IDatagridService datagridService;
Jonathan Harte37e4e22014-05-13 19:12:02 -070084 private ITopologyService topologyService;
Ray Milkey269ffb92014-04-03 14:43:30 -070085 private IntentMap highLevelIntents;
86 private PathIntentMap pathIntents;
87 private IControllerRegistryService controllerRegistry;
88 private PersistIntent persistIntent;
Pavlin Radoslavov13669052014-05-13 10:33:39 -070089 private IRestApiService restApi;
Toshio Koide798bc1b2014-02-20 14:02:40 -080090
Ray Milkey269ffb92014-04-03 14:43:30 -070091 private IEventChannel<Long, IntentOperationList> opEventChannel;
TeruU9e530662014-05-18 11:49:37 -070092 private final ReentrantLock lock = new ReentrantLock(true);
Ray Milkey269ffb92014-04-03 14:43:30 -070093 private HashSet<LinkEvent> unmatchedLinkEvents = new HashSet<>();
TeruUf9111652014-05-14 23:10:35 -070094 private Map<String, Set<Long>> intentInstalledMap = new ConcurrentHashMap<String, Set<Long>>();
Ray Milkey269ffb92014-04-03 14:43:30 -070095 private static final String INTENT_OP_EVENT_CHANNEL_NAME = "onos.pathintent";
96 private static final String INTENT_STATE_EVENT_CHANNEL_NAME = "onos.pathintent_state";
97 private static final Logger log = LoggerFactory.getLogger(PathCalcRuntimeModule.class);
Toshio Koidea10c0372014-02-20 17:28:10 -080098
Ray Milkey269ffb92014-04-03 14:43:30 -070099 // ================================================================================
100 // private methods
101 // ================================================================================
102
103 private void reroutePaths(Collection<Intent> oldPaths) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700104 if (oldPaths == null || oldPaths.isEmpty()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700105 return;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700106 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700107
108 IntentOperationList reroutingOperation = new IntentOperationList();
109 for (Intent intent : oldPaths) {
110 PathIntent pathIntent = (PathIntent) intent;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700111 if (pathIntent.isPathFrozen()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700112 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700113 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700114 if (pathIntent.getState().equals(IntentState.INST_ACK) && // XXX: path intents in flight
115 !reroutingOperation.contains(pathIntent.getParentIntent())) {
116 reroutingOperation.add(Operator.ADD, pathIntent.getParentIntent());
117 }
118 }
119 executeIntentOperations(reroutingOperation);
120 }
Toshio Koidea94060f2014-02-21 22:58:32 -0800121
Toshio Koide27ffd412014-02-18 19:15:27 -0800122
Ray Milkey269ffb92014-04-03 14:43:30 -0700123 // ================================================================================
124 // IFloodlightModule implementations
125 // ================================================================================
Toshio Koide798bc1b2014-02-20 14:02:40 -0800126
Ray Milkey269ffb92014-04-03 14:43:30 -0700127 @Override
128 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
129 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(1);
130 l.add(IPathCalcRuntimeService.class);
131 return l;
132 }
Toshio Koide4f308732014-02-18 15:19:48 -0800133
Ray Milkey269ffb92014-04-03 14:43:30 -0700134 @Override
135 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
136 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
137 m.put(IPathCalcRuntimeService.class, this);
138 return m;
139 }
Toshio Koide4f308732014-02-18 15:19:48 -0800140
Ray Milkey269ffb92014-04-03 14:43:30 -0700141 @Override
142 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
143 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(2);
144 l.add(IDatagridService.class);
Pavlin Radoslavov13669052014-05-13 10:33:39 -0700145 l.add(IRestApiService.class);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700146 l.add(ITopologyService.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700147 return l;
148 }
Toshio Koide4f308732014-02-18 15:19:48 -0800149
Ray Milkey269ffb92014-04-03 14:43:30 -0700150 @Override
151 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
152 datagridService = context.getServiceImpl(IDatagridService.class);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700153 topologyService = context.getServiceImpl(ITopologyService.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700154 controllerRegistry = context.getServiceImpl(IControllerRegistryService.class);
Pavlin Radoslavov13669052014-05-13 10:33:39 -0700155 restApi = context.getServiceImpl(IRestApiService.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700156 }
Toshio Koide4f308732014-02-18 15:19:48 -0800157
Ray Milkey269ffb92014-04-03 14:43:30 -0700158 @Override
159 public void startUp(FloodlightModuleContext context) {
160 highLevelIntents = new IntentMap();
Jonathan Harte37e4e22014-05-13 19:12:02 -0700161 runtime = new PathCalcRuntime(topologyService.getTopology());
Ray Milkey269ffb92014-04-03 14:43:30 -0700162 pathIntents = new PathIntentMap();
163 opEventChannel = datagridService.createChannel(INTENT_OP_EVENT_CHANNEL_NAME, Long.class, IntentOperationList.class);
164 datagridService.addListener(INTENT_STATE_EVENT_CHANNEL_NAME, this, Long.class, IntentStateList.class);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700165 topologyService.registerTopologyListener(this);
Pavlin Radoslavov0294e052014-04-10 13:36:45 -0700166 persistIntent = new PersistIntent(controllerRegistry);
Pavlin Radoslavov13669052014-05-13 10:33:39 -0700167 restApi.addRestletRoutable(new IntentWebRoutable());
Ray Milkey269ffb92014-04-03 14:43:30 -0700168 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800169
Ray Milkey269ffb92014-04-03 14:43:30 -0700170 // ================================================================================
171 // IPathCalcRuntimeService implementations
172 // ================================================================================
Toshio Koide798bc1b2014-02-20 14:02:40 -0800173
Ray Milkey269ffb92014-04-03 14:43:30 -0700174 @Override
175 public IntentOperationList executeIntentOperations(IntentOperationList list) {
TeruU9e530662014-05-18 11:49:37 -0700176
Ray Milkeyb29e6262014-04-09 16:02:14 -0700177 if (list == null || list.size() == 0) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700178 return null;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700179 }
Toshio Koide275d8142014-02-24 16:41:52 -0800180
Ray Milkey269ffb92014-04-03 14:43:30 -0700181 lock.lock(); // TODO optimize locking using smaller steps
182 try {
TeruU9e530662014-05-18 11:49:37 -0700183 log.trace("lock executeIntentOperations, lock obj is already locked? {}", lock.isLocked());
Ray Milkey269ffb92014-04-03 14:43:30 -0700184 // update the map of high-level intents
TeruU9e530662014-05-18 11:49:37 -0700185
Ray Milkey269ffb92014-04-03 14:43:30 -0700186 highLevelIntents.executeOperations(list);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800187
Ray Milkey269ffb92014-04-03 14:43:30 -0700188 // change states of high-level intents
189 IntentStateList states = new IntentStateList();
190 for (IntentOperation op : list) {
191 switch (op.operator) {
192 case ADD:
193 switch (op.intent.getState()) {
194 case CREATED:
195 states.put(op.intent.getId(), IntentState.INST_REQ);
196 break;
197 case INST_ACK:
198 states.put(op.intent.getId(), IntentState.REROUTE_REQ);
199 break;
200 default:
201 break;
202 }
203 break;
204 case REMOVE:
205 switch (op.intent.getState()) {
206 case CREATED:
207 states.put(op.intent.getId(), IntentState.DEL_REQ);
208 break;
209 default:
210 break;
211 }
212 break;
213 default:
214 break;
215 }
216 }
217 highLevelIntents.changeStates(states);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800218
Ray Milkey269ffb92014-04-03 14:43:30 -0700219 // calculate path-intents (low-level operations)
Ray Milkey269ffb92014-04-03 14:43:30 -0700220 IntentOperationList pathIntentOperations = runtime.calcPathIntents(list, highLevelIntents, pathIntents);
Toshio Koide600ae5f2014-02-20 18:42:00 -0800221
Ray Milkey269ffb92014-04-03 14:43:30 -0700222 // persist calculated low-level operations into data store
Ray Milkey269ffb92014-04-03 14:43:30 -0700223 long key = persistIntent.getKey();
224 persistIntent.persistIfLeader(key, pathIntentOperations);
Toshio Koide93be5d62014-02-23 19:30:57 -0800225
Ray Milkey269ffb92014-04-03 14:43:30 -0700226 // remove error-intents and reflect them to high-level intents
Ray Milkey269ffb92014-04-03 14:43:30 -0700227 states.clear();
228 Iterator<IntentOperation> i = pathIntentOperations.iterator();
229 while (i.hasNext()) {
230 IntentOperation op = i.next();
231 if (op.operator.equals(Operator.ERROR)) {
232 states.put(op.intent.getId(), IntentState.INST_NACK);
233 i.remove();
234 }
235 }
236 highLevelIntents.changeStates(states);
Toshio Koidea94060f2014-02-21 22:58:32 -0800237
Ray Milkey269ffb92014-04-03 14:43:30 -0700238 // update the map of path intents and publish the path operations
Ray Milkey269ffb92014-04-03 14:43:30 -0700239 pathIntents.executeOperations(pathIntentOperations);
Toshio Koide93be5d62014-02-23 19:30:57 -0800240
Ray Milkey269ffb92014-04-03 14:43:30 -0700241 // XXX Demo special: add a complete path to remove operation
Ray Milkey269ffb92014-04-03 14:43:30 -0700242 for (IntentOperation op : pathIntentOperations) {
243 if (op.operator.equals(Operator.REMOVE)) {
244 op.intent = pathIntents.getIntent(op.intent.getId());
245 }
246 if (op.intent instanceof PathIntent) {
247 log.debug("operation: {}, intent:{}", op.operator, op.intent);
248 }
249 }
Toshio Koide93be5d62014-02-23 19:30:57 -0800250
Ray Milkey269ffb92014-04-03 14:43:30 -0700251 // send notification
Ray Milkey269ffb92014-04-03 14:43:30 -0700252 // XXX: Send notifications using the same key every time
253 // and receive them by entryAdded() and entryUpdated()
254 opEventChannel.addEntry(0L, pathIntentOperations);
Ray Milkey269ffb92014-04-03 14:43:30 -0700255 //opEventChannel.removeEntry(key);
256 return pathIntentOperations;
257 } finally {
Ray Milkey269ffb92014-04-03 14:43:30 -0700258 lock.unlock();
TeruU9e530662014-05-18 11:49:37 -0700259 log.trace("unlock executeIntentOperations");
Ray Milkey269ffb92014-04-03 14:43:30 -0700260 }
261 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800262
Ray Milkey269ffb92014-04-03 14:43:30 -0700263 @Override
264 public IntentMap getHighLevelIntents() {
265 return highLevelIntents;
266 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800267
Ray Milkey269ffb92014-04-03 14:43:30 -0700268 @Override
269 public IntentMap getPathIntents() {
270 return pathIntents;
271 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800272
Ray Milkey269ffb92014-04-03 14:43:30 -0700273 @Override
274 public void purgeIntents() {
275 highLevelIntents.purge();
276 pathIntents.purge();
277 }
Toshio Koide0c9106d2014-02-19 15:26:38 -0800278
Ray Milkey269ffb92014-04-03 14:43:30 -0700279 // ================================================================================
Jonathan Harte37e4e22014-05-13 19:12:02 -0700280 // ITopologyListener implementations
Ray Milkey269ffb92014-04-03 14:43:30 -0700281 // ================================================================================
Toshio Koide798bc1b2014-02-20 14:02:40 -0800282
Ray Milkeya5450cc2014-04-17 14:31:30 -0700283 // CHECKSTYLE:OFF suppress warning about too many parameters
Ray Milkey269ffb92014-04-03 14:43:30 -0700284 @Override
Jonathan Harte37e4e22014-05-13 19:12:02 -0700285 public void topologyEvents(Collection<SwitchEvent> addedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700286 Collection<SwitchEvent> removedSwitchEvents,
287 Collection<PortEvent> addedPortEvents,
288 Collection<PortEvent> removedPortEvents,
289 Collection<LinkEvent> addedLinkEvents,
290 Collection<LinkEvent> removedLinkEvents,
291 Collection<DeviceEvent> addedDeviceEvents,
292 Collection<DeviceEvent> removedDeviceEvents) {
Ray Milkeya5450cc2014-04-17 14:31:30 -0700293 // CHECKSTYLE:ON
Toshio Koidea9078af2014-02-21 16:57:04 -0800294
Ray Milkey269ffb92014-04-03 14:43:30 -0700295 PerfLogger p = new PerfLogger("networkGraphEvents");
296 HashSet<Intent> affectedPaths = new HashSet<>();
Toshio Koide93797dc2014-02-27 23:54:26 -0800297
Ray Milkey269ffb92014-04-03 14:43:30 -0700298 boolean rerouteAll = false;
299 for (LinkEvent le : addedLinkEvents) {
300 LinkEvent rev = new LinkEvent(le.getDst().getDpid(), le.getDst().getNumber(), le.getSrc().getDpid(), le.getSrc().getNumber());
301 if (unmatchedLinkEvents.contains(rev)) {
302 rerouteAll = true;
303 unmatchedLinkEvents.remove(rev);
304 log.debug("Found matched LinkEvent: {} {}", rev, le);
305 } else {
306 unmatchedLinkEvents.add(le);
307 log.debug("Adding unmatched LinkEvent: {}", le);
308 }
309 }
310 for (LinkEvent le : removedLinkEvents) {
311 if (unmatchedLinkEvents.contains(le)) {
312 unmatchedLinkEvents.remove(le);
313 log.debug("Removing LinkEvent: {}", le);
314 }
315 }
316 if (unmatchedLinkEvents.size() > 0) {
317 log.debug("Unmatched link events: {} events", unmatchedLinkEvents.size());
318 }
Toshio Koidea9078af2014-02-21 16:57:04 -0800319
Ray Milkey7f1567c2014-04-08 13:53:32 -0700320 if (rerouteAll) { //addedLinkEvents.size() > 0) { // ||
Ray Milkey269ffb92014-04-03 14:43:30 -0700321// addedPortEvents.size() > 0 ||
322// addedSwitchEvents.size() > 0) {
323 p.log("begin_getAllIntents");
324 affectedPaths.addAll(getPathIntents().getAllIntents());
325 p.log("end_getAllIntents");
326 } else if (removedSwitchEvents.size() > 0 ||
327 removedLinkEvents.size() > 0 ||
328 removedPortEvents.size() > 0) {
329 p.log("begin_getIntentsByLink");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700330 for (LinkEvent linkEvent : removedLinkEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700331 affectedPaths.addAll(pathIntents.getIntentsByLink(linkEvent));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700332 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700333 p.log("end_getIntentsByLink");
Toshio Koidea9078af2014-02-21 16:57:04 -0800334
Ray Milkey269ffb92014-04-03 14:43:30 -0700335 p.log("begin_getIntentsByPort");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700336 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700337 affectedPaths.addAll(pathIntents.getIntentsByPort(portEvent.getDpid(), portEvent.getNumber()));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700338 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700339 p.log("end_getIntentsByPort");
Toshio Koidea9078af2014-02-21 16:57:04 -0800340
Ray Milkey269ffb92014-04-03 14:43:30 -0700341 p.log("begin_getIntentsByDpid");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700342 for (SwitchEvent switchEvent : removedSwitchEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700343 affectedPaths.addAll(pathIntents.getIntentsByDpid(switchEvent.getDpid()));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700344 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700345 p.log("end_getIntentsByDpid");
346 }
347 p.log("begin_reroutePaths");
348 reroutePaths(affectedPaths);
349 p.log("end_reroutePaths");
350 p.flushLog();
351 }
Toshio Koide066506e2014-02-20 19:52:09 -0800352
Ray Milkey269ffb92014-04-03 14:43:30 -0700353 // ================================================================================
354 // IEventChannelListener implementations
355 // ================================================================================
Toshio Koide066506e2014-02-20 19:52:09 -0800356
Ray Milkey269ffb92014-04-03 14:43:30 -0700357 @Override
358 public void entryAdded(IntentStateList value) {
359 entryUpdated(value);
360 }
Toshio Koide066506e2014-02-20 19:52:09 -0800361
Ray Milkey269ffb92014-04-03 14:43:30 -0700362 @Override
363 public void entryRemoved(IntentStateList value) {
364 // do nothing
365 }
Toshio Koide066506e2014-02-20 19:52:09 -0800366
Ray Milkey149693c2014-05-20 14:58:53 -0700367 @SuppressWarnings("fallthrough")
Ray Milkey269ffb92014-04-03 14:43:30 -0700368 @Override
369 public void entryUpdated(IntentStateList value) {
370 // TODO draw state transition diagram in multiple ONOS instances and update this method
TeruU9e530662014-05-18 11:49:37 -0700371
Ray Milkey269ffb92014-04-03 14:43:30 -0700372 lock.lock(); // TODO optimize locking using smaller steps
373 try {
TeruU9e530662014-05-18 11:49:37 -0700374 log.trace("lock entryUpdated, lock obj is already locked? {}", lock.isLocked());
Ray Milkey269ffb92014-04-03 14:43:30 -0700375 // reflect state changes of path-level intent into application-level intents
Ray Milkey269ffb92014-04-03 14:43:30 -0700376 IntentStateList highLevelIntentStates = new IntentStateList();
377 IntentStateList pathIntentStates = new IntentStateList();
378 for (Entry<String, IntentState> entry : value.entrySet()) {
379 PathIntent pathIntent = (PathIntent) pathIntents.getIntent(entry.getKey());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700380 if (pathIntent == null) {
381 continue;
382 }
Toshio Koide8315d7d2014-02-21 22:58:32 -0800383
Ray Milkey269ffb92014-04-03 14:43:30 -0700384 Intent parentIntent = pathIntent.getParentIntent();
385 if (parentIntent == null ||
386 !(parentIntent instanceof ShortestPathIntent) ||
Ray Milkeyb29e6262014-04-09 16:02:14 -0700387 !((ShortestPathIntent) parentIntent).getPathIntentId().equals(pathIntent.getId())) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700388 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700389 }
Toshio Koide066506e2014-02-20 19:52:09 -0800390
Ray Milkey269ffb92014-04-03 14:43:30 -0700391 IntentState state = entry.getValue();
392 switch (state) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700393 case INST_ACK:
TeruUf9111652014-05-14 23:10:35 -0700394 Set<Long> installedDpids = calcInstalledDpids(pathIntent, value.domainSwitchDpids);
395 if (!isFlowInstalled(pathIntent, installedDpids)) {
396 break;
397 }
398 // FALLTHROUGH
Ray Milkey269ffb92014-04-03 14:43:30 -0700399 case INST_NACK:
TeruUf9111652014-05-14 23:10:35 -0700400 // FALLTHROUGH
401 // case INST_REQ:
402 // FALLTHROUGH
403 // case DEL_REQ:
404 // FALLTHROUGH
Ray Milkey269ffb92014-04-03 14:43:30 -0700405 case DEL_PENDING:
TeruU9e530662014-05-18 11:49:37 -0700406 log.debug("put the state highLevelIntentStates ID {}, state {}", parentIntent.getId(), state);
Ray Milkey269ffb92014-04-03 14:43:30 -0700407 highLevelIntentStates.put(parentIntent.getId(), state);
TeruU9e530662014-05-18 11:49:37 -0700408 log.debug("put the state pathIntentStates ID {}, state {}", entry.getKey(), entry.getValue());
409 pathIntentStates.put(entry.getKey(), entry.getValue());
410 break;
411 case DEL_ACK:
412 if (intentInstalledMap.containsKey(parentIntent.getId())) {
413 intentInstalledMap.remove(parentIntent.getId());
414 }
415 log.debug("put the state highLevelIntentStates ID {}, state {}", parentIntent.getId(), state);
416 highLevelIntentStates.put(parentIntent.getId(), state);
417 log.debug("put the state pathIntentStates ID {}, state {}", entry.getKey(), entry.getValue());
Ray Milkey269ffb92014-04-03 14:43:30 -0700418 pathIntentStates.put(entry.getKey(), entry.getValue());
419 break;
420 default:
421 break;
422 }
423 }
424 highLevelIntents.changeStates(highLevelIntentStates);
425 pathIntents.changeStates(pathIntentStates);
Ray Milkey269ffb92014-04-03 14:43:30 -0700426 } finally {
Ray Milkey269ffb92014-04-03 14:43:30 -0700427 lock.unlock();
TeruU9e530662014-05-18 11:49:37 -0700428 log.trace("unlock entryUpdated");
Ray Milkey269ffb92014-04-03 14:43:30 -0700429 }
430 }
TeruUf9111652014-05-14 23:10:35 -0700431
432 /***
433 * This function is to check whether the entire path's flow entries are installed or not.
TeruU9e530662014-05-18 11:49:37 -0700434 *
TeruUf9111652014-05-14 23:10:35 -0700435 * @param pathIntent : The pathIntent to be checked
436 * @param installedDpids : The dpids installed on one ONOS instance
437 * @return The result of whether a pathIntent has been installed or not.
438 */
439 private boolean isFlowInstalled(PathIntent pathIntent, Set<Long> installedDpids) {
440 String parentIntentId = pathIntent.getParentIntent().getId();
441 log.debug("parentIntentId {}", parentIntentId);
442
443 if (intentInstalledMap.containsKey(parentIntentId)) {
444 if (!installedDpids.isEmpty()) {
445 intentInstalledMap.get(parentIntentId).addAll(installedDpids);
446 }
447 } else {
448 // This is the creation of an entry.
449 intentInstalledMap.put(parentIntentId, installedDpids);
450 }
451
452 Set<Long> allSwitchesForPath = new HashSet<Long>();
453 ShortestPathIntent spfIntent = (ShortestPathIntent) pathIntent.getParentIntent();
454
455 for (LinkEvent linkEvent : pathIntent.getPath()) {
456 long sw = linkEvent.getSrc().getDpid();
457 allSwitchesForPath.add(sw);
458 }
459 allSwitchesForPath.add(spfIntent.getDstSwitchDpid());
460
461 if (log.isTraceEnabled()) {
462 log.trace("All switches {}, installed installedDpids {}", allSwitchesForPath, intentInstalledMap.get(parentIntentId));
463 }
464
465 if (allSwitchesForPath.equals(intentInstalledMap.get(parentIntentId))) {
466 intentInstalledMap.remove(parentIntentId);
467 return true;
468 }
469
470 return false;
471 }
472
473 private Set<Long> calcInstalledDpids(PathIntent pathIntent, Set<Long> domainSwitchDpids) {
474 Set<Long> allSwitchesForPath = new HashSet<Long>();
475 ShortestPathIntent spfIntent = (ShortestPathIntent) pathIntent.getParentIntent();
476
477 for (LinkEvent linkEvent : pathIntent.getPath()) {
478 long sw = linkEvent.getSrc().getDpid();
479
480 if (domainSwitchDpids.contains(sw)) {
481 allSwitchesForPath.add(sw);
482 }
483 }
484
485 if (domainSwitchDpids.contains(spfIntent.getDstSwitchDpid())) {
486 allSwitchesForPath.add(spfIntent.getDstSwitchDpid());
487 }
488
489 if (log.isTraceEnabled()) {
TeruU9e530662014-05-18 11:49:37 -0700490 log.trace("All switches for a path {}, domain switch dpids {}", allSwitchesForPath, domainSwitchDpids);
TeruUf9111652014-05-14 23:10:35 -0700491 }
492
493 return allSwitchesForPath;
494 }
Toshio Koidea9078af2014-02-21 16:57:04 -0800495}