blob: 042f08bffdf1b0029ab17850fff4597a11ab4108 [file] [log] [blame]
Toshio Koide4f308732014-02-18 15:19:48 -08001package net.onrc.onos.intent.runtime;
2
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 Koide4f308732014-02-18 15:19:48 -08008import java.util.Map;
Toshio Koide066506e2014-02-20 19:52:09 -08009import java.util.Map.Entry;
Toshio Koide4f308732014-02-18 15:19:48 -080010
Toshio Koidea94060f2014-02-21 22:58:32 -080011import org.slf4j.Logger;
12import org.slf4j.LoggerFactory;
13
Toshio Koide4f308732014-02-18 15:19:48 -080014import net.floodlightcontroller.core.module.FloodlightModuleContext;
15import net.floodlightcontroller.core.module.FloodlightModuleException;
16import net.floodlightcontroller.core.module.IFloodlightModule;
17import net.floodlightcontroller.core.module.IFloodlightService;
18import net.onrc.onos.datagrid.IDatagridService;
19import net.onrc.onos.datagrid.IEventChannel;
Toshio Koide066506e2014-02-20 19:52:09 -080020import net.onrc.onos.datagrid.IEventChannelListener;
21import net.onrc.onos.intent.Intent;
Toshio Koidedf2eab92014-02-20 11:24:59 -080022import net.onrc.onos.intent.Intent.IntentState;
Toshio Koide4f308732014-02-18 15:19:48 -080023import net.onrc.onos.intent.IntentMap;
Toshio Koidedf2eab92014-02-20 11:24:59 -080024import net.onrc.onos.intent.IntentOperation;
Toshio Koide0c9106d2014-02-19 15:26:38 -080025import net.onrc.onos.intent.IntentOperation.Operator;
Toshio Koide4f308732014-02-18 15:19:48 -080026import net.onrc.onos.intent.IntentOperationList;
Toshio Koide0c9106d2014-02-19 15:26:38 -080027import net.onrc.onos.intent.PathIntent;
Toshio Koide4f308732014-02-18 15:19:48 -080028import net.onrc.onos.intent.PathIntentMap;
Toshio Koide066506e2014-02-20 19:52:09 -080029import net.onrc.onos.intent.ShortestPathIntent;
Toshio Koidedf2eab92014-02-20 11:24:59 -080030import net.onrc.onos.intent.persist.PersistIntent;
Toshio Koide0c9106d2014-02-19 15:26:38 -080031import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
32import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphListener;
Toshio Koide27ffd412014-02-18 19:15:27 -080033import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
Toshio Koide0c9106d2014-02-19 15:26:38 -080034import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
35import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
36import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
Nick Karanatsios8abe7172014-02-19 20:31:48 -080037import net.onrc.onos.registry.controller.IControllerRegistryService;
Toshio Koide4f308732014-02-18 15:19:48 -080038
Toshio Koide0c9106d2014-02-19 15:26:38 -080039/**
40 * @author Toshio Koide (t-koide@onlab.us)
41 */
Toshio Koide066506e2014-02-20 19:52:09 -080042public class PathCalcRuntimeModule implements IFloodlightModule, IPathCalcRuntimeService, INetworkGraphListener, IEventChannelListener<Long, IntentStateList> {
Toshio Koide4f308732014-02-18 15:19:48 -080043 private PathCalcRuntime runtime;
44 private IDatagridService datagridService;
Toshio Koide27ffd412014-02-18 19:15:27 -080045 private INetworkGraphService networkGraphService;
Toshio Koide4f308732014-02-18 15:19:48 -080046 private IntentMap highLevelIntents;
Toshio Koide27ffd412014-02-18 19:15:27 -080047 private PathIntentMap pathIntents;
Toshio Koide798bc1b2014-02-20 14:02:40 -080048 private IControllerRegistryService controllerRegistry;
49 private PersistIntent persistIntent;
Toshio Koide27ffd412014-02-18 19:15:27 -080050
Toshio Koide066506e2014-02-20 19:52:09 -080051 private IEventChannel<Long, IntentOperationList> opEventChannel;
52 private static final String INTENT_OP_EVENT_CHANNEL_NAME = "onos.pathintent";
53 private static final String INTENT_STATE_EVENT_CHANNEL_NAME = "onos.pathintent_state";
Toshio Koidea94060f2014-02-21 22:58:32 -080054 private static final Logger log = LoggerFactory.getLogger(PathCalcRuntimeModule.class);
Toshio Koide4f308732014-02-18 15:19:48 -080055
Toshio Koide798bc1b2014-02-20 14:02:40 -080056 // ================================================================================
57 // private methods
58 // ================================================================================
59
Toshio Koidea94060f2014-02-21 22:58:32 -080060 private void reroutePaths(Collection<Intent> oldPaths) {
Toshio Koidea9078af2014-02-21 16:57:04 -080061 if (oldPaths == null || oldPaths.isEmpty())
Toshio Koide798bc1b2014-02-20 14:02:40 -080062 return;
Toshio Koidea10c0372014-02-20 17:28:10 -080063
Toshio Koide0c9106d2014-02-19 15:26:38 -080064 IntentOperationList reroutingOperation = new IntentOperationList();
Toshio Koide982c81f2014-02-23 16:53:10 -080065 for (Intent intent : oldPaths) {
66 PathIntent pathIntent = (PathIntent) intent;
67 if (pathIntent.getState().equals(IntentState.INST_ACK) &&
68 !reroutingOperation.contains(pathIntent)) {
69 reroutingOperation.add(Operator.ADD, pathIntent.getParentIntent());
70 }
Toshio Koide0c9106d2014-02-19 15:26:38 -080071 }
Toshio Koide8315d7d2014-02-21 22:58:32 -080072 executeIntentOperations(reroutingOperation);
Toshio Koidea94060f2014-02-21 22:58:32 -080073 }
74
75 private void log(String step) {
76 log.error("Step:{}, Time:{}", step, System.nanoTime());
Toshio Koide0c9106d2014-02-19 15:26:38 -080077 }
Toshio Koide27ffd412014-02-18 19:15:27 -080078
Toshio Koide798bc1b2014-02-20 14:02:40 -080079 // ================================================================================
80 // IFloodlightModule implementations
81 // ================================================================================
82
Toshio Koide4f308732014-02-18 15:19:48 -080083 @Override
84 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
85 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(1);
Toshio Koideeb90d912014-02-18 21:30:22 -080086 l.add(IPathCalcRuntimeService.class);
Toshio Koide4f308732014-02-18 15:19:48 -080087 return l;
88 }
89
90 @Override
91 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Toshio Koidea9078af2014-02-21 16:57:04 -080092 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
Toshio Koide27ffd412014-02-18 19:15:27 -080093 m.put(IPathCalcRuntimeService.class, this);
Toshio Koide4f308732014-02-18 15:19:48 -080094 return m;
95 }
96
97 @Override
98 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Toshio Koidea9078af2014-02-21 16:57:04 -080099 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(2);
Toshio Koide4f308732014-02-18 15:19:48 -0800100 l.add(IDatagridService.class);
Toshio Koide27ffd412014-02-18 19:15:27 -0800101 l.add(INetworkGraphService.class);
Toshio Koide4f308732014-02-18 15:19:48 -0800102 return l;
103 }
104
105 @Override
106 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
107 datagridService = context.getServiceImpl(IDatagridService.class);
Toshio Koided9fa2a82014-02-19 17:35:18 -0800108 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
Toshio Koide798bc1b2014-02-20 14:02:40 -0800109 controllerRegistry = context.getServiceImpl(IControllerRegistryService.class);
Toshio Koide4f308732014-02-18 15:19:48 -0800110 }
111
112 @Override
113 public void startUp(FloodlightModuleContext context) {
Toshio Koideeb90d912014-02-18 21:30:22 -0800114 highLevelIntents = new IntentMap();
115 runtime = new PathCalcRuntime(networkGraphService.getNetworkGraph());
Toshio Koide0c9106d2014-02-19 15:26:38 -0800116 pathIntents = new PathIntentMap();
Toshio Koide066506e2014-02-20 19:52:09 -0800117 opEventChannel = datagridService.createChannel(INTENT_OP_EVENT_CHANNEL_NAME, Long.class, IntentOperationList.class);
118 datagridService.addListener(INTENT_STATE_EVENT_CHANNEL_NAME, this, Long.class, IntentStateList.class);
Toshio Koide0c9106d2014-02-19 15:26:38 -0800119 networkGraphService.registerNetworkGraphListener(this);
Toshio Koide798bc1b2014-02-20 14:02:40 -0800120 persistIntent = new PersistIntent(controllerRegistry, networkGraphService);
Toshio Koide4f308732014-02-18 15:19:48 -0800121 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800122
Toshio Koide798bc1b2014-02-20 14:02:40 -0800123 // ================================================================================
124 // IPathCalcRuntimeService implementations
125 // ================================================================================
126
Toshio Koide27ffd412014-02-18 19:15:27 -0800127 @Override
128 public IntentOperationList executeIntentOperations(IntentOperationList list) {
Toshio Koidedf2eab92014-02-20 11:24:59 -0800129 // update the map of high-level intents
Toshio Koidea94060f2014-02-21 22:58:32 -0800130 log("begin_updateInMemoryIntents");
Toshio Koide27ffd412014-02-18 19:15:27 -0800131 highLevelIntents.executeOperations(list);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800132
Toshio Koidea10c0372014-02-20 17:28:10 -0800133 // change states of high-level intents
Toshio Koide066506e2014-02-20 19:52:09 -0800134 IntentStateList states = new IntentStateList();
Toshio Koide798bc1b2014-02-20 14:02:40 -0800135 for (IntentOperation op : list) {
Toshio Koidea10c0372014-02-20 17:28:10 -0800136 if (op.intent.getState().equals(IntentState.INST_ACK))
Toshio Koided7476d02014-02-22 15:59:04 -0800137 states.put(op.intent.getId(), IntentState.REROUTE_REQ);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800138 }
Toshio Koidea10c0372014-02-20 17:28:10 -0800139 highLevelIntents.changeStates(states);
Toshio Koidea94060f2014-02-21 22:58:32 -0800140 log("end_updateInMemoryIntents");
Toshio Koidedf2eab92014-02-20 11:24:59 -0800141
142 // calculate path-intents (low-level operations)
Toshio Koidea94060f2014-02-21 22:58:32 -0800143 log("begin_calcPathIntents");
Toshio Koidedba6fef2014-02-23 15:36:21 -0800144 IntentOperationList pathIntentOperations = runtime.calcPathIntents(list, highLevelIntents, pathIntents);
Toshio Koidea94060f2014-02-21 22:58:32 -0800145 log("end_calcPathIntents");
Toshio Koidedf2eab92014-02-20 11:24:59 -0800146
Toshio Koidea10c0372014-02-20 17:28:10 -0800147 // persist calculated low-level operations into data store
Toshio Koidea94060f2014-02-21 22:58:32 -0800148 log("begin_persistPathIntents");
Nick Karanatsios8abe7172014-02-19 20:31:48 -0800149 long key = persistIntent.getKey();
Toshio Koidedf2eab92014-02-20 11:24:59 -0800150 persistIntent.persistIfLeader(key, pathIntentOperations);
Toshio Koidea94060f2014-02-21 22:58:32 -0800151 log("end_persistPathIntents");
Toshio Koidedf2eab92014-02-20 11:24:59 -0800152
153 // remove error-intents and reflect them to high-level intents
Toshio Koidea94060f2014-02-21 22:58:32 -0800154 log("begin_removeErrorIntents");
Toshio Koidea10c0372014-02-20 17:28:10 -0800155 states.clear();
Toshio Koidedf2eab92014-02-20 11:24:59 -0800156 Iterator<IntentOperation> i = pathIntentOperations.iterator();
157 while (i.hasNext()) {
158 IntentOperation op = i.next();
159 if (op.operator.equals(Operator.ERROR)) {
160 states.put(op.intent.getId(), IntentState.INST_NACK);
161 i.remove();
162 }
163 }
164 highLevelIntents.changeStates(states);
Toshio Koidea94060f2014-02-21 22:58:32 -0800165 log("end_removeErrorIntents");
Toshio Koidedf2eab92014-02-20 11:24:59 -0800166
Toshio Koidea94060f2014-02-21 22:58:32 -0800167 // update the map of path intents and publish the path operations
168 log("begin_updateInMemoryPathIntents");
Toshio Koide27ffd412014-02-18 19:15:27 -0800169 pathIntents.executeOperations(pathIntentOperations);
Toshio Koidea94060f2014-02-21 22:58:32 -0800170 log("end_updateInMemoryPathIntents");
Toshio Koide600ae5f2014-02-20 18:42:00 -0800171
Toshio Koidea94060f2014-02-21 22:58:32 -0800172 // Demo special: add a complete path to remove operation
173 log("begin_addPathToRemoveOperation");
Toshio Koide600ae5f2014-02-20 18:42:00 -0800174 for (IntentOperation op: pathIntentOperations) {
175 if(op.operator.equals(Operator.REMOVE)) {
176 op.intent = pathIntents.getIntent(op.intent.getId());
177 }
178 }
Toshio Koidea94060f2014-02-21 22:58:32 -0800179 log("end_addPathToRemoveOperation");
180
181 // send notification
182 log("begin_sendNotification");
Toshio Koide066506e2014-02-20 19:52:09 -0800183 opEventChannel.addEntry(key, pathIntentOperations);
Toshio Koidea94060f2014-02-21 22:58:32 -0800184 log("end_sendNotification");
Toshio Koide27ffd412014-02-18 19:15:27 -0800185 return pathIntentOperations;
186 }
187
188 @Override
189 public IntentMap getHighLevelIntents() {
Toshio Koide4f308732014-02-18 15:19:48 -0800190 return highLevelIntents;
191 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800192
193 @Override
194 public IntentMap getPathIntents() {
195 return pathIntents;
196 }
197
198 @Override
Toshio Koide4f308732014-02-18 15:19:48 -0800199 public void purgeIntents() {
200 highLevelIntents.purge();
Toshio Koide27ffd412014-02-18 19:15:27 -0800201 pathIntents.purge();
Toshio Koide4f308732014-02-18 15:19:48 -0800202 }
Toshio Koide0c9106d2014-02-19 15:26:38 -0800203
Toshio Koide798bc1b2014-02-20 14:02:40 -0800204 // ================================================================================
205 // INetworkGraphListener implementations
206 // ================================================================================
207
Toshio Koide0c9106d2014-02-19 15:26:38 -0800208 @Override
Toshio Koide798bc1b2014-02-20 14:02:40 -0800209 public void networkGraphEvents(Collection<SwitchEvent> addedSwitchEvents,
210 Collection<SwitchEvent> removedSwitchEvents,
211 Collection<PortEvent> addedPortEvents,
212 Collection<PortEvent> removedPortEvents,
213 Collection<LinkEvent> addedLinkEvents,
214 Collection<LinkEvent> removedLinkEvents,
215 Collection<DeviceEvent> addedDeviceEvents,
216 Collection<DeviceEvent> removedDeviceEvents) {
Toshio Koidea9078af2014-02-21 16:57:04 -0800217
Toshio Koidea94060f2014-02-21 22:58:32 -0800218 log("called_networkGraphEvents");
219 HashSet<Intent> affectedPaths = new HashSet<>();
Toshio Koidea9078af2014-02-21 16:57:04 -0800220
Toshio Koidea94060f2014-02-21 22:58:32 -0800221 if (addedLinkEvents.size() > 0 ||
222 addedPortEvents.size() > 0 ||
223 addedSwitchEvents.size() > 0) {
224 log("begin_getAllIntents");
225 affectedPaths.addAll(getPathIntents().getAllIntents());
226 log("end_getAllIntents");
227 }
228 else {
229 log("begin_getIntentsByLink");
230 for (LinkEvent linkEvent: removedLinkEvents)
231 affectedPaths.addAll(pathIntents.getIntentsByLink(linkEvent));
232 log("end_getIntentsByLink");
Toshio Koidea9078af2014-02-21 16:57:04 -0800233
Toshio Koidea94060f2014-02-21 22:58:32 -0800234 log("begin_getIntentsByPort");
235 for (PortEvent portEvent: removedPortEvents)
236 affectedPaths.addAll(pathIntents.getIntentsByPort(portEvent.getDpid(), portEvent.getNumber()));
237 log("end_getIntentsByPort");
Toshio Koidea9078af2014-02-21 16:57:04 -0800238
Toshio Koidea94060f2014-02-21 22:58:32 -0800239 log("begin_getIntentsByDpid");
240 for (SwitchEvent switchEvent: removedSwitchEvents)
241 affectedPaths.addAll(pathIntents.getIntentsByDpid(switchEvent.getDpid()));
242 log("end_getIntentsByDpid");
243 }
Toshio Koidea9078af2014-02-21 16:57:04 -0800244 reroutePaths(affectedPaths);
Toshio Koidea94060f2014-02-21 22:58:32 -0800245 log("finished_networkGraphEvents");
Toshio Koide0c9106d2014-02-19 15:26:38 -0800246 }
Toshio Koide066506e2014-02-20 19:52:09 -0800247
248 // ================================================================================
249 // IEventChannelListener implementations
250 // ================================================================================
251
252 @Override
253 public void entryAdded(IntentStateList value) {
Toshio Koidea94060f2014-02-21 22:58:32 -0800254 log("called_EntryAdded");
Toshio Koide066506e2014-02-20 19:52:09 -0800255 entryUpdated(value);
256 }
257
258 @Override
259 public void entryRemoved(IntentStateList value) {
260 // do nothing
261 }
262
263 @Override
264 public void entryUpdated(IntentStateList value) {
Toshio Koide8315d7d2014-02-21 22:58:32 -0800265 // TODO draw state transition diagram in multiple ONOS instances and update this method
266
Toshio Koidea94060f2014-02-21 22:58:32 -0800267 log("called_EntryUpdated");
Toshio Koide066506e2014-02-20 19:52:09 -0800268 // reflect state changes of path-level intent into application-level intents
Toshio Koidea94060f2014-02-21 22:58:32 -0800269 log("begin_changeStateByNotification");
Toshio Koide066506e2014-02-20 19:52:09 -0800270 IntentStateList parentStates = new IntentStateList();
271 for (Entry<String, IntentState> entry: value.entrySet()) {
272 PathIntent pathIntent = (PathIntent) pathIntents.getIntent(entry.getKey());
273 if (pathIntent == null) continue;
274
275 Intent parentIntent = pathIntent.getParentIntent();
276 if (parentIntent == null ||
277 !(parentIntent instanceof ShortestPathIntent) ||
278 !((ShortestPathIntent) parentIntent).getPathIntentId().equals(pathIntent.getId()))
279 continue;
280
281 IntentState state = entry.getValue();
282 switch (state) {
Toshio Koide982c81f2014-02-23 16:53:10 -0800283 case INST_REQ:
Toshio Koide066506e2014-02-20 19:52:09 -0800284 case INST_ACK:
285 case INST_NACK:
Toshio Koide982c81f2014-02-23 16:53:10 -0800286 case DEL_REQ:
Toshio Koide066506e2014-02-20 19:52:09 -0800287 case DEL_ACK:
288 case DEL_PENDING:
289 parentStates.put(parentIntent.getId(), state);
290 break;
291 default:
292 break;
293 }
294 }
295 highLevelIntents.changeStates(parentStates);
296 pathIntents.changeStates(value);
Toshio Koidea94060f2014-02-21 22:58:32 -0800297 log("end_changeStateByNotification");
Toshio Koide066506e2014-02-20 19:52:09 -0800298 }
Toshio Koidea9078af2014-02-21 16:57:04 -0800299}