blob: 7c745cf07ac6fbc358ed942df1d89b060ef0061d [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
666 // TODO: Code for debugging purpose only
667 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
668 TopologyElement topologyElement = eventEntry.eventData();
669 log.debug("Topology Event: {} {}", eventEntry.eventType(),
670 topologyElement.toString());
671 }
672
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800673 log.debug("[BEFORE] {}", topology.toString());
674 topology.readFromDatabase(dbHandler);
675 log.debug("[AFTER] {}", topology.toString());
676 shouldRecomputeFlowPaths.putAll(allFlowPaths);
677 return;
678 }
679
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700680 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800681 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700682 //
683 boolean isTopologyModified = false;
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800684 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
685 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800686
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800687 log.debug("Topology Event: {} {}", eventEntry.eventType(),
688 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800689
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800690 switch (eventEntry.eventType()) {
691 case ENTRY_ADD:
692 isTopologyModified |= topology.addTopologyElement(topologyElement);
693 break;
694 case ENTRY_REMOVE:
695 isTopologyModified |= topology.removeTopologyElement(topologyElement);
696 break;
697 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700698 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700699 if (isTopologyModified) {
700 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800701 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700702 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800703 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700704
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800705 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800706 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800707 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800708 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800709 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800710 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800711
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700712 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800713 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700714 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800715 if (! unmatchedFlowEntryAdd.isEmpty()) {
716 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
717 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800718 // log.debug("Processing Unmatched Flow Entry: {}",
719 // flowEntry.toString());
720
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800721 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800722 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800723 remainingUpdates.put(flowEntry.flowEntryId().value(),
724 flowEntry);
725 continue;
726 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800727 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
728 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800729 remainingUpdates.put(flowEntry.flowEntryId().value(),
730 flowEntry);
731 continue;
732 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800733 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
734 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
735 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700736 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800737 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700738 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800739 }
740
741 /**
742 * Process the Flow Entry events.
743 */
744 private void processFlowEntryEvents() {
745 FlowPath flowPath;
746 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700747
748 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800749 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700750 //
751 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
752 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800753
754 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800755 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800756
757 if ((! flowEntry.isValidFlowId()) ||
758 (! flowEntry.isValidFlowEntryId())) {
759 continue;
760 }
761
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700762 switch (eventEntry.eventType()) {
763 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800764 flowPath = allFlowPaths.get(flowEntry.flowId().value());
765 if (flowPath == null) {
766 // Flow Path not found: keep the entry for later matching
767 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
768 flowEntry);
769 break;
770 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800771 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
772 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800773 // Flow Entry not found: keep the entry for later matching
774 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
775 flowEntry);
776 break;
777 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800778 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
779 // Add the updated Flow Path to the list of updated paths
780 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
781 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700782 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800783
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700784 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800785 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
786 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800787 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800788 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800789
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800790 flowPath = allFlowPaths.get(flowEntry.flowId().value());
791 if (flowPath == null) {
792 // Flow Path not found: ignore the update
793 break;
794 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800795 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
796 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800797 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800798 break;
799 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800800 if (updateFlowEntryRemove(flowPath, localFlowEntry,
801 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;
806 }
807 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700808 }
809
810 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800811 * Find a Flow Entry that should be updated because of an external
812 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700813 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800814 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800815 * @param newFlowEntry the FlowEntry with the new state.
816 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700817 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800818 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
819 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700820 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800821 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700822 //
823 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800824 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800825 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700826 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800827 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700828
829 //
830 // Local Flow Entry match found
831 //
832 if (localFlowEntry.isValidFlowEntryId()) {
833 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800834 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700835 //
836 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800837 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700838 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800839 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700840 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700841 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800842 return localFlowEntry;
843 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700844
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800845 return null; // Entry not found
846 }
847
848 /**
849 * Update a Flow Entry because of an external ENTRY_ADD event.
850 *
851 * @param flowPath the FlowPath for the Flow Entry to update.
852 * @param localFlowEntry the local Flow Entry to update.
853 * @param newFlowEntry the FlowEntry with the new state.
854 * @return true if the local Flow Entry was updated, otherwise false.
855 */
856 private boolean updateFlowEntryAdd(FlowPath flowPath,
857 FlowEntry localFlowEntry,
858 FlowEntry newFlowEntry) {
859 boolean updated = false;
860
861 if (localFlowEntry.flowEntryUserState() ==
862 FlowEntryUserState.FE_USER_DELETE) {
863 // Don't add-back a Flow Entry that is already deleted
864 return false;
865 }
866
867 if (! localFlowEntry.isValidFlowEntryId()) {
868 // Update the Flow Entry ID
869 FlowEntryId flowEntryId =
870 new FlowEntryId(newFlowEntry.flowEntryId().value());
871 localFlowEntry.setFlowEntryId(flowEntryId);
872 updated = true;
873 }
874
875 //
876 // Update the local Flow Entry, and keep state to check
877 // if the Flow Path has been installed.
878 //
879 if (localFlowEntry.flowEntryUserState() !=
880 newFlowEntry.flowEntryUserState()) {
881 localFlowEntry.setFlowEntryUserState(
882 newFlowEntry.flowEntryUserState());
883 updated = true;
884 }
885 if (localFlowEntry.flowEntrySwitchState() !=
886 newFlowEntry.flowEntrySwitchState()) {
887 localFlowEntry.setFlowEntrySwitchState(
888 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800889 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800890 updated = true;
891 }
892
893 return updated;
894 }
895
896 /**
897 * Find a Flow Entry that should be updated because of an external
898 * ENTRY_REMOVE event.
899 *
900 * @param flowPath the FlowPath for the Flow Entry to update.
901 * @param newFlowEntry the FlowEntry with the new state.
902 * @return the Flow Entry that should be updated if found, otherwise null.
903 */
904 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
905 FlowEntry newFlowEntry) {
906 //
907 // Iterate over all Flow Entries and find a match based on
908 // the Flow Entry ID.
909 //
910 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
911 if (! localFlowEntry.isValidFlowEntryId())
912 continue;
913 if (localFlowEntry.flowEntryId().value() !=
914 newFlowEntry.flowEntryId().value()) {
915 continue;
916 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800917 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700918 }
919
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800920 return null; // Entry not found
921 }
922
923 /**
924 * Update a Flow Entry because of an external ENTRY_REMOVE event.
925 *
926 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800927 * @param localFlowEntry the local Flow Entry to update.
928 * @param newFlowEntry the FlowEntry with the new state.
929 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800930 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800931 private boolean updateFlowEntryRemove(FlowPath flowPath,
932 FlowEntry localFlowEntry,
933 FlowEntry newFlowEntry) {
934 boolean updated = false;
935
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800936 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800937 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800938 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800939 if (localFlowEntry.flowEntryUserState() !=
940 newFlowEntry.flowEntryUserState()) {
941 localFlowEntry.setFlowEntryUserState(
942 newFlowEntry.flowEntryUserState());
943 updated = true;
944 }
945 if (localFlowEntry.flowEntrySwitchState() !=
946 newFlowEntry.flowEntrySwitchState()) {
947 localFlowEntry.setFlowEntrySwitchState(
948 newFlowEntry.flowEntrySwitchState());
949 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800950 }
951
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800952 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700953 }
954
955 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700956 * Recompute a Flow Path.
957 *
958 * @param flowPath the Flow Path to recompute.
959 * @return true if the recomputed Flow Path has changed, otherwise false.
960 */
961 private boolean recomputeFlowPath(FlowPath flowPath) {
962 boolean hasChanged = false;
963
964 //
965 // Test whether the Flow Path needs to be recomputed
966 //
967 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -0700968 case FP_TYPE_UNKNOWN:
969 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700970 case FP_TYPE_SHORTEST_PATH:
971 break;
972 case FP_TYPE_EXPLICIT_PATH:
973 return false; // An explicit path never changes
974 }
975
976 DataPath oldDataPath = flowPath.dataPath();
977
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700978 // Compute the new path
979 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
980 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700981 if (newDataPath == null) {
982 // We need the DataPath to compare the paths
983 newDataPath = new DataPath();
984 }
985 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
986
987 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700988 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700989 //
990 if (oldDataPath.flowEntries().size() !=
991 newDataPath.flowEntries().size()) {
992 hasChanged = true;
993 } else {
994 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
995 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
996 while (oldIter.hasNext() && newIter.hasNext()) {
997 FlowEntry oldFlowEntry = oldIter.next();
998 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700999 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1000 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001001 hasChanged = true;
1002 break;
1003 }
1004 }
1005 }
1006 if (! hasChanged)
1007 return hasChanged;
1008
1009 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001010 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001011 // - If a Flow Entry for a switch is in the old data path, but not
1012 // in the new data path, then mark it for deletion.
1013 // - If a Flow Entry for a switch is in the new data path, but not
1014 // in the old data path, then mark it for addition.
1015 // - If a Flow Entry for a switch is in both the old and the new
1016 // data path, but it has changed, e.g., the incoming and/or outgoing
1017 // port(s), then mark the old Flow Entry for deletion, and mark
1018 // the new Flow Entry for addition.
1019 // - If a Flow Entry for a switch is in both the old and the new
1020 // data path, and it hasn't changed, then just keep it.
1021 //
1022 // NOTE: We use the Switch DPID of each entry to match the entries
1023 //
1024 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1025 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1026 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1027 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1028
1029 // Prepare maps with the Flow Entries, so they are fast to lookup
1030 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1031 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1032 for (FlowEntry flowEntry : newDataPath.flowEntries())
1033 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1034
1035 //
1036 // Find the old Flow Entries that should be deleted
1037 //
1038 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1039 FlowEntry newFlowEntry =
1040 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1041 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001042 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001043 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1044 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1045 deletedFlowEntries.add(oldFlowEntry);
1046 }
1047 }
1048
1049 //
1050 // Find the new Flow Entries that should be added or updated
1051 //
1052 int idx = 0;
1053 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1054 FlowEntry oldFlowEntry =
1055 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1056
1057 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001058 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1059 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001060 //
1061 // Both Flow Entries are same
1062 //
1063 finalFlowEntries.add(oldFlowEntry);
1064 idx++;
1065 continue;
1066 }
1067
1068 if (oldFlowEntry != null) {
1069 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001070 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001071 //
1072 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1073 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1074 deletedFlowEntries.add(oldFlowEntry);
1075 }
1076
1077 //
1078 // Add the new Flow Entry
1079 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001080 //
1081 // NOTE: Assign only the Flow ID.
1082 // The Flow Entry ID is assigned later only for the Flow Entries
1083 // this instance is responsible for.
1084 //
1085 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001086
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001087 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001088 // Copy the Flow timeouts
1089 //
1090 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1091 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1092
1093 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001094 // Allocate the FlowEntryMatch by copying the default one
1095 // from the FlowPath (if set).
1096 //
1097 FlowEntryMatch flowEntryMatch = null;
1098 if (flowPath.flowEntryMatch() != null)
1099 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1100 else
1101 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001102 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001103
1104 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001105 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1106
1107 //
1108 // Set the actions:
1109 // If the first Flow Entry, copy the Flow Path actions to it.
1110 //
1111 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1112 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1113 FlowEntryActions flowActions =
1114 new FlowEntryActions(flowPath.flowEntryActions());
1115 for (FlowEntryAction action : flowActions.actions())
1116 flowEntryActions.addAction(action);
1117 }
1118 idx++;
1119
1120 //
1121 // Add the outgoing port output action
1122 //
1123 FlowEntryAction flowEntryAction = new FlowEntryAction();
1124 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1125 flowEntryActions.addAction(flowEntryAction);
1126
1127 //
1128 // Set the state of the new Flow Entry
1129 //
1130 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1131 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1132 finalFlowEntries.add(newFlowEntry);
1133 }
1134
1135 //
1136 // Replace the old Flow Entries with the new Flow Entries.
1137 // Note that the Flow Entries that will be deleted are added at
1138 // the end.
1139 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001140 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001141 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1142
1143 return hasChanged;
1144 }
1145
1146 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001147 * Receive a notification that a Flow is added.
1148 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001149 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001150 */
1151 @Override
1152 public void notificationRecvFlowAdded(FlowPath flowPath) {
1153 EventEntry<FlowPath> eventEntry =
1154 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1155 networkEvents.add(eventEntry);
1156 }
1157
1158 /**
1159 * Receive a notification that a Flow is removed.
1160 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001161 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001162 */
1163 @Override
1164 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1165 EventEntry<FlowPath> eventEntry =
1166 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1167 networkEvents.add(eventEntry);
1168 }
1169
1170 /**
1171 * Receive a notification that a Flow is updated.
1172 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001173 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001174 */
1175 @Override
1176 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1177 // NOTE: The ADD and UPDATE events are processed in same way
1178 EventEntry<FlowPath> eventEntry =
1179 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1180 networkEvents.add(eventEntry);
1181 }
1182
1183 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001184 * Receive a notification that a FlowEntry is added.
1185 *
1186 * @param flowEntry the FlowEntry that is added.
1187 */
1188 @Override
1189 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
1190 EventEntry<FlowEntry> eventEntry =
1191 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1192 networkEvents.add(eventEntry);
1193 }
1194
1195 /**
1196 * Receive a notification that a FlowEntry is removed.
1197 *
1198 * @param flowEntry the FlowEntry that is removed.
1199 */
1200 @Override
1201 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
1202 EventEntry<FlowEntry> eventEntry =
1203 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1204 networkEvents.add(eventEntry);
1205 }
1206
1207 /**
1208 * Receive a notification that a FlowEntry is updated.
1209 *
1210 * @param flowEntry the FlowEntry that is updated.
1211 */
1212 @Override
1213 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
1214 // NOTE: The ADD and UPDATE events are processed in same way
1215 EventEntry<FlowEntry> eventEntry =
1216 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1217 networkEvents.add(eventEntry);
1218 }
1219
1220 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001221 * Receive a notification that a FlowId is added.
1222 *
1223 * @param flowId the FlowId that is added.
1224 */
1225 @Override
1226 public void notificationRecvFlowIdAdded(FlowId flowId) {
1227 EventEntry<FlowId> eventEntry =
1228 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1229 networkEvents.add(eventEntry);
1230 }
1231
1232 /**
1233 * Receive a notification that a FlowId is removed.
1234 *
1235 * @param flowId the FlowId that is removed.
1236 */
1237 @Override
1238 public void notificationRecvFlowIdRemoved(FlowId flowId) {
1239 EventEntry<FlowId> eventEntry =
1240 new EventEntry<FlowId>(EventEntry.Type.ENTRY_REMOVE, flowId);
1241 networkEvents.add(eventEntry);
1242 }
1243
1244 /**
1245 * Receive a notification that a FlowId is updated.
1246 *
1247 * @param flowId the FlowId that is updated.
1248 */
1249 @Override
1250 public void notificationRecvFlowIdUpdated(FlowId flowId) {
1251 // NOTE: The ADD and UPDATE events are processed in same way
1252 EventEntry<FlowId> eventEntry =
1253 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1254 networkEvents.add(eventEntry);
1255 }
1256
1257 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001258 * Receive a notification that a FlowEntryId is added.
1259 *
1260 * @param flowEntryId the FlowEntryId that is added.
1261 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1262 */
1263 @Override
1264 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1265 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001266 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1267
1268 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1269 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001270 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001271 }
1272
1273 /**
1274 * Receive a notification that a FlowEntryId is removed.
1275 *
1276 * @param flowEntryId the FlowEntryId that is removed.
1277 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1278 */
1279 @Override
1280 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1281 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001282 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1283
1284 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1285 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001286 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001287 }
1288
1289 /**
1290 * Receive a notification that a FlowEntryId is updated.
1291 *
1292 * @param flowEntryId the FlowEntryId that is updated.
1293 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1294 */
1295 @Override
1296 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1297 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001298 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1299
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001300 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001301 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1302 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001303 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001304 }
1305
1306 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001307 * Receive a notification that a Topology Element is added.
1308 *
1309 * @param topologyElement the Topology Element that is added.
1310 */
1311 @Override
1312 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1313 EventEntry<TopologyElement> eventEntry =
1314 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1315 networkEvents.add(eventEntry);
1316 }
1317
1318 /**
1319 * Receive a notification that a Topology Element is removed.
1320 *
1321 * @param topologyElement the Topology Element that is removed.
1322 */
1323 @Override
1324 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1325 EventEntry<TopologyElement> eventEntry =
1326 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1327 networkEvents.add(eventEntry);
1328 }
1329
1330 /**
1331 * Receive a notification that a Topology Element is updated.
1332 *
1333 * @param topologyElement the Topology Element that is updated.
1334 */
1335 @Override
1336 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1337 // NOTE: The ADD and UPDATE events are processed in same way
1338 EventEntry<TopologyElement> eventEntry =
1339 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1340 networkEvents.add(eventEntry);
1341 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001342
1343 /**
1344 * Get a sorted copy of all Flow Paths.
1345 *
1346 * @return a sorted copy of all Flow Paths.
1347 */
1348 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1349 SortedMap<Long, FlowPath> sortedFlowPaths =
1350 new TreeMap<Long, FlowPath>();
1351
1352 //
1353 // TODO: For now we use serialization/deserialization to create
1354 // a copy of each Flow Path. In the future, we should use proper
1355 // copy constructors.
1356 //
1357 Kryo kryo = kryoFactory.newKryo();
1358 synchronized (allFlowPaths) {
1359 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1360 FlowPath origFlowPath = entry.getValue();
1361 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1362 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1363 }
1364 }
1365 kryoFactory.deleteKryo(kryo);
1366
1367 return sortedFlowPaths;
1368 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001369}