blob: 136a35729b57af1c8cae2e6b810696d9343bac4b [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;
92 private final ReentrantLock lock = new ReentrantLock();
93 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) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700176 if (list == null || list.size() == 0) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700177 return null;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700178 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700179 PerfLogger p = new PerfLogger("executeIntentOperations_" + list.get(0).operator);
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 {
183 // update the map of high-level intents
184 p.log("begin_updateInMemoryIntents");
185 highLevelIntents.executeOperations(list);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800186
Ray Milkey269ffb92014-04-03 14:43:30 -0700187 // change states of high-level intents
188 IntentStateList states = new IntentStateList();
189 for (IntentOperation op : list) {
190 switch (op.operator) {
191 case ADD:
192 switch (op.intent.getState()) {
193 case CREATED:
194 states.put(op.intent.getId(), IntentState.INST_REQ);
195 break;
196 case INST_ACK:
197 states.put(op.intent.getId(), IntentState.REROUTE_REQ);
198 break;
199 default:
200 break;
201 }
202 break;
203 case REMOVE:
204 switch (op.intent.getState()) {
205 case CREATED:
206 states.put(op.intent.getId(), IntentState.DEL_REQ);
207 break;
208 default:
209 break;
210 }
211 break;
212 default:
213 break;
214 }
215 }
216 highLevelIntents.changeStates(states);
217 p.log("end_updateInMemoryIntents");
Toshio Koidedf2eab92014-02-20 11:24:59 -0800218
Ray Milkey269ffb92014-04-03 14:43:30 -0700219 // calculate path-intents (low-level operations)
220 p.log("begin_calcPathIntents");
221 IntentOperationList pathIntentOperations = runtime.calcPathIntents(list, highLevelIntents, pathIntents);
222 p.log("end_calcPathIntents");
Toshio Koide600ae5f2014-02-20 18:42:00 -0800223
Ray Milkey269ffb92014-04-03 14:43:30 -0700224 // persist calculated low-level operations into data store
225 p.log("begin_persistPathIntents");
226 long key = persistIntent.getKey();
227 persistIntent.persistIfLeader(key, pathIntentOperations);
228 p.log("end_persistPathIntents");
Toshio Koide93be5d62014-02-23 19:30:57 -0800229
Ray Milkey269ffb92014-04-03 14:43:30 -0700230 // remove error-intents and reflect them to high-level intents
231 p.log("begin_removeErrorIntents");
232 states.clear();
233 Iterator<IntentOperation> i = pathIntentOperations.iterator();
234 while (i.hasNext()) {
235 IntentOperation op = i.next();
236 if (op.operator.equals(Operator.ERROR)) {
237 states.put(op.intent.getId(), IntentState.INST_NACK);
238 i.remove();
239 }
240 }
241 highLevelIntents.changeStates(states);
242 p.log("end_removeErrorIntents");
Toshio Koidea94060f2014-02-21 22:58:32 -0800243
Ray Milkey269ffb92014-04-03 14:43:30 -0700244 // update the map of path intents and publish the path operations
245 p.log("begin_updateInMemoryPathIntents");
246 pathIntents.executeOperations(pathIntentOperations);
247 p.log("end_updateInMemoryPathIntents");
Toshio Koide93be5d62014-02-23 19:30:57 -0800248
Ray Milkey269ffb92014-04-03 14:43:30 -0700249 // XXX Demo special: add a complete path to remove operation
250 p.log("begin_addPathToRemoveOperation");
251 for (IntentOperation op : pathIntentOperations) {
252 if (op.operator.equals(Operator.REMOVE)) {
253 op.intent = pathIntents.getIntent(op.intent.getId());
254 }
255 if (op.intent instanceof PathIntent) {
256 log.debug("operation: {}, intent:{}", op.operator, op.intent);
257 }
258 }
259 p.log("end_addPathToRemoveOperation");
Toshio Koide93be5d62014-02-23 19:30:57 -0800260
Ray Milkey269ffb92014-04-03 14:43:30 -0700261 // send notification
262 p.log("begin_sendNotification");
263 // XXX: Send notifications using the same key every time
264 // and receive them by entryAdded() and entryUpdated()
265 opEventChannel.addEntry(0L, pathIntentOperations);
266 p.log("end_sendNotification");
267 //opEventChannel.removeEntry(key);
268 return pathIntentOperations;
269 } finally {
Ray Milkey269ffb92014-04-03 14:43:30 -0700270 lock.unlock();
Pavlin Radoslavovc68974f2014-04-09 17:28:38 -0700271 p.flushLog();
Ray Milkey269ffb92014-04-03 14:43:30 -0700272 }
273 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800274
Ray Milkey269ffb92014-04-03 14:43:30 -0700275 @Override
276 public IntentMap getHighLevelIntents() {
277 return highLevelIntents;
278 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800279
Ray Milkey269ffb92014-04-03 14:43:30 -0700280 @Override
281 public IntentMap getPathIntents() {
282 return pathIntents;
283 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800284
Ray Milkey269ffb92014-04-03 14:43:30 -0700285 @Override
286 public void purgeIntents() {
287 highLevelIntents.purge();
288 pathIntents.purge();
289 }
Toshio Koide0c9106d2014-02-19 15:26:38 -0800290
Ray Milkey269ffb92014-04-03 14:43:30 -0700291 // ================================================================================
Jonathan Harte37e4e22014-05-13 19:12:02 -0700292 // ITopologyListener implementations
Ray Milkey269ffb92014-04-03 14:43:30 -0700293 // ================================================================================
Toshio Koide798bc1b2014-02-20 14:02:40 -0800294
Ray Milkeya5450cc2014-04-17 14:31:30 -0700295 // CHECKSTYLE:OFF suppress warning about too many parameters
Ray Milkey269ffb92014-04-03 14:43:30 -0700296 @Override
Jonathan Harte37e4e22014-05-13 19:12:02 -0700297 public void topologyEvents(Collection<SwitchEvent> addedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700298 Collection<SwitchEvent> removedSwitchEvents,
299 Collection<PortEvent> addedPortEvents,
300 Collection<PortEvent> removedPortEvents,
301 Collection<LinkEvent> addedLinkEvents,
302 Collection<LinkEvent> removedLinkEvents,
303 Collection<DeviceEvent> addedDeviceEvents,
304 Collection<DeviceEvent> removedDeviceEvents) {
Ray Milkeya5450cc2014-04-17 14:31:30 -0700305 // CHECKSTYLE:ON
Toshio Koidea9078af2014-02-21 16:57:04 -0800306
Ray Milkey269ffb92014-04-03 14:43:30 -0700307 PerfLogger p = new PerfLogger("networkGraphEvents");
308 HashSet<Intent> affectedPaths = new HashSet<>();
Toshio Koide93797dc2014-02-27 23:54:26 -0800309
Ray Milkey269ffb92014-04-03 14:43:30 -0700310 boolean rerouteAll = false;
311 for (LinkEvent le : addedLinkEvents) {
312 LinkEvent rev = new LinkEvent(le.getDst().getDpid(), le.getDst().getNumber(), le.getSrc().getDpid(), le.getSrc().getNumber());
313 if (unmatchedLinkEvents.contains(rev)) {
314 rerouteAll = true;
315 unmatchedLinkEvents.remove(rev);
316 log.debug("Found matched LinkEvent: {} {}", rev, le);
317 } else {
318 unmatchedLinkEvents.add(le);
319 log.debug("Adding unmatched LinkEvent: {}", le);
320 }
321 }
322 for (LinkEvent le : removedLinkEvents) {
323 if (unmatchedLinkEvents.contains(le)) {
324 unmatchedLinkEvents.remove(le);
325 log.debug("Removing LinkEvent: {}", le);
326 }
327 }
328 if (unmatchedLinkEvents.size() > 0) {
329 log.debug("Unmatched link events: {} events", unmatchedLinkEvents.size());
330 }
Toshio Koidea9078af2014-02-21 16:57:04 -0800331
Ray Milkey7f1567c2014-04-08 13:53:32 -0700332 if (rerouteAll) { //addedLinkEvents.size() > 0) { // ||
Ray Milkey269ffb92014-04-03 14:43:30 -0700333// addedPortEvents.size() > 0 ||
334// addedSwitchEvents.size() > 0) {
335 p.log("begin_getAllIntents");
336 affectedPaths.addAll(getPathIntents().getAllIntents());
337 p.log("end_getAllIntents");
338 } else if (removedSwitchEvents.size() > 0 ||
339 removedLinkEvents.size() > 0 ||
340 removedPortEvents.size() > 0) {
341 p.log("begin_getIntentsByLink");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700342 for (LinkEvent linkEvent : removedLinkEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700343 affectedPaths.addAll(pathIntents.getIntentsByLink(linkEvent));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700344 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700345 p.log("end_getIntentsByLink");
Toshio Koidea9078af2014-02-21 16:57:04 -0800346
Ray Milkey269ffb92014-04-03 14:43:30 -0700347 p.log("begin_getIntentsByPort");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700348 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700349 affectedPaths.addAll(pathIntents.getIntentsByPort(portEvent.getDpid(), portEvent.getNumber()));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700350 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700351 p.log("end_getIntentsByPort");
Toshio Koidea9078af2014-02-21 16:57:04 -0800352
Ray Milkey269ffb92014-04-03 14:43:30 -0700353 p.log("begin_getIntentsByDpid");
Ray Milkeyb29e6262014-04-09 16:02:14 -0700354 for (SwitchEvent switchEvent : removedSwitchEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700355 affectedPaths.addAll(pathIntents.getIntentsByDpid(switchEvent.getDpid()));
Ray Milkeyb29e6262014-04-09 16:02:14 -0700356 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700357 p.log("end_getIntentsByDpid");
358 }
359 p.log("begin_reroutePaths");
360 reroutePaths(affectedPaths);
361 p.log("end_reroutePaths");
362 p.flushLog();
363 }
Toshio Koide066506e2014-02-20 19:52:09 -0800364
Ray Milkey269ffb92014-04-03 14:43:30 -0700365 // ================================================================================
366 // IEventChannelListener implementations
367 // ================================================================================
Toshio Koide066506e2014-02-20 19:52:09 -0800368
Ray Milkey269ffb92014-04-03 14:43:30 -0700369 @Override
370 public void entryAdded(IntentStateList value) {
371 entryUpdated(value);
372 }
Toshio Koide066506e2014-02-20 19:52:09 -0800373
Ray Milkey269ffb92014-04-03 14:43:30 -0700374 @Override
375 public void entryRemoved(IntentStateList value) {
376 // do nothing
377 }
Toshio Koide066506e2014-02-20 19:52:09 -0800378
Ray Milkey149693c2014-05-20 14:58:53 -0700379 @SuppressWarnings("fallthrough")
Ray Milkey269ffb92014-04-03 14:43:30 -0700380 @Override
381 public void entryUpdated(IntentStateList value) {
382 // TODO draw state transition diagram in multiple ONOS instances and update this method
383 PerfLogger p = new PerfLogger("entryUpdated");
384 lock.lock(); // TODO optimize locking using smaller steps
385 try {
386 // reflect state changes of path-level intent into application-level intents
387 p.log("begin_changeStateByNotification");
388 IntentStateList highLevelIntentStates = new IntentStateList();
389 IntentStateList pathIntentStates = new IntentStateList();
390 for (Entry<String, IntentState> entry : value.entrySet()) {
391 PathIntent pathIntent = (PathIntent) pathIntents.getIntent(entry.getKey());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700392 if (pathIntent == null) {
393 continue;
394 }
Toshio Koide8315d7d2014-02-21 22:58:32 -0800395
Ray Milkey269ffb92014-04-03 14:43:30 -0700396 Intent parentIntent = pathIntent.getParentIntent();
397 if (parentIntent == null ||
398 !(parentIntent instanceof ShortestPathIntent) ||
Ray Milkeyb29e6262014-04-09 16:02:14 -0700399 !((ShortestPathIntent) parentIntent).getPathIntentId().equals(pathIntent.getId())) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700400 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700401 }
Toshio Koide066506e2014-02-20 19:52:09 -0800402
Ray Milkey269ffb92014-04-03 14:43:30 -0700403 IntentState state = entry.getValue();
TeruUf9111652014-05-14 23:10:35 -0700404 log.debug("put the state pathIntentStates ID {}, state {}", entry.getKey(), state);
405
Ray Milkey269ffb92014-04-03 14:43:30 -0700406 switch (state) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700407 case INST_ACK:
TeruUf9111652014-05-14 23:10:35 -0700408 Set<Long> installedDpids = calcInstalledDpids(pathIntent, value.domainSwitchDpids);
409 if (!isFlowInstalled(pathIntent, installedDpids)) {
410 break;
411 }
412 // FALLTHROUGH
Ray Milkey269ffb92014-04-03 14:43:30 -0700413 case INST_NACK:
TeruUf9111652014-05-14 23:10:35 -0700414 // FALLTHROUGH
415 // case INST_REQ:
416 // FALLTHROUGH
417 // case DEL_REQ:
418 // FALLTHROUGH
Ray Milkey269ffb92014-04-03 14:43:30 -0700419 case DEL_ACK:
TeruUf9111652014-05-14 23:10:35 -0700420 // FALLTHROUGH
Ray Milkey269ffb92014-04-03 14:43:30 -0700421 case DEL_PENDING:
422 highLevelIntentStates.put(parentIntent.getId(), state);
423 pathIntentStates.put(entry.getKey(), entry.getValue());
424 break;
425 default:
426 break;
427 }
428 }
429 highLevelIntents.changeStates(highLevelIntentStates);
430 pathIntents.changeStates(pathIntentStates);
431 p.log("end_changeStateByNotification");
432 } finally {
Ray Milkey269ffb92014-04-03 14:43:30 -0700433 lock.unlock();
Pavlin Radoslavovc68974f2014-04-09 17:28:38 -0700434 p.flushLog();
Ray Milkey269ffb92014-04-03 14:43:30 -0700435 }
436 }
TeruUf9111652014-05-14 23:10:35 -0700437
438 /***
439 * This function is to check whether the entire path's flow entries are installed or not.
440 * @param pathIntent : The pathIntent to be checked
441 * @param installedDpids : The dpids installed on one ONOS instance
442 * @return The result of whether a pathIntent has been installed or not.
443 */
444 private boolean isFlowInstalled(PathIntent pathIntent, Set<Long> installedDpids) {
445 String parentIntentId = pathIntent.getParentIntent().getId();
446 log.debug("parentIntentId {}", parentIntentId);
447
448 if (intentInstalledMap.containsKey(parentIntentId)) {
449 if (!installedDpids.isEmpty()) {
450 intentInstalledMap.get(parentIntentId).addAll(installedDpids);
451 }
452 } else {
453 // This is the creation of an entry.
454 intentInstalledMap.put(parentIntentId, installedDpids);
455 }
456
457 Set<Long> allSwitchesForPath = new HashSet<Long>();
458 ShortestPathIntent spfIntent = (ShortestPathIntent) pathIntent.getParentIntent();
459
460 for (LinkEvent linkEvent : pathIntent.getPath()) {
461 long sw = linkEvent.getSrc().getDpid();
462 allSwitchesForPath.add(sw);
463 }
464 allSwitchesForPath.add(spfIntent.getDstSwitchDpid());
465
466 if (log.isTraceEnabled()) {
467 log.trace("All switches {}, installed installedDpids {}", allSwitchesForPath, intentInstalledMap.get(parentIntentId));
468 }
469
470 if (allSwitchesForPath.equals(intentInstalledMap.get(parentIntentId))) {
471 intentInstalledMap.remove(parentIntentId);
472 return true;
473 }
474
475 return false;
476 }
477
478 private Set<Long> calcInstalledDpids(PathIntent pathIntent, Set<Long> domainSwitchDpids) {
479 Set<Long> allSwitchesForPath = new HashSet<Long>();
480 ShortestPathIntent spfIntent = (ShortestPathIntent) pathIntent.getParentIntent();
481
482 for (LinkEvent linkEvent : pathIntent.getPath()) {
483 long sw = linkEvent.getSrc().getDpid();
484
485 if (domainSwitchDpids.contains(sw)) {
486 allSwitchesForPath.add(sw);
487 }
488 }
489
490 if (domainSwitchDpids.contains(spfIntent.getDstSwitchDpid())) {
491 allSwitchesForPath.add(spfIntent.getDstSwitchDpid());
492 }
493
494 if (log.isTraceEnabled()) {
495 log.trace("All switches {}, domain switch dpids {}", allSwitchesForPath, domainSwitchDpids);
496 }
497
498 return allSwitchesForPath;
499 }
Toshio Koidea9078af2014-02-21 16:57:04 -0800500}