blob: d1284a282670256d4265aede2cf0e5e12ab5f989 [file] [log] [blame]
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07003import java.util.ArrayList;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07004import java.util.Collection;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07005import java.util.HashMap;
6import java.util.Iterator;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07007import java.util.LinkedList;
8import java.util.List;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07009import java.util.Map;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080010import java.util.SortedMap;
11import java.util.TreeMap;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070012import java.util.concurrent.BlockingQueue;
13import java.util.concurrent.LinkedBlockingQueue;
14
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080015import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070016import net.onrc.onos.datagrid.IDatagridService;
Naoki Shiota0abe38d2014-01-07 15:31:22 -080017import net.onrc.onos.graph.GraphDBOperation;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070018import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070019import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070020import net.onrc.onos.ofcontroller.topology.TopologyManager;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070021import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080022import net.onrc.onos.ofcontroller.util.Dpid;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070023import net.onrc.onos.ofcontroller.util.EventEntry;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070024import net.onrc.onos.ofcontroller.util.FlowEntry;
25import net.onrc.onos.ofcontroller.util.FlowEntryAction;
26import net.onrc.onos.ofcontroller.util.FlowEntryActions;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070027import net.onrc.onos.ofcontroller.util.FlowEntryId;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070028import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
29import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
30import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070031import net.onrc.onos.ofcontroller.util.FlowId;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070032import net.onrc.onos.ofcontroller.util.FlowPath;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070033import net.onrc.onos.ofcontroller.util.FlowPathUserState;
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080034import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080035import net.onrc.onos.ofcontroller.util.Port;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080036import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
37
38import com.esotericsoftware.kryo2.Kryo;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070039
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070044 * Class for FlowPath Maintenance.
45 * This class listens for FlowEvents to:
46 * - Maintain a local cache of the Network Topology.
47 * - Detect FlowPaths impacted by Topology change.
48 * - Recompute impacted FlowPath using cached Topology.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070049 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070050class FlowEventHandler extends Thread implements IFlowEventHandlerService {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080051
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -080052 private boolean enableOnrc2014MeasurementsFlows = true;
53 private boolean enableOnrc2014MeasurementsTopology = true;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080054
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070055 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070056 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
Naoki Shiota0abe38d2014-01-07 15:31:22 -080057
Naoki Shiota0abe38d2014-01-07 15:31:22 -080058 private GraphDBOperation dbHandler;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070059 private FlowManager flowManager; // The Flow Manager to use
60 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070061 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080062 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070063
64 // The queue with Flow Path and Topology Element updates
65 private BlockingQueue<EventEntry<?>> networkEvents =
66 new LinkedBlockingQueue<EventEntry<?>>();
67
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070068 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070069 private List<EventEntry<TopologyElement>> topologyEvents =
70 new LinkedList<EventEntry<TopologyElement>>();
71 private List<EventEntry<FlowPath>> flowPathEvents =
72 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070073 private List<EventEntry<FlowEntry>> flowEntryEvents =
74 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -080075 private List<EventEntry<FlowId>> flowIdEvents =
76 new LinkedList<EventEntry<FlowId>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080077 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
78 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070079
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080080 // All internally computed Flow Paths
81 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
82
83 // The Flow Entries received as notifications with unmatched Flow Paths
84 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
85 new HashMap<Long, FlowEntry>();
86
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080087 //
88 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080089 // - The Flow Paths that should be recomputed
90 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080091 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080092 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080093 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
94 new HashMap<Long, FlowPath>();
95 private Map<Long, FlowPath> modifiedFlowPaths =
96 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080097 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
98 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080099
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700100 /**
101 * Constructor for a given Flow Manager and Datagrid Service.
102 *
103 * @param flowManager the Flow Manager to use.
104 * @param datagridService the Datagrid Service to use.
105 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700106 FlowEventHandler(FlowManager flowManager,
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800107 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700108 this.flowManager = flowManager;
109 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700110 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700111 }
112
113 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800114 * Get the network topology.
115 *
116 * @return the network topology.
117 */
118 protected Topology getTopology() { return this.topology; }
119
120 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800121 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700122 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800123 private void startup() {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800124 this.dbHandler = new GraphDBOperation("");
125
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700126 //
127 // Obtain the initial Topology state
128 //
129 Collection<TopologyElement> topologyElements =
130 datagridService.getAllTopologyElements();
131 for (TopologyElement topologyElement : topologyElements) {
132 EventEntry<TopologyElement> eventEntry =
133 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
134 topologyEvents.add(eventEntry);
135 }
136 //
137 // Obtain the initial Flow Path state
138 //
139 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
140 for (FlowPath flowPath : flowPaths) {
141 EventEntry<FlowPath> eventEntry =
142 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
143 flowPathEvents.add(eventEntry);
144 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700145 //
146 // Obtain the initial FlowEntry state
147 //
148 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
149 for (FlowEntry flowEntry : flowEntries) {
150 EventEntry<FlowEntry> eventEntry =
151 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
152 flowEntryEvents.add(eventEntry);
153 }
154
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800155 //
156 // Obtain the initial FlowId state
157 //
158 Collection<FlowId> flowIds = datagridService.getAllFlowIds();
159 for (FlowId flowId : flowIds) {
160 EventEntry<FlowId> eventEntry =
161 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
162 flowIdEvents.add(eventEntry);
163 }
164
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800165 //
166 // Obtain the initial FlowEntryId state
167 //
168 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
169 datagridService.getAllFlowEntryIds();
170 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
171 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
172 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
173 flowEntryIdEvents.add(eventEntry);
174 }
175
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800176 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800177 synchronized (allFlowPaths) {
178 processEvents();
179 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800180 }
181
182 /**
183 * Run the thread.
184 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800185 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800186 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800187 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800188 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700189
190 //
191 // The main loop
192 //
193 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
194 try {
195 while (true) {
196 EventEntry<?> eventEntry = networkEvents.take();
197 collection.add(eventEntry);
198 networkEvents.drainTo(collection);
199
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700200 //
201 // Demultiplex all events:
202 // - EventEntry<TopologyElement>
203 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700204 // - EventEntry<FlowEntry>
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800205 // - EventEntry<FlowId>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800206 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700207 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700208 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800209 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700210 if (event.eventData() instanceof TopologyElement) {
211 EventEntry<TopologyElement> topologyEventEntry =
212 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800213
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700214 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800215 continue;
216 }
217
218 // FlowPath event
219 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700220 EventEntry<FlowPath> flowPathEventEntry =
221 (EventEntry<FlowPath>)event;
222 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800223 continue;
224 }
225
226 // FlowEntry event
227 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700228 EventEntry<FlowEntry> flowEntryEventEntry =
229 (EventEntry<FlowEntry>)event;
230 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800231 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700232 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800233
234 // FlowId event
235 if (event.eventData() instanceof FlowId) {
236 EventEntry<FlowId> flowIdEventEntry =
237 (EventEntry<FlowId>)event;
238 flowIdEvents.add(flowIdEventEntry);
239 continue;
240 }
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800241 // FlowEntryId event
242 if (event.eventData() instanceof Pair) {
243 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
244 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
245 flowEntryIdEvents.add(flowEntryIdEventEntry);
246 continue;
247 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700248 }
249 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700250
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700251 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800252 synchronized (allFlowPaths) {
253 processEvents();
254 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700255 }
256 } catch (Exception exception) {
257 log.debug("Exception processing Network Events: ", exception);
258 }
259 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800260
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700261 /**
262 * Process the events (if any)
263 */
264 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800265 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700266
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800267 if (enableOnrc2014MeasurementsFlows) {
268
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800269 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
270 flowEntryIdEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800271 return; // Nothing to do
272 }
273
274 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
275
276 // Fetch and prepare my flows
277 prepareMyFlows(mySwitches);
278
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800279 // Process the Flow ID events
280 processFlowIdEvents(mySwitches);
281
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800282 // Fetch the topology
283 processTopologyEvents();
284
285 // Recompute all affected Flow Paths and keep only the modified
286 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
287 if (recomputeFlowPath(flowPath))
288 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
289 }
290
291 // Assign the Flow Entry ID as needed
292 for (FlowPath flowPath : modifiedFlowPaths.values()) {
293 for (FlowEntry flowEntry : flowPath.flowEntries()) {
294 if (! flowEntry.isValidFlowEntryId()) {
295 long id = flowManager.getNextFlowEntryId();
296 flowEntry.setFlowEntryId(new FlowEntryId(id));
297 }
298 }
299 }
300
301 // Extract my modified Flow Entries
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800302 modifiedFlowEntries = processFlowEntryIdEvents(mySwitches);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800303
304 //
305 // Push the modified state to the Flow Manager
306 //
307 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
308 modifiedFlowEntries);
309
310 // Cleanup
311 topologyEvents.clear();
312 flowIdEvents.clear();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800313 flowEntryIdEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800314 //
315 allFlowPaths.clear();
316 shouldRecomputeFlowPaths.clear();
317 modifiedFlowPaths.clear();
318
319 return;
320 }
321
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700322 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800323 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700324 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700325 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700326
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800327 processFlowPathEvents();
328 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800329 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800330 processFlowEntryEvents();
331
332 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800333 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800334 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800335 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800336 }
337
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800338 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800339 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800340
341 // Assign missing Flow Entry IDs
342 assignFlowEntryId(modifiedFlowEntries);
343
344 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800345 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800346 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800347 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
348 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800349
350 //
351 // Remove Flow Entries that were deleted
352 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800353 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800354 flowPath.dataPath().removeDeletedFlowEntries();
355
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800356 //
357 // Check if Flow Paths have been installed into all switches,
358 // and generate the appropriate events.
359 //
360 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
361
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800362 // Cleanup
363 topologyEvents.clear();
364 flowPathEvents.clear();
365 flowEntryEvents.clear();
366 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800367 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800368 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800369 checkIfInstalledFlowPaths.clear();
370 }
371
372 /**
373 * Check if Flow Paths have been installed into all switches,
374 * and generate the appropriate events.
375 *
376 * @param flowPaths the flowPaths to process.
377 */
378 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
379 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
380
381 Kryo kryo = kryoFactory.newKryo();
382
383 for (FlowPath flowPath : flowPaths) {
384 boolean isInstalled = true;
385
386 //
387 // Check whether all Flow Entries have been installed
388 //
389 for (FlowEntry flowEntry : flowPath.flowEntries()) {
390 if (flowEntry.flowEntrySwitchState() !=
391 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
392 isInstalled = false;
393 break;
394 }
395 }
396
397 if (isInstalled) {
398 // Create a copy and add it to the list
399 FlowPath copyFlowPath = kryo.copy(flowPath);
400 installedFlowPaths.add(copyFlowPath);
401 }
402 }
403 kryoFactory.deleteKryo(kryo);
404
405 // Generate an event for the installed Flow Path.
406 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800407 }
408
409 /**
410 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800411 *
412 * @param modifiedFlowPaths the Flow Paths to process.
413 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800414 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800415 private Collection<FlowEntry> extractModifiedFlowEntries(
416 Collection<FlowPath> modifiedFlowPaths) {
417 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800418
419 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800420 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800421 for (FlowEntry flowEntry : flowPath.flowEntries()) {
422 if (flowEntry.flowEntrySwitchState() ==
423 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800424 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800425 }
426 }
427 }
428 return modifiedFlowEntries;
429 }
430
431 /**
432 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800433 *
434 * @param modifiedFlowEnries the collection of Flow Entries that need
435 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800436 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800437 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800438 if (modifiedFlowEntries.isEmpty())
439 return;
440
441 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
442
443 //
444 // Assign the Flow Entry ID only for Flow Entries for my switches
445 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800446 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800447 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
448 if (mySwitch == null)
449 continue;
450 if (! flowEntry.isValidFlowEntryId()) {
451 long id = flowManager.getNextFlowEntryId();
452 flowEntry.setFlowEntryId(new FlowEntryId(id));
453 }
454 }
455 }
456
457 /**
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800458 * Prepare my flows.
459 *
460 * @param mySwitches the collection of my switches.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800461 */
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800462 private void prepareMyFlows(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800463 if (! topologyEvents.isEmpty()) {
464 // Fetch my flows from the database
465 ArrayList<FlowPath> myFlows = FlowDatabaseOperation.getAllMyFlows(dbHandler, mySwitches);
466 for (FlowPath flowPath : myFlows) {
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800467 log.debug("Found my flow: {}", flowPath);
468
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800469 allFlowPaths.put(flowPath.flowId().value(), flowPath);
470
471 //
472 // TODO: Bug workaround / fix :
473 // method FlowDatabaseOperation.extractFlowEntry() doesn't
474 // fetch the inPort and outPort, hence we assign them here.
475 //
476 // Assign the inPort and outPort for the Flow Entries
477 for (FlowEntry flowEntry : flowPath.flowEntries()) {
478 // Set the inPort
479 do {
480 if (flowEntry.inPort() != null)
481 break;
482 if (flowEntry.flowEntryMatch() == null)
483 break;
484 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
485 flowEntry.setInPort(inPort);
486 } while (false);
487
488 // Set the outPort
489 do {
490 if (flowEntry.outPort() != null)
491 break;
492 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
493 if (fa.actionOutput() != null) {
494 Port outPort = new Port(fa.actionOutput().port().value());
495 flowEntry.setOutPort(outPort);
496 break;
497 }
498 }
499 } while (false);
500 }
501 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800502 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800503 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800504
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800505 /**
506 * Process the Flow ID events.
507 *
508 * @param mySwitches the collection of my switches.
509 */
510 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800511 //
512 // Automatically add all Flow ID events (for the Flows this instance
513 // is responsible for) to the collection of Flows to recompute.
514 //
515 for (EventEntry<FlowId> eventEntry : flowIdEvents) {
516 FlowId flowId = eventEntry.eventData();
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800517
518 log.debug("Flow ID Event: {} {}", eventEntry.eventType(), flowId);
519
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800520 FlowPath flowPath = allFlowPaths.get(flowId.value());
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800521 if (flowPath == null) {
522 if (! topologyEvents.isEmpty())
523 continue; // Optimization: Not my flow
524 Dpid dpid = FlowDatabaseOperation.getFlowSourceDpid(dbHandler,
525 flowId);
526 if ((dpid != null) && (mySwitches.get(dpid.value()) != null)) {
527 flowPath = FlowDatabaseOperation.getFlow(dbHandler,
528 flowId);
529 }
530 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800531 if (flowPath != null) {
532 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
533 flowPath);
534 }
535 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800536 }
537
538 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800539 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800540 *
541 * @param mySwitches the collection of my switches.
542 * @return a collection of modified Flow Entries this instance needs
543 * to push to its own switches.
544 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800545 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800546 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
547
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800548 //
549 // Process all Flow ID events and update the appropriate state
550 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800551 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
552 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
553 FlowEntryId flowEntryId = pair.first;
554 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800555
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800556 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
557 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800558
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800559 if (mySwitches.get(dpid.value()) == null)
560 continue;
561
562 // Fetch the Flow Entry
563 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
564 flowEntryId);
565 if (flowEntry == null) {
566 log.debug("Flow Entry ID {} : Flow Entry not found!",
567 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800568 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800569 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800570 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800571 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800572
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800573 return modifiedFlowEntries;
574 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800575
576 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800577 * Process the Flow Path events.
578 */
579 private void processFlowPathEvents() {
580 //
581 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700582 //
583 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
584 FlowPath flowPath = eventEntry.eventData();
585
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800586 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800587
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700588 switch (eventEntry.eventType()) {
589 case ENTRY_ADD: {
590 //
591 // Add a new Flow Path
592 //
593 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
594 //
595 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800596 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700597 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700598 }
599
600 switch (flowPath.flowPathType()) {
601 case FP_TYPE_SHORTEST_PATH:
602 //
603 // Reset the Data Path, in case it was set already, because
604 // we are going to recompute it anyway.
605 //
606 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800607 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
608 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700609 break;
610 case FP_TYPE_EXPLICIT_PATH:
611 //
612 // Mark all Flow Entries for installation in the switches.
613 //
614 for (FlowEntry flowEntry : flowPath.flowEntries()) {
615 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
616 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800617 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700618 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800619 case FP_TYPE_UNKNOWN:
620 log.error("FlowPath event with unknown type");
621 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700622 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800623 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700624
625 break;
626 }
627
628 case ENTRY_REMOVE: {
629 //
630 // Remove an existing Flow Path.
631 //
632 // Find the Flow Path, and mark the Flow and its Flow Entries
633 // for deletion.
634 //
635 FlowPath existingFlowPath =
636 allFlowPaths.get(flowPath.flowId().value());
637 if (existingFlowPath == null)
638 continue; // Nothing to do
639
640 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
641 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
642 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
643 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
644 }
645
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800646 // Remove the Flow Path from the internal state
647 Long key = existingFlowPath.flowId().value();
648 allFlowPaths.remove(key);
649 shouldRecomputeFlowPaths.remove(key);
650 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700651
652 break;
653 }
654 }
655 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800656 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700657
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800658 /**
659 * Process the Topology events.
660 */
661 private void processTopologyEvents() {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800662 if (enableOnrc2014MeasurementsTopology) {
663 if (topologyEvents.isEmpty())
664 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800665
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800666 // 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 Radoslavov737aa522014-01-09 15:35:00 -0800673 //
674 // TODO: Fake the topology read it by checking the cache with
675 // the old topology and ignoring topology events that don't make
676 // any impact to the topology.
677 // This is needed aa workaround: if a port is down, we get
678 // up to three additional "Port Down" or "Link Down" events.
679 //
680 boolean isTopologyModified = false;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800681 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
682 TopologyElement topologyElement = eventEntry.eventData();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800683
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800684 switch (eventEntry.eventType()) {
685 case ENTRY_ADD:
686 isTopologyModified |= topology.addTopologyElement(topologyElement);
687 break;
688 case ENTRY_REMOVE:
689 isTopologyModified |= topology.removeTopologyElement(topologyElement);
690 break;
691 }
692 if (isTopologyModified)
693 break;
694 }
695 if (! isTopologyModified) {
696 log.debug("Ignoring topology events that don't modify the topology");
697 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800698 }
699
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800700 log.debug("[BEFORE] {}", topology.toString());
701 topology.readFromDatabase(dbHandler);
702 log.debug("[AFTER] {}", topology.toString());
703 shouldRecomputeFlowPaths.putAll(allFlowPaths);
704 return;
705 }
706
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700707 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800708 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700709 //
710 boolean isTopologyModified = false;
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800711 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
712 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800713
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800714 log.debug("Topology Event: {} {}", eventEntry.eventType(),
715 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800716
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800717 switch (eventEntry.eventType()) {
718 case ENTRY_ADD:
719 isTopologyModified |= topology.addTopologyElement(topologyElement);
720 break;
721 case ENTRY_REMOVE:
722 isTopologyModified |= topology.removeTopologyElement(topologyElement);
723 break;
724 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700725 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700726 if (isTopologyModified) {
727 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800728 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700729 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800730 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700731
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800732 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800733 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800734 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800735 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800736 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800737 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800738
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700739 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800740 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700741 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800742 if (! unmatchedFlowEntryAdd.isEmpty()) {
743 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
744 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800745 // log.debug("Processing Unmatched Flow Entry: {}",
746 // flowEntry.toString());
747
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800748 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800749 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800750 remainingUpdates.put(flowEntry.flowEntryId().value(),
751 flowEntry);
752 continue;
753 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800754 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
755 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800756 remainingUpdates.put(flowEntry.flowEntryId().value(),
757 flowEntry);
758 continue;
759 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800760 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
761 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
762 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700763 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800764 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700765 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800766 }
767
768 /**
769 * Process the Flow Entry events.
770 */
771 private void processFlowEntryEvents() {
772 FlowPath flowPath;
773 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700774
775 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800776 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700777 //
778 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
779 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800780
781 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800782 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800783
784 if ((! flowEntry.isValidFlowId()) ||
785 (! flowEntry.isValidFlowEntryId())) {
786 continue;
787 }
788
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700789 switch (eventEntry.eventType()) {
790 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800791 flowPath = allFlowPaths.get(flowEntry.flowId().value());
792 if (flowPath == null) {
793 // Flow Path not found: keep the entry for later matching
794 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
795 flowEntry);
796 break;
797 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800798 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
799 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800800 // Flow Entry not found: keep the entry for later matching
801 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
802 flowEntry);
803 break;
804 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800805 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
806 // Add the updated Flow Path to the list of updated paths
807 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
808 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700809 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800810
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700811 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800812 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
813 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800814 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800815 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800816
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800817 flowPath = allFlowPaths.get(flowEntry.flowId().value());
818 if (flowPath == null) {
819 // Flow Path not found: ignore the update
820 break;
821 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800822 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
823 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800824 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800825 break;
826 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800827 if (updateFlowEntryRemove(flowPath, localFlowEntry,
828 flowEntry)) {
829 // Add the updated Flow Path to the list of updated paths
830 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
831 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700832 break;
833 }
834 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700835 }
836
837 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800838 * Find a Flow Entry that should be updated because of an external
839 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700840 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800841 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800842 * @param newFlowEntry the FlowEntry with the new state.
843 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700844 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800845 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
846 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700847 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800848 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700849 //
850 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800851 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800852 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700853 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800854 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700855
856 //
857 // Local Flow Entry match found
858 //
859 if (localFlowEntry.isValidFlowEntryId()) {
860 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800861 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700862 //
863 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800864 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700865 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800866 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700867 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700868 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800869 return localFlowEntry;
870 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700871
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800872 return null; // Entry not found
873 }
874
875 /**
876 * Update a Flow Entry because of an external ENTRY_ADD event.
877 *
878 * @param flowPath the FlowPath for the Flow Entry to update.
879 * @param localFlowEntry the local Flow Entry to update.
880 * @param newFlowEntry the FlowEntry with the new state.
881 * @return true if the local Flow Entry was updated, otherwise false.
882 */
883 private boolean updateFlowEntryAdd(FlowPath flowPath,
884 FlowEntry localFlowEntry,
885 FlowEntry newFlowEntry) {
886 boolean updated = false;
887
888 if (localFlowEntry.flowEntryUserState() ==
889 FlowEntryUserState.FE_USER_DELETE) {
890 // Don't add-back a Flow Entry that is already deleted
891 return false;
892 }
893
894 if (! localFlowEntry.isValidFlowEntryId()) {
895 // Update the Flow Entry ID
896 FlowEntryId flowEntryId =
897 new FlowEntryId(newFlowEntry.flowEntryId().value());
898 localFlowEntry.setFlowEntryId(flowEntryId);
899 updated = true;
900 }
901
902 //
903 // Update the local Flow Entry, and keep state to check
904 // if the Flow Path has been installed.
905 //
906 if (localFlowEntry.flowEntryUserState() !=
907 newFlowEntry.flowEntryUserState()) {
908 localFlowEntry.setFlowEntryUserState(
909 newFlowEntry.flowEntryUserState());
910 updated = true;
911 }
912 if (localFlowEntry.flowEntrySwitchState() !=
913 newFlowEntry.flowEntrySwitchState()) {
914 localFlowEntry.setFlowEntrySwitchState(
915 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800916 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800917 updated = true;
918 }
919
920 return updated;
921 }
922
923 /**
924 * Find a Flow Entry that should be updated because of an external
925 * ENTRY_REMOVE event.
926 *
927 * @param flowPath the FlowPath for the Flow Entry to update.
928 * @param newFlowEntry the FlowEntry with the new state.
929 * @return the Flow Entry that should be updated if found, otherwise null.
930 */
931 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
932 FlowEntry newFlowEntry) {
933 //
934 // Iterate over all Flow Entries and find a match based on
935 // the Flow Entry ID.
936 //
937 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
938 if (! localFlowEntry.isValidFlowEntryId())
939 continue;
940 if (localFlowEntry.flowEntryId().value() !=
941 newFlowEntry.flowEntryId().value()) {
942 continue;
943 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800944 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700945 }
946
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800947 return null; // Entry not found
948 }
949
950 /**
951 * Update a Flow Entry because of an external ENTRY_REMOVE event.
952 *
953 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800954 * @param localFlowEntry the local Flow Entry to update.
955 * @param newFlowEntry the FlowEntry with the new state.
956 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800957 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800958 private boolean updateFlowEntryRemove(FlowPath flowPath,
959 FlowEntry localFlowEntry,
960 FlowEntry newFlowEntry) {
961 boolean updated = false;
962
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800963 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800964 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800965 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800966 if (localFlowEntry.flowEntryUserState() !=
967 newFlowEntry.flowEntryUserState()) {
968 localFlowEntry.setFlowEntryUserState(
969 newFlowEntry.flowEntryUserState());
970 updated = true;
971 }
972 if (localFlowEntry.flowEntrySwitchState() !=
973 newFlowEntry.flowEntrySwitchState()) {
974 localFlowEntry.setFlowEntrySwitchState(
975 newFlowEntry.flowEntrySwitchState());
976 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800977 }
978
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800979 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700980 }
981
982 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700983 * Recompute a Flow Path.
984 *
985 * @param flowPath the Flow Path to recompute.
986 * @return true if the recomputed Flow Path has changed, otherwise false.
987 */
988 private boolean recomputeFlowPath(FlowPath flowPath) {
989 boolean hasChanged = false;
990
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -0800991 if (enableOnrc2014MeasurementsFlows) {
992 // Cleanup the deleted Flow Entries from the earlier iteration
993 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -0800994
995 //
996 // TODO: Fake it that the Flow Entries have been already pushed
997 // into the switches, so we don't push them again.
998 //
999 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1000 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1001 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001002 }
1003
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001004 //
1005 // Test whether the Flow Path needs to be recomputed
1006 //
1007 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001008 case FP_TYPE_UNKNOWN:
1009 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001010 case FP_TYPE_SHORTEST_PATH:
1011 break;
1012 case FP_TYPE_EXPLICIT_PATH:
1013 return false; // An explicit path never changes
1014 }
1015
1016 DataPath oldDataPath = flowPath.dataPath();
1017
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001018 // Compute the new path
1019 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
1020 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001021 if (newDataPath == null) {
1022 // We need the DataPath to compare the paths
1023 newDataPath = new DataPath();
1024 }
1025 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1026
1027 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001028 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001029 //
1030 if (oldDataPath.flowEntries().size() !=
1031 newDataPath.flowEntries().size()) {
1032 hasChanged = true;
1033 } else {
1034 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1035 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1036 while (oldIter.hasNext() && newIter.hasNext()) {
1037 FlowEntry oldFlowEntry = oldIter.next();
1038 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001039 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1040 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001041 hasChanged = true;
1042 break;
1043 }
1044 }
1045 }
1046 if (! hasChanged)
1047 return hasChanged;
1048
1049 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001050 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001051 // - If a Flow Entry for a switch is in the old data path, but not
1052 // in the new data path, then mark it for deletion.
1053 // - If a Flow Entry for a switch is in the new data path, but not
1054 // in the old data path, then mark it for addition.
1055 // - If a Flow Entry for a switch is in both the old and the new
1056 // data path, but it has changed, e.g., the incoming and/or outgoing
1057 // port(s), then mark the old Flow Entry for deletion, and mark
1058 // the new Flow Entry for addition.
1059 // - If a Flow Entry for a switch is in both the old and the new
1060 // data path, and it hasn't changed, then just keep it.
1061 //
1062 // NOTE: We use the Switch DPID of each entry to match the entries
1063 //
1064 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1065 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1066 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1067 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1068
1069 // Prepare maps with the Flow Entries, so they are fast to lookup
1070 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1071 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1072 for (FlowEntry flowEntry : newDataPath.flowEntries())
1073 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1074
1075 //
1076 // Find the old Flow Entries that should be deleted
1077 //
1078 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1079 FlowEntry newFlowEntry =
1080 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1081 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001082 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001083 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1084 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1085 deletedFlowEntries.add(oldFlowEntry);
1086 }
1087 }
1088
1089 //
1090 // Find the new Flow Entries that should be added or updated
1091 //
1092 int idx = 0;
1093 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1094 FlowEntry oldFlowEntry =
1095 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1096
1097 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001098 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1099 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001100 //
1101 // Both Flow Entries are same
1102 //
1103 finalFlowEntries.add(oldFlowEntry);
1104 idx++;
1105 continue;
1106 }
1107
1108 if (oldFlowEntry != null) {
1109 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001110 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001111 //
1112 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1113 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1114 deletedFlowEntries.add(oldFlowEntry);
1115 }
1116
1117 //
1118 // Add the new Flow Entry
1119 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001120 //
1121 // NOTE: Assign only the Flow ID.
1122 // The Flow Entry ID is assigned later only for the Flow Entries
1123 // this instance is responsible for.
1124 //
1125 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001126
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001127 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001128 // Copy the Flow timeouts
1129 //
1130 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1131 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1132
1133 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001134 // Allocate the FlowEntryMatch by copying the default one
1135 // from the FlowPath (if set).
1136 //
1137 FlowEntryMatch flowEntryMatch = null;
1138 if (flowPath.flowEntryMatch() != null)
1139 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1140 else
1141 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001142 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001143
1144 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001145 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1146
1147 //
1148 // Set the actions:
1149 // If the first Flow Entry, copy the Flow Path actions to it.
1150 //
1151 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1152 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1153 FlowEntryActions flowActions =
1154 new FlowEntryActions(flowPath.flowEntryActions());
1155 for (FlowEntryAction action : flowActions.actions())
1156 flowEntryActions.addAction(action);
1157 }
1158 idx++;
1159
1160 //
1161 // Add the outgoing port output action
1162 //
1163 FlowEntryAction flowEntryAction = new FlowEntryAction();
1164 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1165 flowEntryActions.addAction(flowEntryAction);
1166
1167 //
1168 // Set the state of the new Flow Entry
1169 //
1170 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1171 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1172 finalFlowEntries.add(newFlowEntry);
1173 }
1174
1175 //
1176 // Replace the old Flow Entries with the new Flow Entries.
1177 // Note that the Flow Entries that will be deleted are added at
1178 // the end.
1179 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001180 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001181 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1182
1183 return hasChanged;
1184 }
1185
1186 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001187 * Receive a notification that a Flow is added.
1188 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001189 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001190 */
1191 @Override
1192 public void notificationRecvFlowAdded(FlowPath flowPath) {
1193 EventEntry<FlowPath> eventEntry =
1194 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1195 networkEvents.add(eventEntry);
1196 }
1197
1198 /**
1199 * Receive a notification that a Flow is removed.
1200 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001201 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001202 */
1203 @Override
1204 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1205 EventEntry<FlowPath> eventEntry =
1206 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1207 networkEvents.add(eventEntry);
1208 }
1209
1210 /**
1211 * Receive a notification that a Flow is updated.
1212 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001213 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001214 */
1215 @Override
1216 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1217 // NOTE: The ADD and UPDATE events are processed in same way
1218 EventEntry<FlowPath> eventEntry =
1219 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1220 networkEvents.add(eventEntry);
1221 }
1222
1223 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001224 * Receive a notification that a FlowEntry is added.
1225 *
1226 * @param flowEntry the FlowEntry that is added.
1227 */
1228 @Override
1229 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
1230 EventEntry<FlowEntry> eventEntry =
1231 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1232 networkEvents.add(eventEntry);
1233 }
1234
1235 /**
1236 * Receive a notification that a FlowEntry is removed.
1237 *
1238 * @param flowEntry the FlowEntry that is removed.
1239 */
1240 @Override
1241 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
1242 EventEntry<FlowEntry> eventEntry =
1243 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1244 networkEvents.add(eventEntry);
1245 }
1246
1247 /**
1248 * Receive a notification that a FlowEntry is updated.
1249 *
1250 * @param flowEntry the FlowEntry that is updated.
1251 */
1252 @Override
1253 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
1254 // NOTE: The ADD and UPDATE events are processed in same way
1255 EventEntry<FlowEntry> eventEntry =
1256 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1257 networkEvents.add(eventEntry);
1258 }
1259
1260 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001261 * Receive a notification that a FlowId is added.
1262 *
1263 * @param flowId the FlowId that is added.
1264 */
1265 @Override
1266 public void notificationRecvFlowIdAdded(FlowId flowId) {
1267 EventEntry<FlowId> eventEntry =
1268 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1269 networkEvents.add(eventEntry);
1270 }
1271
1272 /**
1273 * Receive a notification that a FlowId is removed.
1274 *
1275 * @param flowId the FlowId that is removed.
1276 */
1277 @Override
1278 public void notificationRecvFlowIdRemoved(FlowId flowId) {
1279 EventEntry<FlowId> eventEntry =
1280 new EventEntry<FlowId>(EventEntry.Type.ENTRY_REMOVE, flowId);
1281 networkEvents.add(eventEntry);
1282 }
1283
1284 /**
1285 * Receive a notification that a FlowId is updated.
1286 *
1287 * @param flowId the FlowId that is updated.
1288 */
1289 @Override
1290 public void notificationRecvFlowIdUpdated(FlowId flowId) {
1291 // NOTE: The ADD and UPDATE events are processed in same way
1292 EventEntry<FlowId> eventEntry =
1293 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1294 networkEvents.add(eventEntry);
1295 }
1296
1297 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001298 * Receive a notification that a FlowEntryId is added.
1299 *
1300 * @param flowEntryId the FlowEntryId that is added.
1301 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1302 */
1303 @Override
1304 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1305 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001306 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1307
1308 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1309 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001310 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001311 }
1312
1313 /**
1314 * Receive a notification that a FlowEntryId is removed.
1315 *
1316 * @param flowEntryId the FlowEntryId that is removed.
1317 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1318 */
1319 @Override
1320 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1321 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001322 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1323
1324 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1325 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001326 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001327 }
1328
1329 /**
1330 * Receive a notification that a FlowEntryId is updated.
1331 *
1332 * @param flowEntryId the FlowEntryId that is updated.
1333 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1334 */
1335 @Override
1336 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1337 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001338 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1339
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001340 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001341 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1342 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001343 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001344 }
1345
1346 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001347 * Receive a notification that a Topology Element is added.
1348 *
1349 * @param topologyElement the Topology Element that is added.
1350 */
1351 @Override
1352 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1353 EventEntry<TopologyElement> eventEntry =
1354 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1355 networkEvents.add(eventEntry);
1356 }
1357
1358 /**
1359 * Receive a notification that a Topology Element is removed.
1360 *
1361 * @param topologyElement the Topology Element that is removed.
1362 */
1363 @Override
1364 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1365 EventEntry<TopologyElement> eventEntry =
1366 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1367 networkEvents.add(eventEntry);
1368 }
1369
1370 /**
1371 * Receive a notification that a Topology Element is updated.
1372 *
1373 * @param topologyElement the Topology Element that is updated.
1374 */
1375 @Override
1376 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1377 // NOTE: The ADD and UPDATE events are processed in same way
1378 EventEntry<TopologyElement> eventEntry =
1379 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1380 networkEvents.add(eventEntry);
1381 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001382
1383 /**
1384 * Get a sorted copy of all Flow Paths.
1385 *
1386 * @return a sorted copy of all Flow Paths.
1387 */
1388 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1389 SortedMap<Long, FlowPath> sortedFlowPaths =
1390 new TreeMap<Long, FlowPath>();
1391
1392 //
1393 // TODO: For now we use serialization/deserialization to create
1394 // a copy of each Flow Path. In the future, we should use proper
1395 // copy constructors.
1396 //
1397 Kryo kryo = kryoFactory.newKryo();
1398 synchronized (allFlowPaths) {
1399 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1400 FlowPath origFlowPath = entry.getValue();
1401 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1402 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1403 }
1404 }
1405 kryoFactory.deleteKryo(kryo);
1406
1407 return sortedFlowPaths;
1408 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001409}