blob: 83f973147c283fac97603965e0b3144af67f8a93 [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 Radoslavov1b454902014-01-09 16:28:27 -0800662 boolean isTopologyModified = false;
663
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800664 if (enableOnrc2014MeasurementsTopology) {
665 if (topologyEvents.isEmpty())
666 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800667
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800668 // TODO: Code for debugging purpose only
669 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
670 TopologyElement topologyElement = eventEntry.eventData();
671 log.debug("Topology Event: {} {}", eventEntry.eventType(),
672 topologyElement.toString());
673 }
674
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800675 log.debug("[BEFORE] {}", topology.toString());
676
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800677 //
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800678 // TODO: Fake the unconditional topology read by checking the cache
679 // with the old topology and ignoring topology events that don't
680 // make any impact to the topology.
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800681 // This is needed aa workaround: if a port is down, we get
682 // up to three additional "Port Down" or "Link Down" events.
683 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800684 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
685 TopologyElement topologyElement = eventEntry.eventData();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800686
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800687 switch (eventEntry.eventType()) {
688 case ENTRY_ADD:
689 isTopologyModified |= topology.addTopologyElement(topologyElement);
690 break;
691 case ENTRY_REMOVE:
692 isTopologyModified |= topology.removeTopologyElement(topologyElement);
693 break;
694 }
695 if (isTopologyModified)
696 break;
697 }
698 if (! isTopologyModified) {
699 log.debug("Ignoring topology events that don't modify the topology");
700 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800701 }
702
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800703 topology.readFromDatabase(dbHandler);
704 log.debug("[AFTER] {}", topology.toString());
705 shouldRecomputeFlowPaths.putAll(allFlowPaths);
706 return;
707 }
708
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700709 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800710 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700711 //
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800712 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
713 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800714
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800715 log.debug("Topology Event: {} {}", eventEntry.eventType(),
716 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800717
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800718 switch (eventEntry.eventType()) {
719 case ENTRY_ADD:
720 isTopologyModified |= topology.addTopologyElement(topologyElement);
721 break;
722 case ENTRY_REMOVE:
723 isTopologyModified |= topology.removeTopologyElement(topologyElement);
724 break;
725 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700726 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700727 if (isTopologyModified) {
728 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800729 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700730 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800731 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700732
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800733 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800734 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800735 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800736 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800737 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800738 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800739
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700740 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800741 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700742 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800743 if (! unmatchedFlowEntryAdd.isEmpty()) {
744 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
745 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800746 // log.debug("Processing Unmatched Flow Entry: {}",
747 // flowEntry.toString());
748
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800749 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800750 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800751 remainingUpdates.put(flowEntry.flowEntryId().value(),
752 flowEntry);
753 continue;
754 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800755 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
756 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800757 remainingUpdates.put(flowEntry.flowEntryId().value(),
758 flowEntry);
759 continue;
760 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800761 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
762 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
763 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700764 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800765 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700766 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800767 }
768
769 /**
770 * Process the Flow Entry events.
771 */
772 private void processFlowEntryEvents() {
773 FlowPath flowPath;
774 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700775
776 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800777 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700778 //
779 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
780 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800781
782 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800783 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800784
785 if ((! flowEntry.isValidFlowId()) ||
786 (! flowEntry.isValidFlowEntryId())) {
787 continue;
788 }
789
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700790 switch (eventEntry.eventType()) {
791 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800792 flowPath = allFlowPaths.get(flowEntry.flowId().value());
793 if (flowPath == null) {
794 // Flow Path not found: keep the entry for later matching
795 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
796 flowEntry);
797 break;
798 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800799 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
800 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800801 // Flow Entry not found: keep the entry for later matching
802 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
803 flowEntry);
804 break;
805 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800806 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
807 // Add the updated Flow Path to the list of updated paths
808 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
809 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700810 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800811
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700812 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800813 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
814 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800815 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800816 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800817
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800818 flowPath = allFlowPaths.get(flowEntry.flowId().value());
819 if (flowPath == null) {
820 // Flow Path not found: ignore the update
821 break;
822 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800823 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
824 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800825 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800826 break;
827 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800828 if (updateFlowEntryRemove(flowPath, localFlowEntry,
829 flowEntry)) {
830 // Add the updated Flow Path to the list of updated paths
831 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
832 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700833 break;
834 }
835 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700836 }
837
838 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800839 * Find a Flow Entry that should be updated because of an external
840 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700841 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800842 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800843 * @param newFlowEntry the FlowEntry with the new state.
844 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700845 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800846 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
847 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700848 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800849 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700850 //
851 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800852 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800853 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700854 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800855 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700856
857 //
858 // Local Flow Entry match found
859 //
860 if (localFlowEntry.isValidFlowEntryId()) {
861 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800862 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700863 //
864 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800865 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700866 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800867 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700868 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700869 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800870 return localFlowEntry;
871 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700872
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800873 return null; // Entry not found
874 }
875
876 /**
877 * Update a Flow Entry because of an external ENTRY_ADD event.
878 *
879 * @param flowPath the FlowPath for the Flow Entry to update.
880 * @param localFlowEntry the local Flow Entry to update.
881 * @param newFlowEntry the FlowEntry with the new state.
882 * @return true if the local Flow Entry was updated, otherwise false.
883 */
884 private boolean updateFlowEntryAdd(FlowPath flowPath,
885 FlowEntry localFlowEntry,
886 FlowEntry newFlowEntry) {
887 boolean updated = false;
888
889 if (localFlowEntry.flowEntryUserState() ==
890 FlowEntryUserState.FE_USER_DELETE) {
891 // Don't add-back a Flow Entry that is already deleted
892 return false;
893 }
894
895 if (! localFlowEntry.isValidFlowEntryId()) {
896 // Update the Flow Entry ID
897 FlowEntryId flowEntryId =
898 new FlowEntryId(newFlowEntry.flowEntryId().value());
899 localFlowEntry.setFlowEntryId(flowEntryId);
900 updated = true;
901 }
902
903 //
904 // Update the local Flow Entry, and keep state to check
905 // if the Flow Path has been installed.
906 //
907 if (localFlowEntry.flowEntryUserState() !=
908 newFlowEntry.flowEntryUserState()) {
909 localFlowEntry.setFlowEntryUserState(
910 newFlowEntry.flowEntryUserState());
911 updated = true;
912 }
913 if (localFlowEntry.flowEntrySwitchState() !=
914 newFlowEntry.flowEntrySwitchState()) {
915 localFlowEntry.setFlowEntrySwitchState(
916 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800917 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800918 updated = true;
919 }
920
921 return updated;
922 }
923
924 /**
925 * Find a Flow Entry that should be updated because of an external
926 * ENTRY_REMOVE event.
927 *
928 * @param flowPath the FlowPath for the Flow Entry to update.
929 * @param newFlowEntry the FlowEntry with the new state.
930 * @return the Flow Entry that should be updated if found, otherwise null.
931 */
932 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
933 FlowEntry newFlowEntry) {
934 //
935 // Iterate over all Flow Entries and find a match based on
936 // the Flow Entry ID.
937 //
938 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
939 if (! localFlowEntry.isValidFlowEntryId())
940 continue;
941 if (localFlowEntry.flowEntryId().value() !=
942 newFlowEntry.flowEntryId().value()) {
943 continue;
944 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800945 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700946 }
947
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800948 return null; // Entry not found
949 }
950
951 /**
952 * Update a Flow Entry because of an external ENTRY_REMOVE event.
953 *
954 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800955 * @param localFlowEntry the local Flow Entry to update.
956 * @param newFlowEntry the FlowEntry with the new state.
957 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800958 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800959 private boolean updateFlowEntryRemove(FlowPath flowPath,
960 FlowEntry localFlowEntry,
961 FlowEntry newFlowEntry) {
962 boolean updated = false;
963
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800964 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800965 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800966 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800967 if (localFlowEntry.flowEntryUserState() !=
968 newFlowEntry.flowEntryUserState()) {
969 localFlowEntry.setFlowEntryUserState(
970 newFlowEntry.flowEntryUserState());
971 updated = true;
972 }
973 if (localFlowEntry.flowEntrySwitchState() !=
974 newFlowEntry.flowEntrySwitchState()) {
975 localFlowEntry.setFlowEntrySwitchState(
976 newFlowEntry.flowEntrySwitchState());
977 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800978 }
979
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800980 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700981 }
982
983 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700984 * Recompute a Flow Path.
985 *
986 * @param flowPath the Flow Path to recompute.
987 * @return true if the recomputed Flow Path has changed, otherwise false.
988 */
989 private boolean recomputeFlowPath(FlowPath flowPath) {
990 boolean hasChanged = false;
991
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -0800992 if (enableOnrc2014MeasurementsFlows) {
993 // Cleanup the deleted Flow Entries from the earlier iteration
994 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800995
996 //
997 // TODO: Fake it that the Flow Entries have been already pushed
998 // into the switches, so we don't push them again.
999 //
1000 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1001 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1002 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001003 }
1004
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001005 //
1006 // Test whether the Flow Path needs to be recomputed
1007 //
1008 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001009 case FP_TYPE_UNKNOWN:
1010 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001011 case FP_TYPE_SHORTEST_PATH:
1012 break;
1013 case FP_TYPE_EXPLICIT_PATH:
1014 return false; // An explicit path never changes
1015 }
1016
1017 DataPath oldDataPath = flowPath.dataPath();
1018
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001019 // Compute the new path
1020 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
1021 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001022 if (newDataPath == null) {
1023 // We need the DataPath to compare the paths
1024 newDataPath = new DataPath();
1025 }
1026 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1027
1028 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001029 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001030 //
1031 if (oldDataPath.flowEntries().size() !=
1032 newDataPath.flowEntries().size()) {
1033 hasChanged = true;
1034 } else {
1035 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1036 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1037 while (oldIter.hasNext() && newIter.hasNext()) {
1038 FlowEntry oldFlowEntry = oldIter.next();
1039 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001040 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1041 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001042 hasChanged = true;
1043 break;
1044 }
1045 }
1046 }
1047 if (! hasChanged)
1048 return hasChanged;
1049
1050 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001051 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001052 // - If a Flow Entry for a switch is in the old data path, but not
1053 // in the new data path, then mark it for deletion.
1054 // - If a Flow Entry for a switch is in the new data path, but not
1055 // in the old data path, then mark it for addition.
1056 // - If a Flow Entry for a switch is in both the old and the new
1057 // data path, but it has changed, e.g., the incoming and/or outgoing
1058 // port(s), then mark the old Flow Entry for deletion, and mark
1059 // the new Flow Entry for addition.
1060 // - If a Flow Entry for a switch is in both the old and the new
1061 // data path, and it hasn't changed, then just keep it.
1062 //
1063 // NOTE: We use the Switch DPID of each entry to match the entries
1064 //
1065 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1066 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1067 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1068 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1069
1070 // Prepare maps with the Flow Entries, so they are fast to lookup
1071 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1072 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1073 for (FlowEntry flowEntry : newDataPath.flowEntries())
1074 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1075
1076 //
1077 // Find the old Flow Entries that should be deleted
1078 //
1079 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1080 FlowEntry newFlowEntry =
1081 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1082 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001083 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001084 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1085 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1086 deletedFlowEntries.add(oldFlowEntry);
1087 }
1088 }
1089
1090 //
1091 // Find the new Flow Entries that should be added or updated
1092 //
1093 int idx = 0;
1094 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1095 FlowEntry oldFlowEntry =
1096 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1097
1098 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001099 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1100 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001101 //
1102 // Both Flow Entries are same
1103 //
1104 finalFlowEntries.add(oldFlowEntry);
1105 idx++;
1106 continue;
1107 }
1108
1109 if (oldFlowEntry != null) {
1110 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001111 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001112 //
1113 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1114 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1115 deletedFlowEntries.add(oldFlowEntry);
1116 }
1117
1118 //
1119 // Add the new Flow Entry
1120 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001121 //
1122 // NOTE: Assign only the Flow ID.
1123 // The Flow Entry ID is assigned later only for the Flow Entries
1124 // this instance is responsible for.
1125 //
1126 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001127
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001128 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001129 // Copy the Flow timeouts
1130 //
1131 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1132 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1133
1134 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001135 // Allocate the FlowEntryMatch by copying the default one
1136 // from the FlowPath (if set).
1137 //
1138 FlowEntryMatch flowEntryMatch = null;
1139 if (flowPath.flowEntryMatch() != null)
1140 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1141 else
1142 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001143 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001144
1145 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001146 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1147
1148 //
1149 // Set the actions:
1150 // If the first Flow Entry, copy the Flow Path actions to it.
1151 //
1152 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1153 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1154 FlowEntryActions flowActions =
1155 new FlowEntryActions(flowPath.flowEntryActions());
1156 for (FlowEntryAction action : flowActions.actions())
1157 flowEntryActions.addAction(action);
1158 }
1159 idx++;
1160
1161 //
1162 // Add the outgoing port output action
1163 //
1164 FlowEntryAction flowEntryAction = new FlowEntryAction();
1165 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1166 flowEntryActions.addAction(flowEntryAction);
1167
1168 //
1169 // Set the state of the new Flow Entry
1170 //
1171 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1172 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1173 finalFlowEntries.add(newFlowEntry);
1174 }
1175
1176 //
1177 // Replace the old Flow Entries with the new Flow Entries.
1178 // Note that the Flow Entries that will be deleted are added at
1179 // the end.
1180 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001181 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001182 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1183
1184 return hasChanged;
1185 }
1186
1187 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001188 * Receive a notification that a Flow is added.
1189 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001190 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001191 */
1192 @Override
1193 public void notificationRecvFlowAdded(FlowPath flowPath) {
1194 EventEntry<FlowPath> eventEntry =
1195 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1196 networkEvents.add(eventEntry);
1197 }
1198
1199 /**
1200 * Receive a notification that a Flow is removed.
1201 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001202 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001203 */
1204 @Override
1205 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1206 EventEntry<FlowPath> eventEntry =
1207 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1208 networkEvents.add(eventEntry);
1209 }
1210
1211 /**
1212 * Receive a notification that a Flow is updated.
1213 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001214 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001215 */
1216 @Override
1217 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1218 // NOTE: The ADD and UPDATE events are processed in same way
1219 EventEntry<FlowPath> eventEntry =
1220 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1221 networkEvents.add(eventEntry);
1222 }
1223
1224 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001225 * Receive a notification that a FlowEntry is added.
1226 *
1227 * @param flowEntry the FlowEntry that is added.
1228 */
1229 @Override
1230 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
1231 EventEntry<FlowEntry> eventEntry =
1232 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1233 networkEvents.add(eventEntry);
1234 }
1235
1236 /**
1237 * Receive a notification that a FlowEntry is removed.
1238 *
1239 * @param flowEntry the FlowEntry that is removed.
1240 */
1241 @Override
1242 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
1243 EventEntry<FlowEntry> eventEntry =
1244 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1245 networkEvents.add(eventEntry);
1246 }
1247
1248 /**
1249 * Receive a notification that a FlowEntry is updated.
1250 *
1251 * @param flowEntry the FlowEntry that is updated.
1252 */
1253 @Override
1254 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
1255 // NOTE: The ADD and UPDATE events are processed in same way
1256 EventEntry<FlowEntry> eventEntry =
1257 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1258 networkEvents.add(eventEntry);
1259 }
1260
1261 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001262 * Receive a notification that a FlowId is added.
1263 *
1264 * @param flowId the FlowId that is added.
1265 */
1266 @Override
1267 public void notificationRecvFlowIdAdded(FlowId flowId) {
1268 EventEntry<FlowId> eventEntry =
1269 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1270 networkEvents.add(eventEntry);
1271 }
1272
1273 /**
1274 * Receive a notification that a FlowId is removed.
1275 *
1276 * @param flowId the FlowId that is removed.
1277 */
1278 @Override
1279 public void notificationRecvFlowIdRemoved(FlowId flowId) {
1280 EventEntry<FlowId> eventEntry =
1281 new EventEntry<FlowId>(EventEntry.Type.ENTRY_REMOVE, flowId);
1282 networkEvents.add(eventEntry);
1283 }
1284
1285 /**
1286 * Receive a notification that a FlowId is updated.
1287 *
1288 * @param flowId the FlowId that is updated.
1289 */
1290 @Override
1291 public void notificationRecvFlowIdUpdated(FlowId flowId) {
1292 // NOTE: The ADD and UPDATE events are processed in same way
1293 EventEntry<FlowId> eventEntry =
1294 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1295 networkEvents.add(eventEntry);
1296 }
1297
1298 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001299 * Receive a notification that a FlowEntryId is added.
1300 *
1301 * @param flowEntryId the FlowEntryId that is added.
1302 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1303 */
1304 @Override
1305 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1306 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001307 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1308
1309 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1310 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001311 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001312 }
1313
1314 /**
1315 * Receive a notification that a FlowEntryId is removed.
1316 *
1317 * @param flowEntryId the FlowEntryId that is removed.
1318 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1319 */
1320 @Override
1321 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1322 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001323 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1324
1325 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1326 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001327 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001328 }
1329
1330 /**
1331 * Receive a notification that a FlowEntryId is updated.
1332 *
1333 * @param flowEntryId the FlowEntryId that is updated.
1334 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1335 */
1336 @Override
1337 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1338 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001339 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1340
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001341 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001342 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1343 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001344 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001345 }
1346
1347 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001348 * Receive a notification that a Topology Element is added.
1349 *
1350 * @param topologyElement the Topology Element that is added.
1351 */
1352 @Override
1353 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1354 EventEntry<TopologyElement> eventEntry =
1355 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1356 networkEvents.add(eventEntry);
1357 }
1358
1359 /**
1360 * Receive a notification that a Topology Element is removed.
1361 *
1362 * @param topologyElement the Topology Element that is removed.
1363 */
1364 @Override
1365 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1366 EventEntry<TopologyElement> eventEntry =
1367 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1368 networkEvents.add(eventEntry);
1369 }
1370
1371 /**
1372 * Receive a notification that a Topology Element is updated.
1373 *
1374 * @param topologyElement the Topology Element that is updated.
1375 */
1376 @Override
1377 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1378 // NOTE: The ADD and UPDATE events are processed in same way
1379 EventEntry<TopologyElement> eventEntry =
1380 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1381 networkEvents.add(eventEntry);
1382 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001383
1384 /**
1385 * Get a sorted copy of all Flow Paths.
1386 *
1387 * @return a sorted copy of all Flow Paths.
1388 */
1389 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1390 SortedMap<Long, FlowPath> sortedFlowPaths =
1391 new TreeMap<Long, FlowPath>();
1392
1393 //
1394 // TODO: For now we use serialization/deserialization to create
1395 // a copy of each Flow Path. In the future, we should use proper
1396 // copy constructors.
1397 //
1398 Kryo kryo = kryoFactory.newKryo();
1399 synchronized (allFlowPaths) {
1400 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1401 FlowPath origFlowPath = entry.getValue();
1402 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1403 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1404 }
1405 }
1406 kryoFactory.deleteKryo(kryo);
1407
1408 return sortedFlowPaths;
1409 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001410}