blob: 8cb935f7a7f6cf02a50ee35a512557d394353063 [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
11import net.floodlightcontroller.core.module.FloodlightModuleContext;
12import net.floodlightcontroller.core.module.FloodlightModuleException;
13import net.floodlightcontroller.core.module.IFloodlightModule;
14import net.floodlightcontroller.core.module.IFloodlightService;
15import net.onrc.onos.datagrid.IDatagridService;
16import net.onrc.onos.datagrid.IEventChannel;
Toshio Koide066506e2014-02-20 19:52:09 -080017import net.onrc.onos.datagrid.IEventChannelListener;
18import net.onrc.onos.intent.Intent;
Toshio Koidedf2eab92014-02-20 11:24:59 -080019import net.onrc.onos.intent.Intent.IntentState;
Toshio Koide4f308732014-02-18 15:19:48 -080020import net.onrc.onos.intent.IntentMap;
Toshio Koidedf2eab92014-02-20 11:24:59 -080021import net.onrc.onos.intent.IntentOperation;
Toshio Koide0c9106d2014-02-19 15:26:38 -080022import net.onrc.onos.intent.IntentOperation.Operator;
Toshio Koide4f308732014-02-18 15:19:48 -080023import net.onrc.onos.intent.IntentOperationList;
Toshio Koide0c9106d2014-02-19 15:26:38 -080024import net.onrc.onos.intent.PathIntent;
Toshio Koide4f308732014-02-18 15:19:48 -080025import net.onrc.onos.intent.PathIntentMap;
Toshio Koide066506e2014-02-20 19:52:09 -080026import net.onrc.onos.intent.ShortestPathIntent;
Toshio Koidedf2eab92014-02-20 11:24:59 -080027import net.onrc.onos.intent.persist.PersistIntent;
Toshio Koide0c9106d2014-02-19 15:26:38 -080028import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
29import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphListener;
Toshio Koide27ffd412014-02-18 19:15:27 -080030import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
Toshio Koide0c9106d2014-02-19 15:26:38 -080031import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
32import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
33import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
Nick Karanatsios8abe7172014-02-19 20:31:48 -080034import net.onrc.onos.registry.controller.IControllerRegistryService;
Toshio Koide4f308732014-02-18 15:19:48 -080035
Toshio Koide0c9106d2014-02-19 15:26:38 -080036/**
37 * @author Toshio Koide (t-koide@onlab.us)
38 */
Toshio Koide066506e2014-02-20 19:52:09 -080039public class PathCalcRuntimeModule implements IFloodlightModule, IPathCalcRuntimeService, INetworkGraphListener, IEventChannelListener<Long, IntentStateList> {
Toshio Koide4f308732014-02-18 15:19:48 -080040 private PathCalcRuntime runtime;
41 private IDatagridService datagridService;
Toshio Koide27ffd412014-02-18 19:15:27 -080042 private INetworkGraphService networkGraphService;
Toshio Koide4f308732014-02-18 15:19:48 -080043 private IntentMap highLevelIntents;
Toshio Koide27ffd412014-02-18 19:15:27 -080044 private PathIntentMap pathIntents;
Toshio Koide798bc1b2014-02-20 14:02:40 -080045 private IControllerRegistryService controllerRegistry;
46 private PersistIntent persistIntent;
Toshio Koide27ffd412014-02-18 19:15:27 -080047
Toshio Koide066506e2014-02-20 19:52:09 -080048 private IEventChannel<Long, IntentOperationList> opEventChannel;
49 private static final String INTENT_OP_EVENT_CHANNEL_NAME = "onos.pathintent";
50 private static final String INTENT_STATE_EVENT_CHANNEL_NAME = "onos.pathintent_state";
Toshio Koide4f308732014-02-18 15:19:48 -080051
Toshio Koide798bc1b2014-02-20 14:02:40 -080052 // ================================================================================
53 // private methods
54 // ================================================================================
55
Toshio Koidea9078af2014-02-21 16:57:04 -080056 private void reroutePaths(Collection<PathIntent> oldPaths) {
57 if (oldPaths == null || oldPaths.isEmpty())
Toshio Koide798bc1b2014-02-20 14:02:40 -080058 return;
Toshio Koidea10c0372014-02-20 17:28:10 -080059
Toshio Koide0c9106d2014-02-19 15:26:38 -080060 IntentOperationList reroutingOperation = new IntentOperationList();
Toshio Koide798bc1b2014-02-20 14:02:40 -080061 for (PathIntent pathIntent : oldPaths) {
Toshio Koide0c9106d2014-02-19 15:26:38 -080062 reroutingOperation.add(Operator.ADD, pathIntent.getParentIntent());
63 }
64 executeIntentOperations(reroutingOperation);
65 }
Toshio Koide27ffd412014-02-18 19:15:27 -080066
Toshio Koide798bc1b2014-02-20 14:02:40 -080067 // ================================================================================
68 // IFloodlightModule implementations
69 // ================================================================================
70
Toshio Koide4f308732014-02-18 15:19:48 -080071 @Override
72 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
73 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(1);
Toshio Koideeb90d912014-02-18 21:30:22 -080074 l.add(IPathCalcRuntimeService.class);
Toshio Koide4f308732014-02-18 15:19:48 -080075 return l;
76 }
77
78 @Override
79 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Toshio Koidea9078af2014-02-21 16:57:04 -080080 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>();
Toshio Koide27ffd412014-02-18 19:15:27 -080081 m.put(IPathCalcRuntimeService.class, this);
Toshio Koide4f308732014-02-18 15:19:48 -080082 return m;
83 }
84
85 @Override
86 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Toshio Koidea9078af2014-02-21 16:57:04 -080087 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(2);
Toshio Koide4f308732014-02-18 15:19:48 -080088 l.add(IDatagridService.class);
Toshio Koide27ffd412014-02-18 19:15:27 -080089 l.add(INetworkGraphService.class);
Toshio Koide4f308732014-02-18 15:19:48 -080090 return l;
91 }
92
93 @Override
94 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
95 datagridService = context.getServiceImpl(IDatagridService.class);
Toshio Koided9fa2a82014-02-19 17:35:18 -080096 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
Toshio Koide798bc1b2014-02-20 14:02:40 -080097 controllerRegistry = context.getServiceImpl(IControllerRegistryService.class);
Toshio Koide4f308732014-02-18 15:19:48 -080098 }
99
100 @Override
101 public void startUp(FloodlightModuleContext context) {
Toshio Koideeb90d912014-02-18 21:30:22 -0800102 highLevelIntents = new IntentMap();
103 runtime = new PathCalcRuntime(networkGraphService.getNetworkGraph());
Toshio Koide0c9106d2014-02-19 15:26:38 -0800104 pathIntents = new PathIntentMap();
Toshio Koide066506e2014-02-20 19:52:09 -0800105 opEventChannel = datagridService.createChannel(INTENT_OP_EVENT_CHANNEL_NAME, Long.class, IntentOperationList.class);
106 datagridService.addListener(INTENT_STATE_EVENT_CHANNEL_NAME, this, Long.class, IntentStateList.class);
Toshio Koide0c9106d2014-02-19 15:26:38 -0800107 networkGraphService.registerNetworkGraphListener(this);
Toshio Koide798bc1b2014-02-20 14:02:40 -0800108 persistIntent = new PersistIntent(controllerRegistry, networkGraphService);
Toshio Koide4f308732014-02-18 15:19:48 -0800109 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800110
Toshio Koide798bc1b2014-02-20 14:02:40 -0800111 // ================================================================================
112 // IPathCalcRuntimeService implementations
113 // ================================================================================
114
Toshio Koide27ffd412014-02-18 19:15:27 -0800115 @Override
116 public IntentOperationList executeIntentOperations(IntentOperationList list) {
Toshio Koidedf2eab92014-02-20 11:24:59 -0800117 // update the map of high-level intents
Toshio Koide27ffd412014-02-18 19:15:27 -0800118 highLevelIntents.executeOperations(list);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800119
Toshio Koidea10c0372014-02-20 17:28:10 -0800120 // change states of high-level intents
Toshio Koide066506e2014-02-20 19:52:09 -0800121 IntentStateList states = new IntentStateList();
Toshio Koide798bc1b2014-02-20 14:02:40 -0800122 for (IntentOperation op : list) {
Toshio Koidedf2eab92014-02-20 11:24:59 -0800123 String id = op.intent.getId();
Toshio Koidea10c0372014-02-20 17:28:10 -0800124 if (op.intent.getState().equals(IntentState.INST_ACK))
125 states.put(id, IntentState.REROUTE_REQ);
126 else
127 states.put(id, IntentState.INST_REQ);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800128 }
Toshio Koidea10c0372014-02-20 17:28:10 -0800129 highLevelIntents.changeStates(states);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800130
131 // calculate path-intents (low-level operations)
Toshio Koide27ffd412014-02-18 19:15:27 -0800132 IntentOperationList pathIntentOperations = runtime.calcPathIntents(list, pathIntents);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800133
Toshio Koidea10c0372014-02-20 17:28:10 -0800134 // persist calculated low-level operations into data store
Nick Karanatsios8abe7172014-02-19 20:31:48 -0800135 long key = persistIntent.getKey();
Toshio Koidedf2eab92014-02-20 11:24:59 -0800136 persistIntent.persistIfLeader(key, pathIntentOperations);
137
138 // remove error-intents and reflect them to high-level intents
Toshio Koidea10c0372014-02-20 17:28:10 -0800139 states.clear();
Toshio Koidedf2eab92014-02-20 11:24:59 -0800140 Iterator<IntentOperation> i = pathIntentOperations.iterator();
141 while (i.hasNext()) {
142 IntentOperation op = i.next();
143 if (op.operator.equals(Operator.ERROR)) {
144 states.put(op.intent.getId(), IntentState.INST_NACK);
145 i.remove();
146 }
147 }
148 highLevelIntents.changeStates(states);
149
Toshio Koide798bc1b2014-02-20 14:02:40 -0800150 // update the map of low-level intents and publish the low-level
151 // operations
Toshio Koide27ffd412014-02-18 19:15:27 -0800152 pathIntents.executeOperations(pathIntentOperations);
Toshio Koide600ae5f2014-02-20 18:42:00 -0800153
154 // send remove operation includes intent which has a complete path
155 // TODO need optimization
156 for (IntentOperation op: pathIntentOperations) {
157 if(op.operator.equals(Operator.REMOVE)) {
158 op.intent = pathIntents.getIntent(op.intent.getId());
159 }
160 }
Toshio Koide066506e2014-02-20 19:52:09 -0800161 opEventChannel.addEntry(key, pathIntentOperations);
Toshio Koide27ffd412014-02-18 19:15:27 -0800162 return pathIntentOperations;
163 }
164
165 @Override
166 public IntentMap getHighLevelIntents() {
Toshio Koide4f308732014-02-18 15:19:48 -0800167 return highLevelIntents;
168 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800169
170 @Override
171 public IntentMap getPathIntents() {
172 return pathIntents;
173 }
174
175 @Override
Toshio Koide4f308732014-02-18 15:19:48 -0800176 public void purgeIntents() {
177 highLevelIntents.purge();
Toshio Koide27ffd412014-02-18 19:15:27 -0800178 pathIntents.purge();
Toshio Koide4f308732014-02-18 15:19:48 -0800179 }
Toshio Koide0c9106d2014-02-19 15:26:38 -0800180
Toshio Koide798bc1b2014-02-20 14:02:40 -0800181 // ================================================================================
182 // INetworkGraphListener implementations
183 // ================================================================================
184
Toshio Koide0c9106d2014-02-19 15:26:38 -0800185 @Override
Toshio Koide798bc1b2014-02-20 14:02:40 -0800186 public void networkGraphEvents(Collection<SwitchEvent> addedSwitchEvents,
187 Collection<SwitchEvent> removedSwitchEvents,
188 Collection<PortEvent> addedPortEvents,
189 Collection<PortEvent> removedPortEvents,
190 Collection<LinkEvent> addedLinkEvents,
191 Collection<LinkEvent> removedLinkEvents,
192 Collection<DeviceEvent> addedDeviceEvents,
193 Collection<DeviceEvent> removedDeviceEvents) {
Toshio Koidea9078af2014-02-21 16:57:04 -0800194
195 HashSet<PathIntent> affectedPaths = new HashSet<>();
196
197 for (SwitchEvent switchEvent: removedSwitchEvents)
198 affectedPaths.addAll(pathIntents.getIntentsByDpid(switchEvent.getDpid()));
199
200 for (PortEvent portEvent: removedPortEvents)
201 affectedPaths.addAll(pathIntents.getIntentsByPort(portEvent.getDpid(), portEvent.getNumber()));
202
203 for (LinkEvent linkEvent: removedLinkEvents)
204 affectedPaths.addAll(pathIntents.getIntentsByLink(linkEvent));
205
206 reroutePaths(affectedPaths);
Toshio Koide0c9106d2014-02-19 15:26:38 -0800207 }
Toshio Koide066506e2014-02-20 19:52:09 -0800208
209 // ================================================================================
210 // IEventChannelListener implementations
211 // ================================================================================
212
213 @Override
214 public void entryAdded(IntentStateList value) {
215 entryUpdated(value);
216 }
217
218 @Override
219 public void entryRemoved(IntentStateList value) {
220 // do nothing
221 }
222
223 @Override
224 public void entryUpdated(IntentStateList value) {
225 // reflect state changes of path-level intent into application-level intents
226 IntentStateList parentStates = new IntentStateList();
227 for (Entry<String, IntentState> entry: value.entrySet()) {
228 PathIntent pathIntent = (PathIntent) pathIntents.getIntent(entry.getKey());
229 if (pathIntent == null) continue;
230
231 Intent parentIntent = pathIntent.getParentIntent();
232 if (parentIntent == null ||
233 !(parentIntent instanceof ShortestPathIntent) ||
234 !((ShortestPathIntent) parentIntent).getPathIntentId().equals(pathIntent.getId()))
235 continue;
236
237 IntentState state = entry.getValue();
238 switch (state) {
239 case INST_ACK:
240 case INST_NACK:
241 case DEL_ACK:
242 case DEL_PENDING:
243 parentStates.put(parentIntent.getId(), state);
244 break;
245 default:
246 break;
247 }
248 }
249 highLevelIntents.changeStates(parentStates);
250 pathIntents.changeStates(value);
251 }
Toshio Koidea9078af2014-02-21 16:57:04 -0800252}