blob: 34958d8633f0c30e3620a2b5ab88ee4c7188c1e7 [file] [log] [blame]
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07003import java.util.ArrayList;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07004import java.util.Collection;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07005import java.util.HashMap;
6import java.util.Iterator;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07007import java.util.LinkedList;
8import java.util.List;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07009import java.util.Map;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080010import java.util.SortedMap;
11import java.util.TreeMap;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070012import java.util.concurrent.BlockingQueue;
13import java.util.concurrent.LinkedBlockingQueue;
14
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080015import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070016import net.onrc.onos.datagrid.IDatagridService;
Naoki Shiota0abe38d2014-01-07 15:31:22 -080017import net.onrc.onos.graph.GraphDBOperation;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070018import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070019import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070020import net.onrc.onos.ofcontroller.topology.TopologyManager;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070021import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080022import net.onrc.onos.ofcontroller.util.Dpid;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070023import net.onrc.onos.ofcontroller.util.EventEntry;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070024import net.onrc.onos.ofcontroller.util.FlowEntry;
25import net.onrc.onos.ofcontroller.util.FlowEntryAction;
26import net.onrc.onos.ofcontroller.util.FlowEntryActions;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070027import net.onrc.onos.ofcontroller.util.FlowEntryId;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070028import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
29import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
30import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070031import net.onrc.onos.ofcontroller.util.FlowId;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070032import net.onrc.onos.ofcontroller.util.FlowPath;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070033import net.onrc.onos.ofcontroller.util.FlowPathUserState;
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080034import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080035import net.onrc.onos.ofcontroller.util.Port;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080036import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
37
38import com.esotericsoftware.kryo2.Kryo;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070039
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070044 * Class for FlowPath Maintenance.
45 * This class listens for FlowEvents to:
46 * - Maintain a local cache of the Network Topology.
47 * - Detect FlowPaths impacted by Topology change.
48 * - Recompute impacted FlowPath using cached Topology.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070049 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070050class FlowEventHandler extends Thread implements IFlowEventHandlerService {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080051
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -080052 private boolean enableOnrc2014MeasurementsFlows = true;
53 private boolean enableOnrc2014MeasurementsTopology = true;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080054
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070055 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070056 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
Naoki Shiota0abe38d2014-01-07 15:31:22 -080057
Naoki Shiota0abe38d2014-01-07 15:31:22 -080058 private GraphDBOperation dbHandler;
Naoki Shiotaf74d5f32014-01-09 21:29:38 -080059
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070060 private FlowManager flowManager; // The Flow Manager to use
61 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070062 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080063 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070064
65 // The queue with Flow Path and Topology Element updates
66 private BlockingQueue<EventEntry<?>> networkEvents =
67 new LinkedBlockingQueue<EventEntry<?>>();
68
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070069 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070070 private List<EventEntry<TopologyElement>> topologyEvents =
71 new LinkedList<EventEntry<TopologyElement>>();
72 private List<EventEntry<FlowPath>> flowPathEvents =
73 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070074 private List<EventEntry<FlowEntry>> flowEntryEvents =
75 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -080076 private List<EventEntry<FlowId>> flowIdEvents =
77 new LinkedList<EventEntry<FlowId>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080078 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
79 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070080
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080081 // All internally computed Flow Paths
82 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
83
84 // The Flow Entries received as notifications with unmatched Flow Paths
85 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
86 new HashMap<Long, FlowEntry>();
87
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080088 //
89 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080090 // - The Flow Paths that should be recomputed
91 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080092 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080093 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080094 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
95 new HashMap<Long, FlowPath>();
96 private Map<Long, FlowPath> modifiedFlowPaths =
97 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080098 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
99 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800100
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700101 /**
102 * Constructor for a given Flow Manager and Datagrid Service.
103 *
104 * @param flowManager the Flow Manager to use.
105 * @param datagridService the Datagrid Service to use.
106 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700107 FlowEventHandler(FlowManager flowManager,
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800108 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700109 this.flowManager = flowManager;
110 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700111 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700112 }
113
114 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800115 * Get the network topology.
116 *
117 * @return the network topology.
118 */
119 protected Topology getTopology() { return this.topology; }
120
121 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800122 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700123 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800124 private void startup() {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800125 this.dbHandler = new GraphDBOperation("");
126
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700127 //
128 // Obtain the initial Topology state
129 //
130 Collection<TopologyElement> topologyElements =
131 datagridService.getAllTopologyElements();
132 for (TopologyElement topologyElement : topologyElements) {
133 EventEntry<TopologyElement> eventEntry =
134 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
135 topologyEvents.add(eventEntry);
136 }
137 //
138 // Obtain the initial Flow Path state
139 //
140 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
141 for (FlowPath flowPath : flowPaths) {
142 EventEntry<FlowPath> eventEntry =
143 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
144 flowPathEvents.add(eventEntry);
145 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700146 //
147 // Obtain the initial FlowEntry state
148 //
149 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
150 for (FlowEntry flowEntry : flowEntries) {
151 EventEntry<FlowEntry> eventEntry =
152 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
153 flowEntryEvents.add(eventEntry);
154 }
155
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800156 //
157 // Obtain the initial FlowId state
158 //
159 Collection<FlowId> flowIds = datagridService.getAllFlowIds();
160 for (FlowId flowId : flowIds) {
161 EventEntry<FlowId> eventEntry =
162 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
163 flowIdEvents.add(eventEntry);
164 }
165
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800166 //
167 // Obtain the initial FlowEntryId state
168 //
169 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
170 datagridService.getAllFlowEntryIds();
171 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
172 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
173 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
174 flowEntryIdEvents.add(eventEntry);
175 }
176
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800177 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800178 synchronized (allFlowPaths) {
179 processEvents();
180 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800181 }
182
183 /**
184 * Run the thread.
185 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800186 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800187 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800188 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800189 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700190
191 //
192 // The main loop
193 //
194 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
195 try {
196 while (true) {
197 EventEntry<?> eventEntry = networkEvents.take();
198 collection.add(eventEntry);
199 networkEvents.drainTo(collection);
200
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700201 //
202 // Demultiplex all events:
203 // - EventEntry<TopologyElement>
204 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700205 // - EventEntry<FlowEntry>
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800206 // - EventEntry<FlowId>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800207 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700208 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700209 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800210 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700211 if (event.eventData() instanceof TopologyElement) {
212 EventEntry<TopologyElement> topologyEventEntry =
213 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800214
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700215 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800216 continue;
217 }
218
219 // FlowPath event
220 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700221 EventEntry<FlowPath> flowPathEventEntry =
222 (EventEntry<FlowPath>)event;
223 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800224 continue;
225 }
226
227 // FlowEntry event
228 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700229 EventEntry<FlowEntry> flowEntryEventEntry =
230 (EventEntry<FlowEntry>)event;
231 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800232 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700233 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800234
235 // FlowId event
236 if (event.eventData() instanceof FlowId) {
237 EventEntry<FlowId> flowIdEventEntry =
238 (EventEntry<FlowId>)event;
239 flowIdEvents.add(flowIdEventEntry);
240 continue;
241 }
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800242 // FlowEntryId event
243 if (event.eventData() instanceof Pair) {
244 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
245 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
246 flowEntryIdEvents.add(flowEntryIdEventEntry);
247 continue;
248 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700249 }
250 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700251
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700252 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800253 synchronized (allFlowPaths) {
254 processEvents();
255 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700256 }
257 } catch (Exception exception) {
258 log.debug("Exception processing Network Events: ", exception);
259 }
260 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800261
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700262 /**
263 * Process the events (if any)
264 */
265 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800266 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700267
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800268 if (enableOnrc2014MeasurementsFlows) {
269
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800270 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800271 return; // Nothing to do
272 }
273
274 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
275
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800276 // Process the Flow ID events
277 processFlowIdEvents(mySwitches);
278
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800279 // Fetch the topology
280 processTopologyEvents();
281
282 // Recompute all affected Flow Paths and keep only the modified
283 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
284 if (recomputeFlowPath(flowPath))
285 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
286 }
287
288 // Assign the Flow Entry ID as needed
289 for (FlowPath flowPath : modifiedFlowPaths.values()) {
290 for (FlowEntry flowEntry : flowPath.flowEntries()) {
291 if (! flowEntry.isValidFlowEntryId()) {
292 long id = flowManager.getNextFlowEntryId();
293 flowEntry.setFlowEntryId(new FlowEntryId(id));
294 }
295 }
296 }
297
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800298 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800299 // Push the modified state to the database
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800300 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800301 flowManager.writeModifiedFlowPathsToDatabase(modifiedFlowPaths.values());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800302
303 // Cleanup
304 topologyEvents.clear();
305 flowIdEvents.clear();
306 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800307 // NOTE: Keep a cache with my Flow Paths
308 // allFlowPaths.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800309 shouldRecomputeFlowPaths.clear();
310 modifiedFlowPaths.clear();
311
312 return;
313 }
314
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700315 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800316 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700317 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700318 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700319
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800320 processFlowPathEvents();
321 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800322 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800323 processFlowEntryEvents();
324
325 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800326 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800327 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800328 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800329 }
330
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800331 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800332 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800333
334 // Assign missing Flow Entry IDs
335 assignFlowEntryId(modifiedFlowEntries);
336
337 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800338 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800339 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800340 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
341 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800342
343 //
344 // Remove Flow Entries that were deleted
345 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800346 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800347 flowPath.dataPath().removeDeletedFlowEntries();
348
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800349 //
350 // Check if Flow Paths have been installed into all switches,
351 // and generate the appropriate events.
352 //
353 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
354
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800355 // Cleanup
356 topologyEvents.clear();
357 flowPathEvents.clear();
358 flowEntryEvents.clear();
359 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800360 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800361 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800362 checkIfInstalledFlowPaths.clear();
363 }
364
365 /**
366 * Check if Flow Paths have been installed into all switches,
367 * and generate the appropriate events.
368 *
369 * @param flowPaths the flowPaths to process.
370 */
371 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
372 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
373
374 Kryo kryo = kryoFactory.newKryo();
375
376 for (FlowPath flowPath : flowPaths) {
377 boolean isInstalled = true;
378
379 //
380 // Check whether all Flow Entries have been installed
381 //
382 for (FlowEntry flowEntry : flowPath.flowEntries()) {
383 if (flowEntry.flowEntrySwitchState() !=
384 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
385 isInstalled = false;
386 break;
387 }
388 }
389
390 if (isInstalled) {
391 // Create a copy and add it to the list
392 FlowPath copyFlowPath = kryo.copy(flowPath);
393 installedFlowPaths.add(copyFlowPath);
394 }
395 }
396 kryoFactory.deleteKryo(kryo);
397
398 // Generate an event for the installed Flow Path.
399 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800400 }
401
402 /**
403 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800404 *
405 * @param modifiedFlowPaths the Flow Paths to process.
406 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800407 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800408 private Collection<FlowEntry> extractModifiedFlowEntries(
409 Collection<FlowPath> modifiedFlowPaths) {
410 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800411
412 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800413 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800414 for (FlowEntry flowEntry : flowPath.flowEntries()) {
415 if (flowEntry.flowEntrySwitchState() ==
416 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800417 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800418 }
419 }
420 }
421 return modifiedFlowEntries;
422 }
423
424 /**
425 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800426 *
427 * @param modifiedFlowEnries the collection of Flow Entries that need
428 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800429 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800430 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800431 if (modifiedFlowEntries.isEmpty())
432 return;
433
434 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
435
436 //
437 // Assign the Flow Entry ID only for Flow Entries for my switches
438 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800439 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800440 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
441 if (mySwitch == null)
442 continue;
443 if (! flowEntry.isValidFlowEntryId()) {
444 long id = flowManager.getNextFlowEntryId();
445 flowEntry.setFlowEntryId(new FlowEntryId(id));
446 }
447 }
448 }
449
450 /**
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800451 * Fix a flow fetched from the database.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800452 *
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800453 * @param flowPath the Flow to fix.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800454 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800455 private void fixFlowFromDatabase(FlowPath flowPath) {
456 //
457 // TODO: Bug workaround / fix :
458 // method FlowDatabaseOperation.extractFlowEntry() doesn't
459 // fetch the inPort and outPort, hence we assign them here.
460 //
461 // Assign the inPort and outPort for the Flow Entries
462 for (FlowEntry flowEntry : flowPath.flowEntries()) {
463 // Set the inPort
464 do {
465 if (flowEntry.inPort() != null)
466 break;
467 if (flowEntry.flowEntryMatch() == null)
468 break;
469 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
470 flowEntry.setInPort(inPort);
471 } while (false);
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800472
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800473 // Set the outPort
474 do {
475 if (flowEntry.outPort() != null)
476 break;
477 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
478 if (fa.actionOutput() != null) {
479 Port outPort = new Port(fa.actionOutput().port().value());
480 flowEntry.setOutPort(outPort);
481 break;
482 }
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800483 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800484 } while (false);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800485 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800486 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800487
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800488 /**
489 * Process the Flow ID events.
490 *
491 * @param mySwitches the collection of my switches.
492 */
493 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800494 List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
495
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800496 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800497 // Process all Flow Id events and update the appropriate state
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800498 //
499 for (EventEntry<FlowId> eventEntry : flowIdEvents) {
500 FlowId flowId = eventEntry.eventData();
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800501
502 log.debug("Flow ID Event: {} {}", eventEntry.eventType(), flowId);
503
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800504 switch (eventEntry.eventType()) {
505 case ENTRY_ADD: {
506 //
507 // Add a new Flow Path
508 //
509 if (allFlowPaths.get(flowId.value()) != null) {
510 //
511 // TODO: What to do if the Flow Path already exists?
512 // Fow now, we just re-add it.
513 //
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800514 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800515 shouldFetchMyFlowIds.add(flowId);
516
517 break;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800518 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800519
520 case ENTRY_REMOVE: {
521 //
522 // Remove an existing Flow Path.
523 //
524 // Find the Flow Path, and mark the Flow and its Flow Entries
525 // for deletion.
526 //
527 FlowPath existingFlowPath =
528 allFlowPaths.get(flowId.value());
529 if (existingFlowPath == null)
530 continue; // Nothing to do
531
532 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
533 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
534 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
535 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
536 }
537
538 // Remove the Flow Path from the internal state
539 Long key = existingFlowPath.flowId().value();
540 allFlowPaths.remove(key);
541 shouldRecomputeFlowPaths.remove(key);
542 modifiedFlowPaths.put(key, existingFlowPath);
543
544 break;
545 }
546 }
547 }
548
549 // Get my Flows
550 Collection<FlowPath> myFlows =
551 FlowDatabaseOperation.getFlows(dbHandler, shouldFetchMyFlowIds);
552
553 for (FlowPath flowPath : myFlows) {
554 fixFlowFromDatabase(flowPath);
555
556 switch (flowPath.flowPathType()) {
557 case FP_TYPE_SHORTEST_PATH:
558 //
559 // Reset the Data Path, in case it was set already, because
560 // we are going to recompute it anyway.
561 //
562 flowPath.flowEntries().clear();
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800563 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
564 flowPath);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800565 break;
566 case FP_TYPE_EXPLICIT_PATH:
567 //
568 // Mark all Flow Entries for installation in the switches.
569 //
570 for (FlowEntry flowEntry : flowPath.flowEntries()) {
571 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
572 }
573 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
574 break;
575 case FP_TYPE_UNKNOWN:
576 log.error("FlowPath event with unknown type");
577 break;
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800578 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800579 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800580 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800581 }
582
583 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800584 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800585 *
586 * @param mySwitches the collection of my switches.
587 * @return a collection of modified Flow Entries this instance needs
588 * to push to its own switches.
589 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800590 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800591 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
592
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800593 //
594 // Process all Flow ID events and update the appropriate state
595 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800596 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
597 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
598 FlowEntryId flowEntryId = pair.first;
599 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800600
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800601 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
602 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800603
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800604 if (mySwitches.get(dpid.value()) == null)
605 continue;
606
607 // Fetch the Flow Entry
608 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
609 flowEntryId);
610 if (flowEntry == null) {
611 log.debug("Flow Entry ID {} : Flow Entry not found!",
612 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800613 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800614 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800615 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800616 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800617
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800618 return modifiedFlowEntries;
619 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800620
621 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800622 * Process the Flow Path events.
623 */
624 private void processFlowPathEvents() {
625 //
626 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700627 //
628 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
629 FlowPath flowPath = eventEntry.eventData();
630
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800631 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800632
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700633 switch (eventEntry.eventType()) {
634 case ENTRY_ADD: {
635 //
636 // Add a new Flow Path
637 //
638 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
639 //
640 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800641 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700642 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700643 }
644
645 switch (flowPath.flowPathType()) {
646 case FP_TYPE_SHORTEST_PATH:
647 //
648 // Reset the Data Path, in case it was set already, because
649 // we are going to recompute it anyway.
650 //
651 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800652 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
653 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700654 break;
655 case FP_TYPE_EXPLICIT_PATH:
656 //
657 // Mark all Flow Entries for installation in the switches.
658 //
659 for (FlowEntry flowEntry : flowPath.flowEntries()) {
660 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
661 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800662 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700663 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800664 case FP_TYPE_UNKNOWN:
665 log.error("FlowPath event with unknown type");
666 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700667 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800668 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700669
670 break;
671 }
672
673 case ENTRY_REMOVE: {
674 //
675 // Remove an existing Flow Path.
676 //
677 // Find the Flow Path, and mark the Flow and its Flow Entries
678 // for deletion.
679 //
680 FlowPath existingFlowPath =
681 allFlowPaths.get(flowPath.flowId().value());
682 if (existingFlowPath == null)
683 continue; // Nothing to do
684
685 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
686 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
687 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
688 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
689 }
690
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800691 // Remove the Flow Path from the internal state
692 Long key = existingFlowPath.flowId().value();
693 allFlowPaths.remove(key);
694 shouldRecomputeFlowPaths.remove(key);
695 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700696
697 break;
698 }
699 }
700 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800701 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700702
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800703 /**
704 * Process the Topology events.
705 */
706 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800707 boolean isTopologyModified = false;
708
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800709 if (enableOnrc2014MeasurementsTopology) {
710 if (topologyEvents.isEmpty())
711 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800712
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800713 // TODO: Code for debugging purpose only
714 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
715 TopologyElement topologyElement = eventEntry.eventData();
716 log.debug("Topology Event: {} {}", eventEntry.eventType(),
717 topologyElement.toString());
718 }
719
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800720 log.debug("[BEFORE] {}", topology.toString());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800721 topology.readFromDatabase(dbHandler);
722 log.debug("[AFTER] {}", topology.toString());
723 shouldRecomputeFlowPaths.putAll(allFlowPaths);
724 return;
725 }
726
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700727 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800728 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700729 //
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800730 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
731 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800732
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800733 log.debug("Topology Event: {} {}", eventEntry.eventType(),
734 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800735
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800736 switch (eventEntry.eventType()) {
737 case ENTRY_ADD:
Naoki Shiota9f6fc212014-01-09 21:38:08 -0800738 isTopologyModified |= topology.addTopologyElement(topologyElement);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800739 break;
740 case ENTRY_REMOVE:
Naoki Shiota9f6fc212014-01-09 21:38:08 -0800741 isTopologyModified |= topology.removeTopologyElement(topologyElement);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800742 break;
743 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700744 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700745 if (isTopologyModified) {
746 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800747 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700748 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800749 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700750
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800751 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800752 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800753 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800754 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800755 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800756 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800757
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700758 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800759 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700760 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800761 if (! unmatchedFlowEntryAdd.isEmpty()) {
762 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
763 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800764 // log.debug("Processing Unmatched Flow Entry: {}",
765 // flowEntry.toString());
766
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800767 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800768 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800769 remainingUpdates.put(flowEntry.flowEntryId().value(),
770 flowEntry);
771 continue;
772 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800773 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
774 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800775 remainingUpdates.put(flowEntry.flowEntryId().value(),
776 flowEntry);
777 continue;
778 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800779 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
780 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
781 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700782 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800783 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700784 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800785 }
786
787 /**
788 * Process the Flow Entry events.
789 */
790 private void processFlowEntryEvents() {
791 FlowPath flowPath;
792 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700793
794 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800795 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700796 //
797 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
798 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800799
800 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800801 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800802
803 if ((! flowEntry.isValidFlowId()) ||
804 (! flowEntry.isValidFlowEntryId())) {
805 continue;
806 }
807
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700808 switch (eventEntry.eventType()) {
809 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800810 flowPath = allFlowPaths.get(flowEntry.flowId().value());
811 if (flowPath == null) {
812 // Flow Path not found: keep the entry for later matching
813 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
814 flowEntry);
815 break;
816 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800817 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
818 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800819 // Flow Entry not found: keep the entry for later matching
820 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
821 flowEntry);
822 break;
823 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800824 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
825 // Add the updated Flow Path to the list of updated paths
826 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
827 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700828 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800829
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700830 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800831 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
832 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800833 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800834 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800835
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800836 flowPath = allFlowPaths.get(flowEntry.flowId().value());
837 if (flowPath == null) {
838 // Flow Path not found: ignore the update
839 break;
840 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800841 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
842 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800843 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800844 break;
845 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800846 if (updateFlowEntryRemove(flowPath, localFlowEntry,
847 flowEntry)) {
848 // Add the updated Flow Path to the list of updated paths
849 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
850 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700851 break;
852 }
853 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700854 }
855
856 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800857 * Find a Flow Entry that should be updated because of an external
858 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700859 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800860 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800861 * @param newFlowEntry the FlowEntry with the new state.
862 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700863 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800864 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
865 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700866 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800867 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700868 //
869 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800870 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800871 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700872 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800873 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700874
875 //
876 // Local Flow Entry match found
877 //
878 if (localFlowEntry.isValidFlowEntryId()) {
879 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800880 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700881 //
882 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800883 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700884 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800885 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700886 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700887 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800888 return localFlowEntry;
889 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700890
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800891 return null; // Entry not found
892 }
893
894 /**
895 * Update a Flow Entry because of an external ENTRY_ADD event.
896 *
897 * @param flowPath the FlowPath for the Flow Entry to update.
898 * @param localFlowEntry the local Flow Entry to update.
899 * @param newFlowEntry the FlowEntry with the new state.
900 * @return true if the local Flow Entry was updated, otherwise false.
901 */
902 private boolean updateFlowEntryAdd(FlowPath flowPath,
903 FlowEntry localFlowEntry,
904 FlowEntry newFlowEntry) {
905 boolean updated = false;
906
907 if (localFlowEntry.flowEntryUserState() ==
908 FlowEntryUserState.FE_USER_DELETE) {
909 // Don't add-back a Flow Entry that is already deleted
910 return false;
911 }
912
913 if (! localFlowEntry.isValidFlowEntryId()) {
914 // Update the Flow Entry ID
915 FlowEntryId flowEntryId =
916 new FlowEntryId(newFlowEntry.flowEntryId().value());
917 localFlowEntry.setFlowEntryId(flowEntryId);
918 updated = true;
919 }
920
921 //
922 // Update the local Flow Entry, and keep state to check
923 // if the Flow Path has been installed.
924 //
925 if (localFlowEntry.flowEntryUserState() !=
926 newFlowEntry.flowEntryUserState()) {
927 localFlowEntry.setFlowEntryUserState(
928 newFlowEntry.flowEntryUserState());
929 updated = true;
930 }
931 if (localFlowEntry.flowEntrySwitchState() !=
932 newFlowEntry.flowEntrySwitchState()) {
933 localFlowEntry.setFlowEntrySwitchState(
934 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800935 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800936 updated = true;
937 }
938
939 return updated;
940 }
941
942 /**
943 * Find a Flow Entry that should be updated because of an external
944 * ENTRY_REMOVE event.
945 *
946 * @param flowPath the FlowPath for the Flow Entry to update.
947 * @param newFlowEntry the FlowEntry with the new state.
948 * @return the Flow Entry that should be updated if found, otherwise null.
949 */
950 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
951 FlowEntry newFlowEntry) {
952 //
953 // Iterate over all Flow Entries and find a match based on
954 // the Flow Entry ID.
955 //
956 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
957 if (! localFlowEntry.isValidFlowEntryId())
958 continue;
959 if (localFlowEntry.flowEntryId().value() !=
960 newFlowEntry.flowEntryId().value()) {
961 continue;
962 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800963 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700964 }
965
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800966 return null; // Entry not found
967 }
968
969 /**
970 * Update a Flow Entry because of an external ENTRY_REMOVE event.
971 *
972 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800973 * @param localFlowEntry the local Flow Entry to update.
974 * @param newFlowEntry the FlowEntry with the new state.
975 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800976 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800977 private boolean updateFlowEntryRemove(FlowPath flowPath,
978 FlowEntry localFlowEntry,
979 FlowEntry newFlowEntry) {
980 boolean updated = false;
981
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800982 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800983 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800984 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800985 if (localFlowEntry.flowEntryUserState() !=
986 newFlowEntry.flowEntryUserState()) {
987 localFlowEntry.setFlowEntryUserState(
988 newFlowEntry.flowEntryUserState());
989 updated = true;
990 }
991 if (localFlowEntry.flowEntrySwitchState() !=
992 newFlowEntry.flowEntrySwitchState()) {
993 localFlowEntry.setFlowEntrySwitchState(
994 newFlowEntry.flowEntrySwitchState());
995 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800996 }
997
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800998 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700999 }
1000
1001 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001002 * Recompute a Flow Path.
1003 *
1004 * @param flowPath the Flow Path to recompute.
1005 * @return true if the recomputed Flow Path has changed, otherwise false.
1006 */
1007 private boolean recomputeFlowPath(FlowPath flowPath) {
1008 boolean hasChanged = false;
1009
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001010 if (enableOnrc2014MeasurementsFlows) {
1011 // Cleanup the deleted Flow Entries from the earlier iteration
1012 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -08001013
1014 //
1015 // TODO: Fake it that the Flow Entries have been already pushed
1016 // into the switches, so we don't push them again.
1017 //
1018 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1019 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1020 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001021 }
1022
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001023 //
1024 // Test whether the Flow Path needs to be recomputed
1025 //
1026 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001027 case FP_TYPE_UNKNOWN:
1028 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001029 case FP_TYPE_SHORTEST_PATH:
1030 break;
1031 case FP_TYPE_EXPLICIT_PATH:
1032 return false; // An explicit path never changes
1033 }
1034
1035 DataPath oldDataPath = flowPath.dataPath();
1036
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001037 // Compute the new path
Naoki Shiota9f6fc212014-01-09 21:38:08 -08001038 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001039 flowPath);
Naoki Shiotaf74d5f32014-01-09 21:29:38 -08001040
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001041 if (newDataPath == null) {
1042 // We need the DataPath to compare the paths
1043 newDataPath = new DataPath();
1044 }
1045 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1046
1047 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001048 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001049 //
1050 if (oldDataPath.flowEntries().size() !=
1051 newDataPath.flowEntries().size()) {
1052 hasChanged = true;
1053 } else {
1054 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1055 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1056 while (oldIter.hasNext() && newIter.hasNext()) {
1057 FlowEntry oldFlowEntry = oldIter.next();
1058 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001059 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1060 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001061 hasChanged = true;
1062 break;
1063 }
1064 }
1065 }
1066 if (! hasChanged)
1067 return hasChanged;
1068
1069 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001070 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001071 // - If a Flow Entry for a switch is in the old data path, but not
1072 // in the new data path, then mark it for deletion.
1073 // - If a Flow Entry for a switch is in the new data path, but not
1074 // in the old data path, then mark it for addition.
1075 // - If a Flow Entry for a switch is in both the old and the new
1076 // data path, but it has changed, e.g., the incoming and/or outgoing
1077 // port(s), then mark the old Flow Entry for deletion, and mark
1078 // the new Flow Entry for addition.
1079 // - If a Flow Entry for a switch is in both the old and the new
1080 // data path, and it hasn't changed, then just keep it.
1081 //
1082 // NOTE: We use the Switch DPID of each entry to match the entries
1083 //
1084 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1085 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1086 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1087 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1088
1089 // Prepare maps with the Flow Entries, so they are fast to lookup
1090 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1091 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1092 for (FlowEntry flowEntry : newDataPath.flowEntries())
1093 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1094
1095 //
1096 // Find the old Flow Entries that should be deleted
1097 //
1098 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1099 FlowEntry newFlowEntry =
1100 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1101 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001102 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001103 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1104 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1105 deletedFlowEntries.add(oldFlowEntry);
1106 }
1107 }
1108
1109 //
1110 // Find the new Flow Entries that should be added or updated
1111 //
1112 int idx = 0;
1113 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1114 FlowEntry oldFlowEntry =
1115 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1116
1117 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001118 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1119 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001120 //
1121 // Both Flow Entries are same
1122 //
1123 finalFlowEntries.add(oldFlowEntry);
1124 idx++;
1125 continue;
1126 }
1127
1128 if (oldFlowEntry != null) {
1129 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001130 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001131 //
1132 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1133 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1134 deletedFlowEntries.add(oldFlowEntry);
1135 }
1136
1137 //
1138 // Add the new Flow Entry
1139 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001140 //
1141 // NOTE: Assign only the Flow ID.
1142 // The Flow Entry ID is assigned later only for the Flow Entries
1143 // this instance is responsible for.
1144 //
1145 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001146
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001147 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001148 // Copy the Flow timeouts
1149 //
1150 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1151 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1152
1153 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001154 // Allocate the FlowEntryMatch by copying the default one
1155 // from the FlowPath (if set).
1156 //
1157 FlowEntryMatch flowEntryMatch = null;
1158 if (flowPath.flowEntryMatch() != null)
1159 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1160 else
1161 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001162 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001163
1164 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001165 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1166
1167 //
1168 // Set the actions:
1169 // If the first Flow Entry, copy the Flow Path actions to it.
1170 //
1171 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1172 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1173 FlowEntryActions flowActions =
1174 new FlowEntryActions(flowPath.flowEntryActions());
1175 for (FlowEntryAction action : flowActions.actions())
1176 flowEntryActions.addAction(action);
1177 }
1178 idx++;
1179
1180 //
1181 // Add the outgoing port output action
1182 //
1183 FlowEntryAction flowEntryAction = new FlowEntryAction();
1184 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1185 flowEntryActions.addAction(flowEntryAction);
1186
1187 //
1188 // Set the state of the new Flow Entry
1189 //
1190 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1191 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1192 finalFlowEntries.add(newFlowEntry);
1193 }
1194
1195 //
1196 // Replace the old Flow Entries with the new Flow Entries.
1197 // Note that the Flow Entries that will be deleted are added at
1198 // the end.
1199 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001200 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001201 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1202
1203 return hasChanged;
1204 }
1205
1206 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001207 * Receive a notification that a Flow is added.
1208 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001209 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001210 */
1211 @Override
1212 public void notificationRecvFlowAdded(FlowPath flowPath) {
1213 EventEntry<FlowPath> eventEntry =
1214 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1215 networkEvents.add(eventEntry);
1216 }
1217
1218 /**
1219 * Receive a notification that a Flow is removed.
1220 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001221 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001222 */
1223 @Override
1224 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1225 EventEntry<FlowPath> eventEntry =
1226 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1227 networkEvents.add(eventEntry);
1228 }
1229
1230 /**
1231 * Receive a notification that a Flow is updated.
1232 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001233 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001234 */
1235 @Override
1236 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1237 // NOTE: The ADD and UPDATE events are processed in same way
1238 EventEntry<FlowPath> eventEntry =
1239 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1240 networkEvents.add(eventEntry);
1241 }
1242
1243 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001244 * Receive a notification that a FlowEntry is added.
1245 *
1246 * @param flowEntry the FlowEntry that is added.
1247 */
1248 @Override
1249 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001250 if (enableOnrc2014MeasurementsFlows) {
1251 Collection entries = new ArrayList();
1252 entries.add(flowEntry);
1253 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1254 return;
1255 }
1256
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001257 EventEntry<FlowEntry> eventEntry =
1258 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1259 networkEvents.add(eventEntry);
1260 }
1261
1262 /**
1263 * Receive a notification that a FlowEntry is removed.
1264 *
1265 * @param flowEntry the FlowEntry that is removed.
1266 */
1267 @Override
1268 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001269 if (enableOnrc2014MeasurementsFlows) {
Pavlin Radoslavove4d2a432014-01-10 12:01:08 -08001270 //
1271 // NOTE: Must update the state to DELETE, because
1272 // the notification contains the original state.
1273 //
1274 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1275
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001276 Collection entries = new ArrayList();
1277 entries.add(flowEntry);
1278 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1279 return;
1280 }
1281
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001282 EventEntry<FlowEntry> eventEntry =
1283 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1284 networkEvents.add(eventEntry);
1285 }
1286
1287 /**
1288 * Receive a notification that a FlowEntry is updated.
1289 *
1290 * @param flowEntry the FlowEntry that is updated.
1291 */
1292 @Override
1293 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001294 if (enableOnrc2014MeasurementsFlows) {
1295 Collection entries = new ArrayList();
1296 entries.add(flowEntry);
1297 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1298 return;
1299 }
1300
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001301 // NOTE: The ADD and UPDATE events are processed in same way
1302 EventEntry<FlowEntry> eventEntry =
1303 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1304 networkEvents.add(eventEntry);
1305 }
1306
1307 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001308 * Receive a notification that a FlowId is added.
1309 *
1310 * @param flowId the FlowId that is added.
1311 */
1312 @Override
1313 public void notificationRecvFlowIdAdded(FlowId flowId) {
1314 EventEntry<FlowId> eventEntry =
1315 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1316 networkEvents.add(eventEntry);
1317 }
1318
1319 /**
1320 * Receive a notification that a FlowId is removed.
1321 *
1322 * @param flowId the FlowId that is removed.
1323 */
1324 @Override
1325 public void notificationRecvFlowIdRemoved(FlowId flowId) {
1326 EventEntry<FlowId> eventEntry =
1327 new EventEntry<FlowId>(EventEntry.Type.ENTRY_REMOVE, flowId);
1328 networkEvents.add(eventEntry);
1329 }
1330
1331 /**
1332 * Receive a notification that a FlowId is updated.
1333 *
1334 * @param flowId the FlowId that is updated.
1335 */
1336 @Override
1337 public void notificationRecvFlowIdUpdated(FlowId flowId) {
1338 // NOTE: The ADD and UPDATE events are processed in same way
1339 EventEntry<FlowId> eventEntry =
1340 new EventEntry<FlowId>(EventEntry.Type.ENTRY_ADD, flowId);
1341 networkEvents.add(eventEntry);
1342 }
1343
1344 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001345 * Receive a notification that a FlowEntryId is added.
1346 *
1347 * @param flowEntryId the FlowEntryId that is added.
1348 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1349 */
1350 @Override
1351 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1352 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001353 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1354
1355 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1356 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001357 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001358 }
1359
1360 /**
1361 * Receive a notification that a FlowEntryId is removed.
1362 *
1363 * @param flowEntryId the FlowEntryId that is removed.
1364 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1365 */
1366 @Override
1367 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1368 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001369 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1370
1371 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1372 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001373 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001374 }
1375
1376 /**
1377 * Receive a notification that a FlowEntryId is updated.
1378 *
1379 * @param flowEntryId the FlowEntryId that is updated.
1380 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1381 */
1382 @Override
1383 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1384 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001385 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1386
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001387 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001388 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1389 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001390 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001391 }
1392
1393 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001394 * Receive a notification that a Topology Element is added.
1395 *
1396 * @param topologyElement the Topology Element that is added.
1397 */
1398 @Override
1399 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1400 EventEntry<TopologyElement> eventEntry =
1401 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1402 networkEvents.add(eventEntry);
1403 }
1404
1405 /**
1406 * Receive a notification that a Topology Element is removed.
1407 *
1408 * @param topologyElement the Topology Element that is removed.
1409 */
1410 @Override
1411 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1412 EventEntry<TopologyElement> eventEntry =
1413 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1414 networkEvents.add(eventEntry);
1415 }
1416
1417 /**
1418 * Receive a notification that a Topology Element is updated.
1419 *
1420 * @param topologyElement the Topology Element that is updated.
1421 */
1422 @Override
1423 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1424 // NOTE: The ADD and UPDATE events are processed in same way
1425 EventEntry<TopologyElement> eventEntry =
1426 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1427 networkEvents.add(eventEntry);
1428 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001429
1430 /**
1431 * Get a sorted copy of all Flow Paths.
1432 *
1433 * @return a sorted copy of all Flow Paths.
1434 */
1435 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1436 SortedMap<Long, FlowPath> sortedFlowPaths =
1437 new TreeMap<Long, FlowPath>();
1438
1439 //
1440 // TODO: For now we use serialization/deserialization to create
1441 // a copy of each Flow Path. In the future, we should use proper
1442 // copy constructors.
1443 //
1444 Kryo kryo = kryoFactory.newKryo();
1445 synchronized (allFlowPaths) {
1446 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1447 FlowPath origFlowPath = entry.getValue();
1448 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1449 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1450 }
1451 }
1452 kryoFactory.deleteKryo(kryo);
1453
1454 return sortedFlowPaths;
1455 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001456}