blob: 67902dd1a08a22026d0aacb9f1aab5718068263a [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
56 private void reroutePaths(Collection<LinkEvent> removedLinkEvents) {
57 HashSet<PathIntent> oldPaths = new HashSet<>();
58 for (LinkEvent linkEvent : removedLinkEvents) {
59 Collection<PathIntent> intents = pathIntents.getIntentsByLink(linkEvent);
60 if (intents == null)
61 continue;
62 oldPaths.addAll(intents);
63 }
64
65 if (oldPaths.isEmpty())
66 return;
Toshio Koidea10c0372014-02-20 17:28:10 -080067
Toshio Koide0c9106d2014-02-19 15:26:38 -080068 IntentOperationList reroutingOperation = new IntentOperationList();
Toshio Koide798bc1b2014-02-20 14:02:40 -080069 for (PathIntent pathIntent : oldPaths) {
Toshio Koide0c9106d2014-02-19 15:26:38 -080070 reroutingOperation.add(Operator.ADD, pathIntent.getParentIntent());
71 }
72 executeIntentOperations(reroutingOperation);
73 }
Toshio Koide27ffd412014-02-18 19:15:27 -080074
Toshio Koide798bc1b2014-02-20 14:02:40 -080075 // ================================================================================
76 // IFloodlightModule implementations
77 // ================================================================================
78
Toshio Koide4f308732014-02-18 15:19:48 -080079 @Override
80 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
81 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(1);
Toshio Koideeb90d912014-02-18 21:30:22 -080082 l.add(IPathCalcRuntimeService.class);
Toshio Koide4f308732014-02-18 15:19:48 -080083 return l;
84 }
85
86 @Override
87 public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
88 Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>(1);
Toshio Koide27ffd412014-02-18 19:15:27 -080089 m.put(IPathCalcRuntimeService.class, this);
Toshio Koide4f308732014-02-18 15:19:48 -080090 return m;
91 }
92
93 @Override
94 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
95 Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
96 l.add(IDatagridService.class);
Toshio Koide27ffd412014-02-18 19:15:27 -080097 l.add(INetworkGraphService.class);
Toshio Koide4f308732014-02-18 15:19:48 -080098 return l;
99 }
100
101 @Override
102 public void init(FloodlightModuleContext context) throws FloodlightModuleException {
103 datagridService = context.getServiceImpl(IDatagridService.class);
Toshio Koided9fa2a82014-02-19 17:35:18 -0800104 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
Toshio Koide798bc1b2014-02-20 14:02:40 -0800105 controllerRegistry = context.getServiceImpl(IControllerRegistryService.class);
Toshio Koide4f308732014-02-18 15:19:48 -0800106 }
107
108 @Override
109 public void startUp(FloodlightModuleContext context) {
Toshio Koideeb90d912014-02-18 21:30:22 -0800110 highLevelIntents = new IntentMap();
111 runtime = new PathCalcRuntime(networkGraphService.getNetworkGraph());
Toshio Koide0c9106d2014-02-19 15:26:38 -0800112 pathIntents = new PathIntentMap();
Toshio Koide066506e2014-02-20 19:52:09 -0800113 opEventChannel = datagridService.createChannel(INTENT_OP_EVENT_CHANNEL_NAME, Long.class, IntentOperationList.class);
114 datagridService.addListener(INTENT_STATE_EVENT_CHANNEL_NAME, this, Long.class, IntentStateList.class);
Toshio Koide0c9106d2014-02-19 15:26:38 -0800115 networkGraphService.registerNetworkGraphListener(this);
Toshio Koide798bc1b2014-02-20 14:02:40 -0800116 persistIntent = new PersistIntent(controllerRegistry, networkGraphService);
Toshio Koide4f308732014-02-18 15:19:48 -0800117 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800118
Toshio Koide798bc1b2014-02-20 14:02:40 -0800119 // ================================================================================
120 // IPathCalcRuntimeService implementations
121 // ================================================================================
122
Toshio Koide27ffd412014-02-18 19:15:27 -0800123 @Override
124 public IntentOperationList executeIntentOperations(IntentOperationList list) {
Toshio Koidedf2eab92014-02-20 11:24:59 -0800125 // update the map of high-level intents
Toshio Koide27ffd412014-02-18 19:15:27 -0800126 highLevelIntents.executeOperations(list);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800127
Toshio Koidea10c0372014-02-20 17:28:10 -0800128 // change states of high-level intents
Toshio Koide066506e2014-02-20 19:52:09 -0800129 IntentStateList states = new IntentStateList();
Toshio Koide798bc1b2014-02-20 14:02:40 -0800130 for (IntentOperation op : list) {
Toshio Koidedf2eab92014-02-20 11:24:59 -0800131 String id = op.intent.getId();
Toshio Koidea10c0372014-02-20 17:28:10 -0800132 if (op.intent.getState().equals(IntentState.INST_ACK))
133 states.put(id, IntentState.REROUTE_REQ);
134 else
135 states.put(id, IntentState.INST_REQ);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800136 }
Toshio Koidea10c0372014-02-20 17:28:10 -0800137 highLevelIntents.changeStates(states);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800138
139 // calculate path-intents (low-level operations)
Toshio Koide27ffd412014-02-18 19:15:27 -0800140 IntentOperationList pathIntentOperations = runtime.calcPathIntents(list, pathIntents);
Toshio Koidedf2eab92014-02-20 11:24:59 -0800141
Toshio Koidea10c0372014-02-20 17:28:10 -0800142 // persist calculated low-level operations into data store
Nick Karanatsios8abe7172014-02-19 20:31:48 -0800143 long key = persistIntent.getKey();
Toshio Koidedf2eab92014-02-20 11:24:59 -0800144 persistIntent.persistIfLeader(key, pathIntentOperations);
145
146 // remove error-intents and reflect them to high-level intents
Toshio Koidea10c0372014-02-20 17:28:10 -0800147 states.clear();
Toshio Koidedf2eab92014-02-20 11:24:59 -0800148 Iterator<IntentOperation> i = pathIntentOperations.iterator();
149 while (i.hasNext()) {
150 IntentOperation op = i.next();
151 if (op.operator.equals(Operator.ERROR)) {
152 states.put(op.intent.getId(), IntentState.INST_NACK);
153 i.remove();
154 }
155 }
156 highLevelIntents.changeStates(states);
157
Toshio Koide798bc1b2014-02-20 14:02:40 -0800158 // update the map of low-level intents and publish the low-level
159 // operations
Toshio Koide27ffd412014-02-18 19:15:27 -0800160 pathIntents.executeOperations(pathIntentOperations);
Toshio Koide600ae5f2014-02-20 18:42:00 -0800161
162 // send remove operation includes intent which has a complete path
163 // TODO need optimization
164 for (IntentOperation op: pathIntentOperations) {
165 if(op.operator.equals(Operator.REMOVE)) {
166 op.intent = pathIntents.getIntent(op.intent.getId());
167 }
168 }
Toshio Koide066506e2014-02-20 19:52:09 -0800169 opEventChannel.addEntry(key, pathIntentOperations);
Toshio Koide27ffd412014-02-18 19:15:27 -0800170 return pathIntentOperations;
171 }
172
173 @Override
174 public IntentMap getHighLevelIntents() {
Toshio Koide4f308732014-02-18 15:19:48 -0800175 return highLevelIntents;
176 }
Toshio Koide27ffd412014-02-18 19:15:27 -0800177
178 @Override
179 public IntentMap getPathIntents() {
180 return pathIntents;
181 }
182
183 @Override
Toshio Koide4f308732014-02-18 15:19:48 -0800184 public void purgeIntents() {
185 highLevelIntents.purge();
Toshio Koide27ffd412014-02-18 19:15:27 -0800186 pathIntents.purge();
Toshio Koide4f308732014-02-18 15:19:48 -0800187 }
Toshio Koide0c9106d2014-02-19 15:26:38 -0800188
Toshio Koide798bc1b2014-02-20 14:02:40 -0800189 // ================================================================================
190 // INetworkGraphListener implementations
191 // ================================================================================
192
Toshio Koide0c9106d2014-02-19 15:26:38 -0800193 @Override
Toshio Koide798bc1b2014-02-20 14:02:40 -0800194 public void networkGraphEvents(Collection<SwitchEvent> addedSwitchEvents,
195 Collection<SwitchEvent> removedSwitchEvents,
196 Collection<PortEvent> addedPortEvents,
197 Collection<PortEvent> removedPortEvents,
198 Collection<LinkEvent> addedLinkEvents,
199 Collection<LinkEvent> removedLinkEvents,
200 Collection<DeviceEvent> addedDeviceEvents,
201 Collection<DeviceEvent> removedDeviceEvents) {
Toshio Koide066506e2014-02-20 19:52:09 -0800202 // TODO add getIntentsByPort() and getIntentsBySwitch() to PathIntentMap.
Toshio Koide798bc1b2014-02-20 14:02:40 -0800203 reroutePaths(removedLinkEvents);
Toshio Koide0c9106d2014-02-19 15:26:38 -0800204 }
Toshio Koide066506e2014-02-20 19:52:09 -0800205
206 // ================================================================================
207 // IEventChannelListener implementations
208 // ================================================================================
209
210 @Override
211 public void entryAdded(IntentStateList value) {
212 entryUpdated(value);
213 }
214
215 @Override
216 public void entryRemoved(IntentStateList value) {
217 // do nothing
218 }
219
220 @Override
221 public void entryUpdated(IntentStateList value) {
222 // reflect state changes of path-level intent into application-level intents
223 IntentStateList parentStates = new IntentStateList();
224 for (Entry<String, IntentState> entry: value.entrySet()) {
225 PathIntent pathIntent = (PathIntent) pathIntents.getIntent(entry.getKey());
226 if (pathIntent == null) continue;
227
228 Intent parentIntent = pathIntent.getParentIntent();
229 if (parentIntent == null ||
230 !(parentIntent instanceof ShortestPathIntent) ||
231 !((ShortestPathIntent) parentIntent).getPathIntentId().equals(pathIntent.getId()))
232 continue;
233
234 IntentState state = entry.getValue();
235 switch (state) {
236 case INST_ACK:
237 case INST_NACK:
238 case DEL_ACK:
239 case DEL_PENDING:
240 parentStates.put(parentIntent.getId(), state);
241 break;
242 default:
243 break;
244 }
245 }
246 highLevelIntents.changeStates(parentStates);
247 pathIntents.changeStates(value);
248 }
Toshio Koide798bc1b2014-02-20 14:02:40 -0800249}