blob: cb8cc5ddfca31ed9c23a61cd3fb6dedff7171742 [file] [log] [blame]
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07003import java.util.ArrayList;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07004import java.util.Collection;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07005import java.util.HashMap;
6import java.util.Iterator;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07007import java.util.LinkedList;
8import java.util.List;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07009import java.util.Map;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080010import java.util.SortedMap;
11import java.util.TreeMap;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070012import java.util.concurrent.BlockingQueue;
13import java.util.concurrent.LinkedBlockingQueue;
14
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080015import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070016import net.onrc.onos.datagrid.IDatagridService;
Naoki Shiota0abe38d2014-01-07 15:31:22 -080017import net.onrc.onos.graph.GraphDBOperation;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070018import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070019import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070020import net.onrc.onos.ofcontroller.topology.TopologyManager;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070021import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080022import net.onrc.onos.ofcontroller.util.Dpid;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070023import net.onrc.onos.ofcontroller.util.EventEntry;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070024import net.onrc.onos.ofcontroller.util.FlowEntry;
25import net.onrc.onos.ofcontroller.util.FlowEntryAction;
26import net.onrc.onos.ofcontroller.util.FlowEntryActions;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070027import net.onrc.onos.ofcontroller.util.FlowEntryId;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070028import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
29import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
30import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070031import net.onrc.onos.ofcontroller.util.FlowId;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070032import net.onrc.onos.ofcontroller.util.FlowPath;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070033import net.onrc.onos.ofcontroller.util.FlowPathUserState;
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080034import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080035import net.onrc.onos.ofcontroller.util.Port;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080036import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
37
38import com.esotericsoftware.kryo2.Kryo;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070039
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070044 * Class for FlowPath Maintenance.
45 * This class listens for FlowEvents to:
46 * - Maintain a local cache of the Network Topology.
47 * - Detect FlowPaths impacted by Topology change.
48 * - Recompute impacted FlowPath using cached Topology.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070049 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070050class FlowEventHandler extends Thread implements IFlowEventHandlerService {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080051
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -080052 private boolean enableOnrc2014MeasurementsFlows = true;
53 private boolean enableOnrc2014MeasurementsTopology = true;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080054
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070055 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070056 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
Naoki Shiota0abe38d2014-01-07 15:31:22 -080057
Naoki Shiota0abe38d2014-01-07 15:31:22 -080058 private GraphDBOperation dbHandler;
Naoki Shiotaf74d5f32014-01-09 21:29:38 -080059
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070060 private FlowManager flowManager; // The Flow Manager to use
61 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070062 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080063 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070064
65 // The queue with Flow Path and Topology Element updates
66 private BlockingQueue<EventEntry<?>> networkEvents =
67 new LinkedBlockingQueue<EventEntry<?>>();
68
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070069 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070070 private List<EventEntry<TopologyElement>> topologyEvents =
71 new LinkedList<EventEntry<TopologyElement>>();
72 private List<EventEntry<FlowPath>> flowPathEvents =
73 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070074 private List<EventEntry<FlowEntry>> flowEntryEvents =
75 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -080076 private List<EventEntry<FlowId>> flowIdEvents =
77 new LinkedList<EventEntry<FlowId>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080078 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
79 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070080
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080081 // All internally computed Flow Paths
82 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
83
84 // The Flow Entries received as notifications with unmatched Flow Paths
85 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
86 new HashMap<Long, FlowEntry>();
87
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080088 //
89 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080090 // - The Flow Paths that should be recomputed
91 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080092 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080093 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080094 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
95 new HashMap<Long, FlowPath>();
96 private Map<Long, FlowPath> modifiedFlowPaths =
97 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080098 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
99 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800100
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700101 /**
102 * Constructor for a given Flow Manager and Datagrid Service.
103 *
104 * @param flowManager the Flow Manager to use.
105 * @param datagridService the Datagrid Service to use.
106 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700107 FlowEventHandler(FlowManager flowManager,
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800108 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700109 this.flowManager = flowManager;
110 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700111 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700112 }
113
114 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800115 * Get the network topology.
116 *
117 * @return the network topology.
118 */
119 protected Topology getTopology() { return this.topology; }
120
121 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800122 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700123 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800124 private void startup() {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800125 this.dbHandler = new GraphDBOperation("");
126
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700127 //
128 // Obtain the initial Topology state
129 //
130 Collection<TopologyElement> topologyElements =
131 datagridService.getAllTopologyElements();
132 for (TopologyElement topologyElement : topologyElements) {
133 EventEntry<TopologyElement> eventEntry =
134 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
135 topologyEvents.add(eventEntry);
136 }
137 //
138 // Obtain the initial Flow Path state
139 //
140 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
141 for (FlowPath flowPath : flowPaths) {
142 EventEntry<FlowPath> eventEntry =
143 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
144 flowPathEvents.add(eventEntry);
145 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700146 //
147 // Obtain the initial FlowEntry state
148 //
149 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
150 for (FlowEntry flowEntry : flowEntries) {
151 EventEntry<FlowEntry> eventEntry =
152 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
153 flowEntryEvents.add(eventEntry);
154 }
155
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800156 //
157 // Obtain the initial FlowId state
158 //
159 Collection<FlowId> flowIds = datagridService.getAllFlowIds();
160 for (FlowId flowId : flowIds) {
161 EventEntry<FlowId> eventEntry =
162 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
163 flowIdEvents.add(eventEntry);
164 }
165
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800166 //
167 // Obtain the initial FlowEntryId state
168 //
169 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
170 datagridService.getAllFlowEntryIds();
171 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
172 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
173 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
174 flowEntryIdEvents.add(eventEntry);
175 }
176
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800177 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800178 synchronized (allFlowPaths) {
179 processEvents();
180 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800181 }
182
183 /**
184 * Run the thread.
185 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800186 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800187 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800188 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800189 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700190
191 //
192 // The main loop
193 //
194 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
195 try {
196 while (true) {
197 EventEntry<?> eventEntry = networkEvents.take();
198 collection.add(eventEntry);
199 networkEvents.drainTo(collection);
200
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700201 //
202 // Demultiplex all events:
203 // - EventEntry<TopologyElement>
204 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700205 // - EventEntry<FlowEntry>
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800206 // - EventEntry<FlowId>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800207 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700208 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700209 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800210 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700211 if (event.eventData() instanceof TopologyElement) {
212 EventEntry<TopologyElement> topologyEventEntry =
213 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800214
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700215 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800216 continue;
217 }
218
219 // FlowPath event
220 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700221 EventEntry<FlowPath> flowPathEventEntry =
222 (EventEntry<FlowPath>)event;
223 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800224 continue;
225 }
226
227 // FlowEntry event
228 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700229 EventEntry<FlowEntry> flowEntryEventEntry =
230 (EventEntry<FlowEntry>)event;
231 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800232 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700233 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800234
235 // FlowId event
236 if (event.eventData() instanceof FlowId) {
237 EventEntry<FlowId> flowIdEventEntry =
238 (EventEntry<FlowId>)event;
239 flowIdEvents.add(flowIdEventEntry);
240 continue;
241 }
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800242 // FlowEntryId event
243 if (event.eventData() instanceof Pair) {
244 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
245 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
246 flowEntryIdEvents.add(flowEntryIdEventEntry);
247 continue;
248 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700249 }
250 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700251
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700252 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800253 synchronized (allFlowPaths) {
254 processEvents();
255 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700256 }
257 } catch (Exception exception) {
258 log.debug("Exception processing Network Events: ", exception);
259 }
260 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800261
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700262 /**
263 * Process the events (if any)
264 */
265 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800266 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700267
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800268 if (enableOnrc2014MeasurementsFlows) {
269
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800270 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
271 flowEntryIdEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800272 return; // Nothing to do
273 }
274
275 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
276
277 // Fetch and prepare my flows
278 prepareMyFlows(mySwitches);
279
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800280 // Process the Flow ID events
281 processFlowIdEvents(mySwitches);
282
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800283 // Fetch the topology
284 processTopologyEvents();
285
286 // Recompute all affected Flow Paths and keep only the modified
287 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
288 if (recomputeFlowPath(flowPath))
289 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
290 }
291
292 // Assign the Flow Entry ID as needed
293 for (FlowPath flowPath : modifiedFlowPaths.values()) {
294 for (FlowEntry flowEntry : flowPath.flowEntries()) {
295 if (! flowEntry.isValidFlowEntryId()) {
296 long id = flowManager.getNextFlowEntryId();
297 flowEntry.setFlowEntryId(new FlowEntryId(id));
298 }
299 }
300 }
301
302 // Extract my modified Flow Entries
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800303 modifiedFlowEntries = processFlowEntryIdEvents(mySwitches);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800304
305 //
306 // Push the modified state to the Flow Manager
307 //
308 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
309 modifiedFlowEntries);
310
311 // Cleanup
312 topologyEvents.clear();
313 flowIdEvents.clear();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800314 flowEntryIdEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800315 //
316 allFlowPaths.clear();
317 shouldRecomputeFlowPaths.clear();
318 modifiedFlowPaths.clear();
319
320 return;
321 }
322
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700323 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800324 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700325 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700326 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700327
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800328 processFlowPathEvents();
329 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800330 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800331 processFlowEntryEvents();
332
333 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800334 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800335 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800336 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800337 }
338
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800339 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800340 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800341
342 // Assign missing Flow Entry IDs
343 assignFlowEntryId(modifiedFlowEntries);
344
345 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800346 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800347 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800348 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
349 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800350
351 //
352 // Remove Flow Entries that were deleted
353 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800354 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800355 flowPath.dataPath().removeDeletedFlowEntries();
356
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800357 //
358 // Check if Flow Paths have been installed into all switches,
359 // and generate the appropriate events.
360 //
361 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
362
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800363 // Cleanup
364 topologyEvents.clear();
365 flowPathEvents.clear();
366 flowEntryEvents.clear();
367 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800368 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800369 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800370 checkIfInstalledFlowPaths.clear();
371 }
372
373 /**
374 * Check if Flow Paths have been installed into all switches,
375 * and generate the appropriate events.
376 *
377 * @param flowPaths the flowPaths to process.
378 */
379 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
380 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
381
382 Kryo kryo = kryoFactory.newKryo();
383
384 for (FlowPath flowPath : flowPaths) {
385 boolean isInstalled = true;
386
387 //
388 // Check whether all Flow Entries have been installed
389 //
390 for (FlowEntry flowEntry : flowPath.flowEntries()) {
391 if (flowEntry.flowEntrySwitchState() !=
392 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
393 isInstalled = false;
394 break;
395 }
396 }
397
398 if (isInstalled) {
399 // Create a copy and add it to the list
400 FlowPath copyFlowPath = kryo.copy(flowPath);
401 installedFlowPaths.add(copyFlowPath);
402 }
403 }
404 kryoFactory.deleteKryo(kryo);
405
406 // Generate an event for the installed Flow Path.
407 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800408 }
409
410 /**
411 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800412 *
413 * @param modifiedFlowPaths the Flow Paths to process.
414 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800415 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800416 private Collection<FlowEntry> extractModifiedFlowEntries(
417 Collection<FlowPath> modifiedFlowPaths) {
418 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800419
420 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800421 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800422 for (FlowEntry flowEntry : flowPath.flowEntries()) {
423 if (flowEntry.flowEntrySwitchState() ==
424 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800425 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800426 }
427 }
428 }
429 return modifiedFlowEntries;
430 }
431
432 /**
433 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800434 *
435 * @param modifiedFlowEnries the collection of Flow Entries that need
436 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800437 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800438 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800439 if (modifiedFlowEntries.isEmpty())
440 return;
441
442 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
443
444 //
445 // Assign the Flow Entry ID only for Flow Entries for my switches
446 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800447 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800448 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
449 if (mySwitch == null)
450 continue;
451 if (! flowEntry.isValidFlowEntryId()) {
452 long id = flowManager.getNextFlowEntryId();
453 flowEntry.setFlowEntryId(new FlowEntryId(id));
454 }
455 }
456 }
457
458 /**
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800459 * Prepare my flows.
460 *
461 * @param mySwitches the collection of my switches.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800462 */
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800463 private void prepareMyFlows(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800464 if (! topologyEvents.isEmpty()) {
465 // Fetch my flows from the database
466 ArrayList<FlowPath> myFlows = FlowDatabaseOperation.getAllMyFlows(dbHandler, mySwitches);
467 for (FlowPath flowPath : myFlows) {
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800468 log.debug("Found my flow: {}", flowPath);
469
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800470 allFlowPaths.put(flowPath.flowId().value(), flowPath);
471
472 //
473 // TODO: Bug workaround / fix :
474 // method FlowDatabaseOperation.extractFlowEntry() doesn't
475 // fetch the inPort and outPort, hence we assign them here.
476 //
477 // Assign the inPort and outPort for the Flow Entries
478 for (FlowEntry flowEntry : flowPath.flowEntries()) {
479 // Set the inPort
480 do {
481 if (flowEntry.inPort() != null)
482 break;
483 if (flowEntry.flowEntryMatch() == null)
484 break;
485 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
486 flowEntry.setInPort(inPort);
487 } while (false);
488
489 // Set the outPort
490 do {
491 if (flowEntry.outPort() != null)
492 break;
493 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
494 if (fa.actionOutput() != null) {
495 Port outPort = new Port(fa.actionOutput().port().value());
496 flowEntry.setOutPort(outPort);
497 break;
498 }
499 }
500 } while (false);
501 }
502 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800503 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800504 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800505
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800506 /**
507 * Process the Flow ID events.
508 *
509 * @param mySwitches the collection of my switches.
510 */
511 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800512 //
513 // Automatically add all Flow ID events (for the Flows this instance
514 // is responsible for) to the collection of Flows to recompute.
515 //
516 for (EventEntry<FlowId> eventEntry : flowIdEvents) {
517 FlowId flowId = eventEntry.eventData();
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800518
519 log.debug("Flow ID Event: {} {}", eventEntry.eventType(), flowId);
520
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800521 FlowPath flowPath = allFlowPaths.get(flowId.value());
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800522 if (flowPath == null) {
523 if (! topologyEvents.isEmpty())
524 continue; // Optimization: Not my flow
525 Dpid dpid = FlowDatabaseOperation.getFlowSourceDpid(dbHandler,
526 flowId);
527 if ((dpid != null) && (mySwitches.get(dpid.value()) != null)) {
528 flowPath = FlowDatabaseOperation.getFlow(dbHandler,
529 flowId);
530 }
531 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800532 if (flowPath != null) {
533 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
534 flowPath);
535 }
536 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800537 }
538
539 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800540 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800541 *
542 * @param mySwitches the collection of my switches.
543 * @return a collection of modified Flow Entries this instance needs
544 * to push to its own switches.
545 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800546 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800547 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
548
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800549 //
550 // Process all Flow ID events and update the appropriate state
551 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800552 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
553 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
554 FlowEntryId flowEntryId = pair.first;
555 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800556
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800557 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
558 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800559
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800560 if (mySwitches.get(dpid.value()) == null)
561 continue;
562
563 // Fetch the Flow Entry
564 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
565 flowEntryId);
566 if (flowEntry == null) {
567 log.debug("Flow Entry ID {} : Flow Entry not found!",
568 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800569 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800570 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800571 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800572 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800573
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800574 return modifiedFlowEntries;
575 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800576
577 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800578 * Process the Flow Path events.
579 */
580 private void processFlowPathEvents() {
581 //
582 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700583 //
584 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
585 FlowPath flowPath = eventEntry.eventData();
586
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800587 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800588
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700589 switch (eventEntry.eventType()) {
590 case ENTRY_ADD: {
591 //
592 // Add a new Flow Path
593 //
594 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
595 //
596 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800597 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700598 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700599 }
600
601 switch (flowPath.flowPathType()) {
602 case FP_TYPE_SHORTEST_PATH:
603 //
604 // Reset the Data Path, in case it was set already, because
605 // we are going to recompute it anyway.
606 //
607 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800608 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
609 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700610 break;
611 case FP_TYPE_EXPLICIT_PATH:
612 //
613 // Mark all Flow Entries for installation in the switches.
614 //
615 for (FlowEntry flowEntry : flowPath.flowEntries()) {
616 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
617 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800618 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700619 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800620 case FP_TYPE_UNKNOWN:
621 log.error("FlowPath event with unknown type");
622 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700623 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800624 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700625
626 break;
627 }
628
629 case ENTRY_REMOVE: {
630 //
631 // Remove an existing Flow Path.
632 //
633 // Find the Flow Path, and mark the Flow and its Flow Entries
634 // for deletion.
635 //
636 FlowPath existingFlowPath =
637 allFlowPaths.get(flowPath.flowId().value());
638 if (existingFlowPath == null)
639 continue; // Nothing to do
640
641 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
642 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
643 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
644 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
645 }
646
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800647 // Remove the Flow Path from the internal state
648 Long key = existingFlowPath.flowId().value();
649 allFlowPaths.remove(key);
650 shouldRecomputeFlowPaths.remove(key);
651 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700652
653 break;
654 }
655 }
656 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800657 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700658
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800659 /**
660 * Process the Topology events.
661 */
662 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800663 boolean isTopologyModified = false;
664
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800665 if (enableOnrc2014MeasurementsTopology) {
666 if (topologyEvents.isEmpty())
667 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800668
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800669 // TODO: Code for debugging purpose only
670 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
671 TopologyElement topologyElement = eventEntry.eventData();
672 log.debug("Topology Event: {} {}", eventEntry.eventType(),
673 topologyElement.toString());
674 }
675
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800676 log.debug("[BEFORE] {}", topology.toString());
677
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800678 //
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800679 // TODO: Fake the unconditional topology read by checking the cache
680 // with the old topology and ignoring topology events that don't
681 // make any impact to the topology.
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800682 // This is needed aa workaround: if a port is down, we get
683 // up to three additional "Port Down" or "Link Down" events.
684 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800685 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
686 TopologyElement topologyElement = eventEntry.eventData();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800687
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800688 switch (eventEntry.eventType()) {
689 case ENTRY_ADD:
690 isTopologyModified |= topology.addTopologyElement(topologyElement);
691 break;
692 case ENTRY_REMOVE:
693 isTopologyModified |= topology.removeTopologyElement(topologyElement);
694 break;
695 }
696 if (isTopologyModified)
697 break;
698 }
699 if (! isTopologyModified) {
700 log.debug("Ignoring topology events that don't modify the topology");
701 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800702 }
703
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800704 topology.readFromDatabase(dbHandler);
705 log.debug("[AFTER] {}", topology.toString());
706 shouldRecomputeFlowPaths.putAll(allFlowPaths);
707 return;
708 }
709
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700710 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800711 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700712 //
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800713 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
714 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800715
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800716 log.debug("Topology Event: {} {}", eventEntry.eventType(),
717 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800718
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800719 switch (eventEntry.eventType()) {
720 case ENTRY_ADD:
Naoki Shiota9f6fc212014-01-09 21:38:08 -0800721 isTopologyModified |= topology.addTopologyElement(topologyElement);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800722 break;
723 case ENTRY_REMOVE:
Naoki Shiota9f6fc212014-01-09 21:38:08 -0800724 isTopologyModified |= topology.removeTopologyElement(topologyElement);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800725 break;
726 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700727 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700728 if (isTopologyModified) {
729 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800730 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700731 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800732 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700733
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800734 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800735 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800736 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800737 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800738 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800739 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800740
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700741 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800742 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700743 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800744 if (! unmatchedFlowEntryAdd.isEmpty()) {
745 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
746 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800747 // log.debug("Processing Unmatched Flow Entry: {}",
748 // flowEntry.toString());
749
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800750 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800751 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800752 remainingUpdates.put(flowEntry.flowEntryId().value(),
753 flowEntry);
754 continue;
755 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800756 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
757 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800758 remainingUpdates.put(flowEntry.flowEntryId().value(),
759 flowEntry);
760 continue;
761 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800762 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
763 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
764 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700765 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800766 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700767 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800768 }
769
770 /**
771 * Process the Flow Entry events.
772 */
773 private void processFlowEntryEvents() {
774 FlowPath flowPath;
775 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700776
777 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800778 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700779 //
780 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
781 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800782
783 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800784 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800785
786 if ((! flowEntry.isValidFlowId()) ||
787 (! flowEntry.isValidFlowEntryId())) {
788 continue;
789 }
790
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700791 switch (eventEntry.eventType()) {
792 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800793 flowPath = allFlowPaths.get(flowEntry.flowId().value());
794 if (flowPath == null) {
795 // Flow Path not found: keep the entry for later matching
796 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
797 flowEntry);
798 break;
799 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800800 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
801 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800802 // Flow Entry not found: keep the entry for later matching
803 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
804 flowEntry);
805 break;
806 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800807 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
808 // Add the updated Flow Path to the list of updated paths
809 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
810 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700811 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800812
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700813 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800814 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
815 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800816 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800817 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800818
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800819 flowPath = allFlowPaths.get(flowEntry.flowId().value());
820 if (flowPath == null) {
821 // Flow Path not found: ignore the update
822 break;
823 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800824 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
825 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800826 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800827 break;
828 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800829 if (updateFlowEntryRemove(flowPath, localFlowEntry,
830 flowEntry)) {
831 // Add the updated Flow Path to the list of updated paths
832 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
833 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700834 break;
835 }
836 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700837 }
838
839 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800840 * Find a Flow Entry that should be updated because of an external
841 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700842 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800843 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800844 * @param newFlowEntry the FlowEntry with the new state.
845 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700846 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800847 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
848 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700849 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800850 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700851 //
852 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800853 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800854 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700855 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800856 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700857
858 //
859 // Local Flow Entry match found
860 //
861 if (localFlowEntry.isValidFlowEntryId()) {
862 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800863 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700864 //
865 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800866 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700867 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800868 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700869 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700870 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800871 return localFlowEntry;
872 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700873
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800874 return null; // Entry not found
875 }
876
877 /**
878 * Update a Flow Entry because of an external ENTRY_ADD event.
879 *
880 * @param flowPath the FlowPath for the Flow Entry to update.
881 * @param localFlowEntry the local Flow Entry to update.
882 * @param newFlowEntry the FlowEntry with the new state.
883 * @return true if the local Flow Entry was updated, otherwise false.
884 */
885 private boolean updateFlowEntryAdd(FlowPath flowPath,
886 FlowEntry localFlowEntry,
887 FlowEntry newFlowEntry) {
888 boolean updated = false;
889
890 if (localFlowEntry.flowEntryUserState() ==
891 FlowEntryUserState.FE_USER_DELETE) {
892 // Don't add-back a Flow Entry that is already deleted
893 return false;
894 }
895
896 if (! localFlowEntry.isValidFlowEntryId()) {
897 // Update the Flow Entry ID
898 FlowEntryId flowEntryId =
899 new FlowEntryId(newFlowEntry.flowEntryId().value());
900 localFlowEntry.setFlowEntryId(flowEntryId);
901 updated = true;
902 }
903
904 //
905 // Update the local Flow Entry, and keep state to check
906 // if the Flow Path has been installed.
907 //
908 if (localFlowEntry.flowEntryUserState() !=
909 newFlowEntry.flowEntryUserState()) {
910 localFlowEntry.setFlowEntryUserState(
911 newFlowEntry.flowEntryUserState());
912 updated = true;
913 }
914 if (localFlowEntry.flowEntrySwitchState() !=
915 newFlowEntry.flowEntrySwitchState()) {
916 localFlowEntry.setFlowEntrySwitchState(
917 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800918 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800919 updated = true;
920 }
921
922 return updated;
923 }
924
925 /**
926 * Find a Flow Entry that should be updated because of an external
927 * ENTRY_REMOVE event.
928 *
929 * @param flowPath the FlowPath for the Flow Entry to update.
930 * @param newFlowEntry the FlowEntry with the new state.
931 * @return the Flow Entry that should be updated if found, otherwise null.
932 */
933 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
934 FlowEntry newFlowEntry) {
935 //
936 // Iterate over all Flow Entries and find a match based on
937 // the Flow Entry ID.
938 //
939 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
940 if (! localFlowEntry.isValidFlowEntryId())
941 continue;
942 if (localFlowEntry.flowEntryId().value() !=
943 newFlowEntry.flowEntryId().value()) {
944 continue;
945 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800946 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700947 }
948
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800949 return null; // Entry not found
950 }
951
952 /**
953 * Update a Flow Entry because of an external ENTRY_REMOVE event.
954 *
955 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800956 * @param localFlowEntry the local Flow Entry to update.
957 * @param newFlowEntry the FlowEntry with the new state.
958 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800959 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800960 private boolean updateFlowEntryRemove(FlowPath flowPath,
961 FlowEntry localFlowEntry,
962 FlowEntry newFlowEntry) {
963 boolean updated = false;
964
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800965 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800966 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800967 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800968 if (localFlowEntry.flowEntryUserState() !=
969 newFlowEntry.flowEntryUserState()) {
970 localFlowEntry.setFlowEntryUserState(
971 newFlowEntry.flowEntryUserState());
972 updated = true;
973 }
974 if (localFlowEntry.flowEntrySwitchState() !=
975 newFlowEntry.flowEntrySwitchState()) {
976 localFlowEntry.setFlowEntrySwitchState(
977 newFlowEntry.flowEntrySwitchState());
978 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800979 }
980
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800981 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700982 }
983
984 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700985 * Recompute a Flow Path.
986 *
987 * @param flowPath the Flow Path to recompute.
988 * @return true if the recomputed Flow Path has changed, otherwise false.
989 */
990 private boolean recomputeFlowPath(FlowPath flowPath) {
991 boolean hasChanged = false;
992
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -0800993 if (enableOnrc2014MeasurementsFlows) {
994 // Cleanup the deleted Flow Entries from the earlier iteration
995 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800996
997 //
998 // TODO: Fake it that the Flow Entries have been already pushed
999 // into the switches, so we don't push them again.
1000 //
1001 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1002 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1003 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001004 }
1005
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001006 //
1007 // Test whether the Flow Path needs to be recomputed
1008 //
1009 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001010 case FP_TYPE_UNKNOWN:
1011 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001012 case FP_TYPE_SHORTEST_PATH:
1013 break;
1014 case FP_TYPE_EXPLICIT_PATH:
1015 return false; // An explicit path never changes
1016 }
1017
1018 DataPath oldDataPath = flowPath.dataPath();
1019
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001020 // Compute the new path
Naoki Shiota9f6fc212014-01-09 21:38:08 -08001021 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001022 flowPath);
Naoki Shiotaf74d5f32014-01-09 21:29:38 -08001023
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001024 if (newDataPath == null) {
1025 // We need the DataPath to compare the paths
1026 newDataPath = new DataPath();
1027 }
1028 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1029
1030 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001031 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001032 //
1033 if (oldDataPath.flowEntries().size() !=
1034 newDataPath.flowEntries().size()) {
1035 hasChanged = true;
1036 } else {
1037 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1038 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1039 while (oldIter.hasNext() && newIter.hasNext()) {
1040 FlowEntry oldFlowEntry = oldIter.next();
1041 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001042 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1043 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001044 hasChanged = true;
1045 break;
1046 }
1047 }
1048 }
1049 if (! hasChanged)
1050 return hasChanged;
1051
1052 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001053 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001054 // - If a Flow Entry for a switch is in the old data path, but not
1055 // in the new data path, then mark it for deletion.
1056 // - If a Flow Entry for a switch is in the new data path, but not
1057 // in the old data path, then mark it for addition.
1058 // - If a Flow Entry for a switch is in both the old and the new
1059 // data path, but it has changed, e.g., the incoming and/or outgoing
1060 // port(s), then mark the old Flow Entry for deletion, and mark
1061 // the new Flow Entry for addition.
1062 // - If a Flow Entry for a switch is in both the old and the new
1063 // data path, and it hasn't changed, then just keep it.
1064 //
1065 // NOTE: We use the Switch DPID of each entry to match the entries
1066 //
1067 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1068 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1069 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1070 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1071
1072 // Prepare maps with the Flow Entries, so they are fast to lookup
1073 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1074 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1075 for (FlowEntry flowEntry : newDataPath.flowEntries())
1076 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1077
1078 //
1079 // Find the old Flow Entries that should be deleted
1080 //
1081 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1082 FlowEntry newFlowEntry =
1083 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1084 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001085 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001086 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1087 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1088 deletedFlowEntries.add(oldFlowEntry);
1089 }
1090 }
1091
1092 //
1093 // Find the new Flow Entries that should be added or updated
1094 //
1095 int idx = 0;
1096 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1097 FlowEntry oldFlowEntry =
1098 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1099
1100 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001101 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1102 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001103 //
1104 // Both Flow Entries are same
1105 //
1106 finalFlowEntries.add(oldFlowEntry);
1107 idx++;
1108 continue;
1109 }
1110
1111 if (oldFlowEntry != null) {
1112 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001113 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001114 //
1115 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1116 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1117 deletedFlowEntries.add(oldFlowEntry);
1118 }
1119
1120 //
1121 // Add the new Flow Entry
1122 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001123 //
1124 // NOTE: Assign only the Flow ID.
1125 // The Flow Entry ID is assigned later only for the Flow Entries
1126 // this instance is responsible for.
1127 //
1128 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001129
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001130 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001131 // Copy the Flow timeouts
1132 //
1133 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1134 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1135
1136 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001137 // Allocate the FlowEntryMatch by copying the default one
1138 // from the FlowPath (if set).
1139 //
1140 FlowEntryMatch flowEntryMatch = null;
1141 if (flowPath.flowEntryMatch() != null)
1142 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1143 else
1144 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001145 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001146
1147 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001148 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1149
1150 //
1151 // Set the actions:
1152 // If the first Flow Entry, copy the Flow Path actions to it.
1153 //
1154 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1155 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1156 FlowEntryActions flowActions =
1157 new FlowEntryActions(flowPath.flowEntryActions());
1158 for (FlowEntryAction action : flowActions.actions())
1159 flowEntryActions.addAction(action);
1160 }
1161 idx++;
1162
1163 //
1164 // Add the outgoing port output action
1165 //
1166 FlowEntryAction flowEntryAction = new FlowEntryAction();
1167 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1168 flowEntryActions.addAction(flowEntryAction);
1169
1170 //
1171 // Set the state of the new Flow Entry
1172 //
1173 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1174 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1175 finalFlowEntries.add(newFlowEntry);
1176 }
1177
1178 //
1179 // Replace the old Flow Entries with the new Flow Entries.
1180 // Note that the Flow Entries that will be deleted are added at
1181 // the end.
1182 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001183 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001184 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1185
1186 return hasChanged;
1187 }
1188
1189 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001190 * Receive a notification that a Flow is added.
1191 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001192 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001193 */
1194 @Override
1195 public void notificationRecvFlowAdded(FlowPath flowPath) {
1196 EventEntry<FlowPath> eventEntry =
1197 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1198 networkEvents.add(eventEntry);
1199 }
1200
1201 /**
1202 * Receive a notification that a Flow is removed.
1203 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001204 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001205 */
1206 @Override
1207 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1208 EventEntry<FlowPath> eventEntry =
1209 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1210 networkEvents.add(eventEntry);
1211 }
1212
1213 /**
1214 * Receive a notification that a Flow is updated.
1215 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001216 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001217 */
1218 @Override
1219 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1220 // NOTE: The ADD and UPDATE events are processed in same way
1221 EventEntry<FlowPath> eventEntry =
1222 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1223 networkEvents.add(eventEntry);
1224 }
1225
1226 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001227 * Receive a notification that a FlowEntry is added.
1228 *
1229 * @param flowEntry the FlowEntry that is added.
1230 */
1231 @Override
1232 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001233 if (enableOnrc2014MeasurementsFlows) {
1234 Collection entries = new ArrayList();
1235 entries.add(flowEntry);
1236 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1237 return;
1238 }
1239
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001240 EventEntry<FlowEntry> eventEntry =
1241 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1242 networkEvents.add(eventEntry);
1243 }
1244
1245 /**
1246 * Receive a notification that a FlowEntry is removed.
1247 *
1248 * @param flowEntry the FlowEntry that is removed.
1249 */
1250 @Override
1251 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001252 if (enableOnrc2014MeasurementsFlows) {
1253 Collection entries = new ArrayList();
1254 entries.add(flowEntry);
1255 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1256 return;
1257 }
1258
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001259 EventEntry<FlowEntry> eventEntry =
1260 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1261 networkEvents.add(eventEntry);
1262 }
1263
1264 /**
1265 * Receive a notification that a FlowEntry is updated.
1266 *
1267 * @param flowEntry the FlowEntry that is updated.
1268 */
1269 @Override
1270 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001271 if (enableOnrc2014MeasurementsFlows) {
1272 Collection entries = new ArrayList();
1273 entries.add(flowEntry);
1274 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1275 return;
1276 }
1277
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001278 // NOTE: The ADD and UPDATE events are processed in same way
1279 EventEntry<FlowEntry> eventEntry =
1280 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1281 networkEvents.add(eventEntry);
1282 }
1283
1284 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001285 * Receive a notification that a FlowId is added.
1286 *
1287 * @param flowId the FlowId that is added.
1288 */
1289 @Override
1290 public void notificationRecvFlowIdAdded(FlowId flowId) {
1291 EventEntry<FlowId> eventEntry =
1292 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1293 networkEvents.add(eventEntry);
1294 }
1295
1296 /**
1297 * Receive a notification that a FlowId is removed.
1298 *
1299 * @param flowId the FlowId that is removed.
1300 */
1301 @Override
1302 public void notificationRecvFlowIdRemoved(FlowId flowId) {
1303 EventEntry<FlowId> eventEntry =
1304 new EventEntry<FlowId>(EventEntry.Type.ENTRY_REMOVE, flowId);
1305 networkEvents.add(eventEntry);
1306 }
1307
1308 /**
1309 * Receive a notification that a FlowId is updated.
1310 *
1311 * @param flowId the FlowId that is updated.
1312 */
1313 @Override
1314 public void notificationRecvFlowIdUpdated(FlowId flowId) {
1315 // NOTE: The ADD and UPDATE events are processed in same way
1316 EventEntry<FlowId> eventEntry =
1317 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1318 networkEvents.add(eventEntry);
1319 }
1320
1321 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001322 * Receive a notification that a FlowEntryId is added.
1323 *
1324 * @param flowEntryId the FlowEntryId that is added.
1325 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1326 */
1327 @Override
1328 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1329 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001330 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1331
1332 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1333 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001334 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001335 }
1336
1337 /**
1338 * Receive a notification that a FlowEntryId is removed.
1339 *
1340 * @param flowEntryId the FlowEntryId that is removed.
1341 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1342 */
1343 @Override
1344 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1345 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001346 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1347
1348 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1349 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001350 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001351 }
1352
1353 /**
1354 * Receive a notification that a FlowEntryId is updated.
1355 *
1356 * @param flowEntryId the FlowEntryId that is updated.
1357 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1358 */
1359 @Override
1360 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1361 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001362 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1363
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001364 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001365 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1366 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001367 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001368 }
1369
1370 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001371 * Receive a notification that a Topology Element is added.
1372 *
1373 * @param topologyElement the Topology Element that is added.
1374 */
1375 @Override
1376 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1377 EventEntry<TopologyElement> eventEntry =
1378 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1379 networkEvents.add(eventEntry);
1380 }
1381
1382 /**
1383 * Receive a notification that a Topology Element is removed.
1384 *
1385 * @param topologyElement the Topology Element that is removed.
1386 */
1387 @Override
1388 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1389 EventEntry<TopologyElement> eventEntry =
1390 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1391 networkEvents.add(eventEntry);
1392 }
1393
1394 /**
1395 * Receive a notification that a Topology Element is updated.
1396 *
1397 * @param topologyElement the Topology Element that is updated.
1398 */
1399 @Override
1400 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1401 // NOTE: The ADD and UPDATE events are processed in same way
1402 EventEntry<TopologyElement> eventEntry =
1403 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1404 networkEvents.add(eventEntry);
1405 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001406
1407 /**
1408 * Get a sorted copy of all Flow Paths.
1409 *
1410 * @return a sorted copy of all Flow Paths.
1411 */
1412 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1413 SortedMap<Long, FlowPath> sortedFlowPaths =
1414 new TreeMap<Long, FlowPath>();
1415
1416 //
1417 // TODO: For now we use serialization/deserialization to create
1418 // a copy of each Flow Path. In the future, we should use proper
1419 // copy constructors.
1420 //
1421 Kryo kryo = kryoFactory.newKryo();
1422 synchronized (allFlowPaths) {
1423 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1424 FlowPath origFlowPath = entry.getValue();
1425 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1426 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1427 }
1428 }
1429 kryoFactory.deleteKryo(kryo);
1430
1431 return sortedFlowPaths;
1432 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001433}