blob: e4e9a76823003cfab1059cba260c7a9d68e3a7cb [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;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070059 private FlowManager flowManager; // The Flow Manager to use
60 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070061 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080062 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070063
64 // The queue with Flow Path and Topology Element updates
65 private BlockingQueue<EventEntry<?>> networkEvents =
66 new LinkedBlockingQueue<EventEntry<?>>();
67
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070068 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070069 private List<EventEntry<TopologyElement>> topologyEvents =
70 new LinkedList<EventEntry<TopologyElement>>();
71 private List<EventEntry<FlowPath>> flowPathEvents =
72 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070073 private List<EventEntry<FlowEntry>> flowEntryEvents =
74 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -080075 private List<EventEntry<FlowId>> flowIdEvents =
76 new LinkedList<EventEntry<FlowId>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080077 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
78 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070079
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080080 // All internally computed Flow Paths
81 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
82
83 // The Flow Entries received as notifications with unmatched Flow Paths
84 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
85 new HashMap<Long, FlowEntry>();
86
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080087 //
88 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080089 // - The Flow Paths that should be recomputed
90 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080091 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080092 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080093 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
94 new HashMap<Long, FlowPath>();
95 private Map<Long, FlowPath> modifiedFlowPaths =
96 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080097 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
98 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080099
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700100 /**
101 * Constructor for a given Flow Manager and Datagrid Service.
102 *
103 * @param flowManager the Flow Manager to use.
104 * @param datagridService the Datagrid Service to use.
105 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700106 FlowEventHandler(FlowManager flowManager,
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800107 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700108 this.flowManager = flowManager;
109 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700110 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700111 }
112
113 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800114 * Get the network topology.
115 *
116 * @return the network topology.
117 */
118 protected Topology getTopology() { return this.topology; }
119
120 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800121 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700122 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800123 private void startup() {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800124 this.dbHandler = new GraphDBOperation("");
125
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700126 //
127 // Obtain the initial Topology state
128 //
129 Collection<TopologyElement> topologyElements =
130 datagridService.getAllTopologyElements();
131 for (TopologyElement topologyElement : topologyElements) {
132 EventEntry<TopologyElement> eventEntry =
133 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
134 topologyEvents.add(eventEntry);
135 }
136 //
137 // Obtain the initial Flow Path state
138 //
139 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
140 for (FlowPath flowPath : flowPaths) {
141 EventEntry<FlowPath> eventEntry =
142 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
143 flowPathEvents.add(eventEntry);
144 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700145 //
146 // Obtain the initial FlowEntry state
147 //
148 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
149 for (FlowEntry flowEntry : flowEntries) {
150 EventEntry<FlowEntry> eventEntry =
151 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
152 flowEntryEvents.add(eventEntry);
153 }
154
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800155 //
156 // Obtain the initial FlowId state
157 //
158 Collection<FlowId> flowIds = datagridService.getAllFlowIds();
159 for (FlowId flowId : flowIds) {
160 EventEntry<FlowId> eventEntry =
161 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
162 flowIdEvents.add(eventEntry);
163 }
164
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800165 //
166 // Obtain the initial FlowEntryId state
167 //
168 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
169 datagridService.getAllFlowEntryIds();
170 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
171 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
172 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
173 flowEntryIdEvents.add(eventEntry);
174 }
175
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800176 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800177 synchronized (allFlowPaths) {
178 processEvents();
179 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800180 }
181
182 /**
183 * Run the thread.
184 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800185 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800186 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800187 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800188 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700189
190 //
191 // The main loop
192 //
193 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
194 try {
195 while (true) {
196 EventEntry<?> eventEntry = networkEvents.take();
197 collection.add(eventEntry);
198 networkEvents.drainTo(collection);
199
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700200 //
201 // Demultiplex all events:
202 // - EventEntry<TopologyElement>
203 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700204 // - EventEntry<FlowEntry>
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800205 // - EventEntry<FlowId>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800206 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700207 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700208 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800209 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700210 if (event.eventData() instanceof TopologyElement) {
211 EventEntry<TopologyElement> topologyEventEntry =
212 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800213
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700214 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800215 continue;
216 }
217
218 // FlowPath event
219 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700220 EventEntry<FlowPath> flowPathEventEntry =
221 (EventEntry<FlowPath>)event;
222 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800223 continue;
224 }
225
226 // FlowEntry event
227 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700228 EventEntry<FlowEntry> flowEntryEventEntry =
229 (EventEntry<FlowEntry>)event;
230 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800231 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700232 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800233
234 // FlowId event
235 if (event.eventData() instanceof FlowId) {
236 EventEntry<FlowId> flowIdEventEntry =
237 (EventEntry<FlowId>)event;
238 flowIdEvents.add(flowIdEventEntry);
239 continue;
240 }
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800241 // FlowEntryId event
242 if (event.eventData() instanceof Pair) {
243 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
244 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
245 flowEntryIdEvents.add(flowEntryIdEventEntry);
246 continue;
247 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700248 }
249 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700250
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700251 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800252 synchronized (allFlowPaths) {
253 processEvents();
254 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700255 }
256 } catch (Exception exception) {
257 log.debug("Exception processing Network Events: ", exception);
258 }
259 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800260
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700261 /**
262 * Process the events (if any)
263 */
264 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800265 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700266
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800267 if (enableOnrc2014MeasurementsFlows) {
268
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800269 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
270 flowEntryIdEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800271 return; // Nothing to do
272 }
273
274 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
275
276 // Fetch and prepare my flows
277 prepareMyFlows(mySwitches);
278
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800279 // Process the Flow ID events
280 processFlowIdEvents(mySwitches);
281
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800282 // Fetch the topology
283 processTopologyEvents();
284
285 // Recompute all affected Flow Paths and keep only the modified
286 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
287 if (recomputeFlowPath(flowPath))
288 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
289 }
290
291 // Assign the Flow Entry ID as needed
292 for (FlowPath flowPath : modifiedFlowPaths.values()) {
293 for (FlowEntry flowEntry : flowPath.flowEntries()) {
294 if (! flowEntry.isValidFlowEntryId()) {
295 long id = flowManager.getNextFlowEntryId();
296 flowEntry.setFlowEntryId(new FlowEntryId(id));
297 }
298 }
299 }
300
301 // Extract my modified Flow Entries
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800302 modifiedFlowEntries = processFlowEntryIdEvents(mySwitches);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800303
304 //
305 // Push the modified state to the Flow Manager
306 //
307 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
308 modifiedFlowEntries);
309
310 // Cleanup
311 topologyEvents.clear();
312 flowIdEvents.clear();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800313 flowEntryIdEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800314 //
315 allFlowPaths.clear();
316 shouldRecomputeFlowPaths.clear();
317 modifiedFlowPaths.clear();
318
319 return;
320 }
321
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700322 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800323 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700324 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700325 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700326
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800327 processFlowPathEvents();
328 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800329 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800330 processFlowEntryEvents();
331
332 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800333 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800334 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800335 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800336 }
337
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800338 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800339 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800340
341 // Assign missing Flow Entry IDs
342 assignFlowEntryId(modifiedFlowEntries);
343
344 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800345 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800346 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800347 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
348 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800349
350 //
351 // Remove Flow Entries that were deleted
352 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800353 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800354 flowPath.dataPath().removeDeletedFlowEntries();
355
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800356 //
357 // Check if Flow Paths have been installed into all switches,
358 // and generate the appropriate events.
359 //
360 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
361
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800362 // Cleanup
363 topologyEvents.clear();
364 flowPathEvents.clear();
365 flowEntryEvents.clear();
366 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800367 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800368 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800369 checkIfInstalledFlowPaths.clear();
370 }
371
372 /**
373 * Check if Flow Paths have been installed into all switches,
374 * and generate the appropriate events.
375 *
376 * @param flowPaths the flowPaths to process.
377 */
378 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
379 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
380
381 Kryo kryo = kryoFactory.newKryo();
382
383 for (FlowPath flowPath : flowPaths) {
384 boolean isInstalled = true;
385
386 //
387 // Check whether all Flow Entries have been installed
388 //
389 for (FlowEntry flowEntry : flowPath.flowEntries()) {
390 if (flowEntry.flowEntrySwitchState() !=
391 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
392 isInstalled = false;
393 break;
394 }
395 }
396
397 if (isInstalled) {
398 // Create a copy and add it to the list
399 FlowPath copyFlowPath = kryo.copy(flowPath);
400 installedFlowPaths.add(copyFlowPath);
401 }
402 }
403 kryoFactory.deleteKryo(kryo);
404
405 // Generate an event for the installed Flow Path.
406 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800407 }
408
409 /**
410 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800411 *
412 * @param modifiedFlowPaths the Flow Paths to process.
413 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800414 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800415 private Collection<FlowEntry> extractModifiedFlowEntries(
416 Collection<FlowPath> modifiedFlowPaths) {
417 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800418
419 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800420 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800421 for (FlowEntry flowEntry : flowPath.flowEntries()) {
422 if (flowEntry.flowEntrySwitchState() ==
423 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800424 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800425 }
426 }
427 }
428 return modifiedFlowEntries;
429 }
430
431 /**
432 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800433 *
434 * @param modifiedFlowEnries the collection of Flow Entries that need
435 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800436 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800437 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800438 if (modifiedFlowEntries.isEmpty())
439 return;
440
441 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
442
443 //
444 // Assign the Flow Entry ID only for Flow Entries for my switches
445 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800446 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800447 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
448 if (mySwitch == null)
449 continue;
450 if (! flowEntry.isValidFlowEntryId()) {
451 long id = flowManager.getNextFlowEntryId();
452 flowEntry.setFlowEntryId(new FlowEntryId(id));
453 }
454 }
455 }
456
457 /**
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800458 * Prepare my flows.
459 *
460 * @param mySwitches the collection of my switches.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800461 */
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800462 private void prepareMyFlows(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800463 if (! topologyEvents.isEmpty()) {
464 // Fetch my flows from the database
465 ArrayList<FlowPath> myFlows = FlowDatabaseOperation.getAllMyFlows(dbHandler, mySwitches);
466 for (FlowPath flowPath : myFlows) {
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800467 log.debug("Found my flow: {}", flowPath);
468
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800469 allFlowPaths.put(flowPath.flowId().value(), flowPath);
470
471 //
472 // TODO: Bug workaround / fix :
473 // method FlowDatabaseOperation.extractFlowEntry() doesn't
474 // fetch the inPort and outPort, hence we assign them here.
475 //
476 // Assign the inPort and outPort for the Flow Entries
477 for (FlowEntry flowEntry : flowPath.flowEntries()) {
478 // Set the inPort
479 do {
480 if (flowEntry.inPort() != null)
481 break;
482 if (flowEntry.flowEntryMatch() == null)
483 break;
484 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
485 flowEntry.setInPort(inPort);
486 } while (false);
487
488 // Set the outPort
489 do {
490 if (flowEntry.outPort() != null)
491 break;
492 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
493 if (fa.actionOutput() != null) {
494 Port outPort = new Port(fa.actionOutput().port().value());
495 flowEntry.setOutPort(outPort);
496 break;
497 }
498 }
499 } while (false);
500 }
501 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800502 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800503 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800504
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800505 /**
506 * Process the Flow ID events.
507 *
508 * @param mySwitches the collection of my switches.
509 */
510 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800511 //
512 // Automatically add all Flow ID events (for the Flows this instance
513 // is responsible for) to the collection of Flows to recompute.
514 //
515 for (EventEntry<FlowId> eventEntry : flowIdEvents) {
516 FlowId flowId = eventEntry.eventData();
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800517
518 log.debug("Flow ID Event: {} {}", eventEntry.eventType(), flowId);
519
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800520 FlowPath flowPath = allFlowPaths.get(flowId.value());
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800521 if (flowPath == null) {
522 if (! topologyEvents.isEmpty())
523 continue; // Optimization: Not my flow
524 Dpid dpid = FlowDatabaseOperation.getFlowSourceDpid(dbHandler,
525 flowId);
526 if ((dpid != null) && (mySwitches.get(dpid.value()) != null)) {
527 flowPath = FlowDatabaseOperation.getFlow(dbHandler,
528 flowId);
529 }
530 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800531 if (flowPath != null) {
532 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
533 flowPath);
534 }
535 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800536 }
537
538 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800539 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800540 *
541 * @param mySwitches the collection of my switches.
542 * @return a collection of modified Flow Entries this instance needs
543 * to push to its own switches.
544 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800545 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800546 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
547
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800548 //
549 // Process all Flow ID events and update the appropriate state
550 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800551 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
552 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
553 FlowEntryId flowEntryId = pair.first;
554 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800555
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800556 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
557 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800558
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800559 if (mySwitches.get(dpid.value()) == null)
560 continue;
561
562 // Fetch the Flow Entry
563 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
564 flowEntryId);
565 if (flowEntry == null) {
566 log.debug("Flow Entry ID {} : Flow Entry not found!",
567 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800568 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800569 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800570 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800571 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800572
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800573 return modifiedFlowEntries;
574 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800575
576 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800577 * Process the Flow Path events.
578 */
579 private void processFlowPathEvents() {
580 //
581 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700582 //
583 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
584 FlowPath flowPath = eventEntry.eventData();
585
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800586 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800587
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700588 switch (eventEntry.eventType()) {
589 case ENTRY_ADD: {
590 //
591 // Add a new Flow Path
592 //
593 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
594 //
595 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800596 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700597 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700598 }
599
600 switch (flowPath.flowPathType()) {
601 case FP_TYPE_SHORTEST_PATH:
602 //
603 // Reset the Data Path, in case it was set already, because
604 // we are going to recompute it anyway.
605 //
606 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800607 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
608 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700609 break;
610 case FP_TYPE_EXPLICIT_PATH:
611 //
612 // Mark all Flow Entries for installation in the switches.
613 //
614 for (FlowEntry flowEntry : flowPath.flowEntries()) {
615 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
616 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800617 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700618 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800619 case FP_TYPE_UNKNOWN:
620 log.error("FlowPath event with unknown type");
621 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700622 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800623 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700624
625 break;
626 }
627
628 case ENTRY_REMOVE: {
629 //
630 // Remove an existing Flow Path.
631 //
632 // Find the Flow Path, and mark the Flow and its Flow Entries
633 // for deletion.
634 //
635 FlowPath existingFlowPath =
636 allFlowPaths.get(flowPath.flowId().value());
637 if (existingFlowPath == null)
638 continue; // Nothing to do
639
640 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
641 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
642 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
643 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
644 }
645
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800646 // Remove the Flow Path from the internal state
647 Long key = existingFlowPath.flowId().value();
648 allFlowPaths.remove(key);
649 shouldRecomputeFlowPaths.remove(key);
650 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700651
652 break;
653 }
654 }
655 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800656 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700657
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800658 /**
659 * Process the Topology events.
660 */
661 private void processTopologyEvents() {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800662 if (enableOnrc2014MeasurementsTopology) {
663 if (topologyEvents.isEmpty())
664 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800665
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800666 //
667 // TODO: Fake the topology read it by checking the cache with
668 // the old topology and ignoring topology events that don't make
669 // any impact to the topology.
670 // This is needed aa workaround: if a port is down, we get
671 // up to three additional "Port Down" or "Link Down" events.
672 //
673 boolean isTopologyModified = false;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800674 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
675 TopologyElement topologyElement = eventEntry.eventData();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800676
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800677 log.debug("Topology Event: {} {}", eventEntry.eventType(),
678 topologyElement.toString());
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800679
680 switch (eventEntry.eventType()) {
681 case ENTRY_ADD:
682 isTopologyModified |= topology.addTopologyElement(topologyElement);
683 break;
684 case ENTRY_REMOVE:
685 isTopologyModified |= topology.removeTopologyElement(topologyElement);
686 break;
687 }
688 if (isTopologyModified)
689 break;
690 }
691 if (! isTopologyModified) {
692 log.debug("Ignoring topology events that don't modify the topology");
693 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800694 }
695
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800696 log.debug("[BEFORE] {}", topology.toString());
697 topology.readFromDatabase(dbHandler);
698 log.debug("[AFTER] {}", topology.toString());
699 shouldRecomputeFlowPaths.putAll(allFlowPaths);
700 return;
701 }
702
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700703 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800704 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700705 //
706 boolean isTopologyModified = false;
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800707 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
708 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800709
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800710 log.debug("Topology Event: {} {}", eventEntry.eventType(),
711 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800712
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800713 switch (eventEntry.eventType()) {
714 case ENTRY_ADD:
715 isTopologyModified |= topology.addTopologyElement(topologyElement);
716 break;
717 case ENTRY_REMOVE:
718 isTopologyModified |= topology.removeTopologyElement(topologyElement);
719 break;
720 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700721 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700722 if (isTopologyModified) {
723 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800724 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700725 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800726 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700727
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800728 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800729 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800730 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800731 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800732 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800733 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800734
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700735 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800736 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700737 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800738 if (! unmatchedFlowEntryAdd.isEmpty()) {
739 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
740 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800741 // log.debug("Processing Unmatched Flow Entry: {}",
742 // flowEntry.toString());
743
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800744 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800745 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800746 remainingUpdates.put(flowEntry.flowEntryId().value(),
747 flowEntry);
748 continue;
749 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800750 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
751 if (localFlowEntry == 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 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
757 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
758 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700759 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800760 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700761 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800762 }
763
764 /**
765 * Process the Flow Entry events.
766 */
767 private void processFlowEntryEvents() {
768 FlowPath flowPath;
769 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700770
771 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800772 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700773 //
774 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
775 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800776
777 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800778 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800779
780 if ((! flowEntry.isValidFlowId()) ||
781 (! flowEntry.isValidFlowEntryId())) {
782 continue;
783 }
784
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700785 switch (eventEntry.eventType()) {
786 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800787 flowPath = allFlowPaths.get(flowEntry.flowId().value());
788 if (flowPath == null) {
789 // Flow Path not found: keep the entry for later matching
790 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
791 flowEntry);
792 break;
793 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800794 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
795 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800796 // Flow Entry not found: keep the entry for later matching
797 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
798 flowEntry);
799 break;
800 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800801 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
802 // Add the updated Flow Path to the list of updated paths
803 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
804 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700805 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800806
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700807 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800808 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
809 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800810 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800811 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800812
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800813 flowPath = allFlowPaths.get(flowEntry.flowId().value());
814 if (flowPath == null) {
815 // Flow Path not found: ignore the update
816 break;
817 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800818 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
819 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800820 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800821 break;
822 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800823 if (updateFlowEntryRemove(flowPath, localFlowEntry,
824 flowEntry)) {
825 // Add the updated Flow Path to the list of updated paths
826 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
827 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700828 break;
829 }
830 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700831 }
832
833 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800834 * Find a Flow Entry that should be updated because of an external
835 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700836 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800837 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800838 * @param newFlowEntry the FlowEntry with the new state.
839 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700840 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800841 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
842 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700843 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800844 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700845 //
846 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800847 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800848 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700849 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800850 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700851
852 //
853 // Local Flow Entry match found
854 //
855 if (localFlowEntry.isValidFlowEntryId()) {
856 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800857 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700858 //
859 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800860 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700861 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800862 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700863 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700864 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800865 return localFlowEntry;
866 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700867
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800868 return null; // Entry not found
869 }
870
871 /**
872 * Update a Flow Entry because of an external ENTRY_ADD event.
873 *
874 * @param flowPath the FlowPath for the Flow Entry to update.
875 * @param localFlowEntry the local Flow Entry to update.
876 * @param newFlowEntry the FlowEntry with the new state.
877 * @return true if the local Flow Entry was updated, otherwise false.
878 */
879 private boolean updateFlowEntryAdd(FlowPath flowPath,
880 FlowEntry localFlowEntry,
881 FlowEntry newFlowEntry) {
882 boolean updated = false;
883
884 if (localFlowEntry.flowEntryUserState() ==
885 FlowEntryUserState.FE_USER_DELETE) {
886 // Don't add-back a Flow Entry that is already deleted
887 return false;
888 }
889
890 if (! localFlowEntry.isValidFlowEntryId()) {
891 // Update the Flow Entry ID
892 FlowEntryId flowEntryId =
893 new FlowEntryId(newFlowEntry.flowEntryId().value());
894 localFlowEntry.setFlowEntryId(flowEntryId);
895 updated = true;
896 }
897
898 //
899 // Update the local Flow Entry, and keep state to check
900 // if the Flow Path has been installed.
901 //
902 if (localFlowEntry.flowEntryUserState() !=
903 newFlowEntry.flowEntryUserState()) {
904 localFlowEntry.setFlowEntryUserState(
905 newFlowEntry.flowEntryUserState());
906 updated = true;
907 }
908 if (localFlowEntry.flowEntrySwitchState() !=
909 newFlowEntry.flowEntrySwitchState()) {
910 localFlowEntry.setFlowEntrySwitchState(
911 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800912 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800913 updated = true;
914 }
915
916 return updated;
917 }
918
919 /**
920 * Find a Flow Entry that should be updated because of an external
921 * ENTRY_REMOVE event.
922 *
923 * @param flowPath the FlowPath for the Flow Entry to update.
924 * @param newFlowEntry the FlowEntry with the new state.
925 * @return the Flow Entry that should be updated if found, otherwise null.
926 */
927 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
928 FlowEntry newFlowEntry) {
929 //
930 // Iterate over all Flow Entries and find a match based on
931 // the Flow Entry ID.
932 //
933 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
934 if (! localFlowEntry.isValidFlowEntryId())
935 continue;
936 if (localFlowEntry.flowEntryId().value() !=
937 newFlowEntry.flowEntryId().value()) {
938 continue;
939 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800940 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700941 }
942
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800943 return null; // Entry not found
944 }
945
946 /**
947 * Update a Flow Entry because of an external ENTRY_REMOVE event.
948 *
949 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800950 * @param localFlowEntry the local Flow Entry to update.
951 * @param newFlowEntry the FlowEntry with the new state.
952 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800953 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800954 private boolean updateFlowEntryRemove(FlowPath flowPath,
955 FlowEntry localFlowEntry,
956 FlowEntry newFlowEntry) {
957 boolean updated = false;
958
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800959 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800960 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800961 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800962 if (localFlowEntry.flowEntryUserState() !=
963 newFlowEntry.flowEntryUserState()) {
964 localFlowEntry.setFlowEntryUserState(
965 newFlowEntry.flowEntryUserState());
966 updated = true;
967 }
968 if (localFlowEntry.flowEntrySwitchState() !=
969 newFlowEntry.flowEntrySwitchState()) {
970 localFlowEntry.setFlowEntrySwitchState(
971 newFlowEntry.flowEntrySwitchState());
972 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800973 }
974
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800975 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700976 }
977
978 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700979 * Recompute a Flow Path.
980 *
981 * @param flowPath the Flow Path to recompute.
982 * @return true if the recomputed Flow Path has changed, otherwise false.
983 */
984 private boolean recomputeFlowPath(FlowPath flowPath) {
985 boolean hasChanged = false;
986
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -0800987 if (enableOnrc2014MeasurementsFlows) {
988 // Cleanup the deleted Flow Entries from the earlier iteration
989 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800990
991 //
992 // TODO: Fake it that the Flow Entries have been already pushed
993 // into the switches, so we don't push them again.
994 //
995 for (FlowEntry flowEntry : flowPath.flowEntries()) {
996 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
997 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -0800998 }
999
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001000 //
1001 // Test whether the Flow Path needs to be recomputed
1002 //
1003 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001004 case FP_TYPE_UNKNOWN:
1005 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001006 case FP_TYPE_SHORTEST_PATH:
1007 break;
1008 case FP_TYPE_EXPLICIT_PATH:
1009 return false; // An explicit path never changes
1010 }
1011
1012 DataPath oldDataPath = flowPath.dataPath();
1013
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001014 // Compute the new path
1015 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
1016 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001017 if (newDataPath == null) {
1018 // We need the DataPath to compare the paths
1019 newDataPath = new DataPath();
1020 }
1021 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1022
1023 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001024 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001025 //
1026 if (oldDataPath.flowEntries().size() !=
1027 newDataPath.flowEntries().size()) {
1028 hasChanged = true;
1029 } else {
1030 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1031 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1032 while (oldIter.hasNext() && newIter.hasNext()) {
1033 FlowEntry oldFlowEntry = oldIter.next();
1034 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001035 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1036 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001037 hasChanged = true;
1038 break;
1039 }
1040 }
1041 }
1042 if (! hasChanged)
1043 return hasChanged;
1044
1045 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001046 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001047 // - If a Flow Entry for a switch is in the old data path, but not
1048 // in the new data path, then mark it for deletion.
1049 // - If a Flow Entry for a switch is in the new data path, but not
1050 // in the old data path, then mark it for addition.
1051 // - If a Flow Entry for a switch is in both the old and the new
1052 // data path, but it has changed, e.g., the incoming and/or outgoing
1053 // port(s), then mark the old Flow Entry for deletion, and mark
1054 // the new Flow Entry for addition.
1055 // - If a Flow Entry for a switch is in both the old and the new
1056 // data path, and it hasn't changed, then just keep it.
1057 //
1058 // NOTE: We use the Switch DPID of each entry to match the entries
1059 //
1060 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1061 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1062 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1063 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1064
1065 // Prepare maps with the Flow Entries, so they are fast to lookup
1066 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1067 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1068 for (FlowEntry flowEntry : newDataPath.flowEntries())
1069 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1070
1071 //
1072 // Find the old Flow Entries that should be deleted
1073 //
1074 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1075 FlowEntry newFlowEntry =
1076 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1077 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001078 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001079 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1080 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1081 deletedFlowEntries.add(oldFlowEntry);
1082 }
1083 }
1084
1085 //
1086 // Find the new Flow Entries that should be added or updated
1087 //
1088 int idx = 0;
1089 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1090 FlowEntry oldFlowEntry =
1091 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1092
1093 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001094 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1095 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001096 //
1097 // Both Flow Entries are same
1098 //
1099 finalFlowEntries.add(oldFlowEntry);
1100 idx++;
1101 continue;
1102 }
1103
1104 if (oldFlowEntry != null) {
1105 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001106 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001107 //
1108 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1109 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1110 deletedFlowEntries.add(oldFlowEntry);
1111 }
1112
1113 //
1114 // Add the new Flow Entry
1115 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001116 //
1117 // NOTE: Assign only the Flow ID.
1118 // The Flow Entry ID is assigned later only for the Flow Entries
1119 // this instance is responsible for.
1120 //
1121 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001122
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001123 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001124 // Copy the Flow timeouts
1125 //
1126 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1127 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1128
1129 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001130 // Allocate the FlowEntryMatch by copying the default one
1131 // from the FlowPath (if set).
1132 //
1133 FlowEntryMatch flowEntryMatch = null;
1134 if (flowPath.flowEntryMatch() != null)
1135 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1136 else
1137 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001138 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001139
1140 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001141 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1142
1143 //
1144 // Set the actions:
1145 // If the first Flow Entry, copy the Flow Path actions to it.
1146 //
1147 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1148 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1149 FlowEntryActions flowActions =
1150 new FlowEntryActions(flowPath.flowEntryActions());
1151 for (FlowEntryAction action : flowActions.actions())
1152 flowEntryActions.addAction(action);
1153 }
1154 idx++;
1155
1156 //
1157 // Add the outgoing port output action
1158 //
1159 FlowEntryAction flowEntryAction = new FlowEntryAction();
1160 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1161 flowEntryActions.addAction(flowEntryAction);
1162
1163 //
1164 // Set the state of the new Flow Entry
1165 //
1166 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1167 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1168 finalFlowEntries.add(newFlowEntry);
1169 }
1170
1171 //
1172 // Replace the old Flow Entries with the new Flow Entries.
1173 // Note that the Flow Entries that will be deleted are added at
1174 // the end.
1175 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001176 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001177 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1178
1179 return hasChanged;
1180 }
1181
1182 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001183 * Receive a notification that a Flow is added.
1184 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001185 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001186 */
1187 @Override
1188 public void notificationRecvFlowAdded(FlowPath flowPath) {
1189 EventEntry<FlowPath> eventEntry =
1190 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1191 networkEvents.add(eventEntry);
1192 }
1193
1194 /**
1195 * Receive a notification that a Flow is removed.
1196 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001197 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001198 */
1199 @Override
1200 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1201 EventEntry<FlowPath> eventEntry =
1202 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1203 networkEvents.add(eventEntry);
1204 }
1205
1206 /**
1207 * Receive a notification that a Flow is updated.
1208 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001209 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001210 */
1211 @Override
1212 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1213 // NOTE: The ADD and UPDATE events are processed in same way
1214 EventEntry<FlowPath> eventEntry =
1215 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1216 networkEvents.add(eventEntry);
1217 }
1218
1219 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001220 * Receive a notification that a FlowEntry is added.
1221 *
1222 * @param flowEntry the FlowEntry that is added.
1223 */
1224 @Override
1225 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
1226 EventEntry<FlowEntry> eventEntry =
1227 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1228 networkEvents.add(eventEntry);
1229 }
1230
1231 /**
1232 * Receive a notification that a FlowEntry is removed.
1233 *
1234 * @param flowEntry the FlowEntry that is removed.
1235 */
1236 @Override
1237 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
1238 EventEntry<FlowEntry> eventEntry =
1239 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1240 networkEvents.add(eventEntry);
1241 }
1242
1243 /**
1244 * Receive a notification that a FlowEntry is updated.
1245 *
1246 * @param flowEntry the FlowEntry that is updated.
1247 */
1248 @Override
1249 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
1250 // NOTE: The ADD and UPDATE events are processed in same way
1251 EventEntry<FlowEntry> eventEntry =
1252 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1253 networkEvents.add(eventEntry);
1254 }
1255
1256 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001257 * Receive a notification that a FlowId is added.
1258 *
1259 * @param flowId the FlowId that is added.
1260 */
1261 @Override
1262 public void notificationRecvFlowIdAdded(FlowId flowId) {
1263 EventEntry<FlowId> eventEntry =
1264 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1265 networkEvents.add(eventEntry);
1266 }
1267
1268 /**
1269 * Receive a notification that a FlowId is removed.
1270 *
1271 * @param flowId the FlowId that is removed.
1272 */
1273 @Override
1274 public void notificationRecvFlowIdRemoved(FlowId flowId) {
1275 EventEntry<FlowId> eventEntry =
1276 new EventEntry<FlowId>(EventEntry.Type.ENTRY_REMOVE, flowId);
1277 networkEvents.add(eventEntry);
1278 }
1279
1280 /**
1281 * Receive a notification that a FlowId is updated.
1282 *
1283 * @param flowId the FlowId that is updated.
1284 */
1285 @Override
1286 public void notificationRecvFlowIdUpdated(FlowId flowId) {
1287 // NOTE: The ADD and UPDATE events are processed in same way
1288 EventEntry<FlowId> eventEntry =
1289 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1290 networkEvents.add(eventEntry);
1291 }
1292
1293 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001294 * Receive a notification that a FlowEntryId is added.
1295 *
1296 * @param flowEntryId the FlowEntryId that is added.
1297 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1298 */
1299 @Override
1300 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1301 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001302 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1303
1304 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1305 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001306 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001307 }
1308
1309 /**
1310 * Receive a notification that a FlowEntryId is removed.
1311 *
1312 * @param flowEntryId the FlowEntryId that is removed.
1313 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1314 */
1315 @Override
1316 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1317 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001318 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1319
1320 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1321 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001322 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001323 }
1324
1325 /**
1326 * Receive a notification that a FlowEntryId is updated.
1327 *
1328 * @param flowEntryId the FlowEntryId that is updated.
1329 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1330 */
1331 @Override
1332 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1333 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001334 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1335
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001336 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001337 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1338 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001339 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001340 }
1341
1342 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001343 * Receive a notification that a Topology Element is added.
1344 *
1345 * @param topologyElement the Topology Element that is added.
1346 */
1347 @Override
1348 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1349 EventEntry<TopologyElement> eventEntry =
1350 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1351 networkEvents.add(eventEntry);
1352 }
1353
1354 /**
1355 * Receive a notification that a Topology Element is removed.
1356 *
1357 * @param topologyElement the Topology Element that is removed.
1358 */
1359 @Override
1360 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1361 EventEntry<TopologyElement> eventEntry =
1362 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1363 networkEvents.add(eventEntry);
1364 }
1365
1366 /**
1367 * Receive a notification that a Topology Element is updated.
1368 *
1369 * @param topologyElement the Topology Element that is updated.
1370 */
1371 @Override
1372 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1373 // NOTE: The ADD and UPDATE events are processed in same way
1374 EventEntry<TopologyElement> eventEntry =
1375 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1376 networkEvents.add(eventEntry);
1377 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001378
1379 /**
1380 * Get a sorted copy of all Flow Paths.
1381 *
1382 * @return a sorted copy of all Flow Paths.
1383 */
1384 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1385 SortedMap<Long, FlowPath> sortedFlowPaths =
1386 new TreeMap<Long, FlowPath>();
1387
1388 //
1389 // TODO: For now we use serialization/deserialization to create
1390 // a copy of each Flow Path. In the future, we should use proper
1391 // copy constructors.
1392 //
1393 Kryo kryo = kryoFactory.newKryo();
1394 synchronized (allFlowPaths) {
1395 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1396 FlowPath origFlowPath = entry.getValue();
1397 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1398 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1399 }
1400 }
1401 kryoFactory.deleteKryo(kryo);
1402
1403 return sortedFlowPaths;
1404 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001405}