blob: fa650f62c920ee727988f41451ea5b01d1ff9f94 [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 Radoslavov2194d112014-01-10 13:36:00 -080076 private List<EventEntry<Pair<FlowId, Dpid>>> flowIdEvents =
77 new LinkedList<EventEntry<Pair<FlowId, Dpid>>>();
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 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800159 Collection<Pair<FlowId, Dpid>> flowIds =
160 datagridService.getAllFlowIds();
161 for (Pair<FlowId, Dpid> pair : flowIds) {
162 EventEntry<Pair<FlowId, Dpid>> eventEntry =
163 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800164 flowIdEvents.add(eventEntry);
165 }
166
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800167 //
168 // Obtain the initial FlowEntryId state
169 //
170 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
171 datagridService.getAllFlowEntryIds();
172 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
173 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
174 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
175 flowEntryIdEvents.add(eventEntry);
176 }
177
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800178 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800179 synchronized (allFlowPaths) {
180 processEvents();
181 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800182 }
183
184 /**
185 * Run the thread.
186 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800187 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800188 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800189 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800190 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700191
192 //
193 // The main loop
194 //
195 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
196 try {
197 while (true) {
198 EventEntry<?> eventEntry = networkEvents.take();
199 collection.add(eventEntry);
200 networkEvents.drainTo(collection);
201
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700202 //
203 // Demultiplex all events:
204 // - EventEntry<TopologyElement>
205 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700206 // - EventEntry<FlowEntry>
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800207 // - EventEntry<Pair<FlowId, Dpid>>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800208 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700209 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700210 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800211 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700212 if (event.eventData() instanceof TopologyElement) {
213 EventEntry<TopologyElement> topologyEventEntry =
214 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800215
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700216 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800217 continue;
218 }
219
220 // FlowPath event
221 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700222 EventEntry<FlowPath> flowPathEventEntry =
223 (EventEntry<FlowPath>)event;
224 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800225 continue;
226 }
227
228 // FlowEntry event
229 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700230 EventEntry<FlowEntry> flowEntryEventEntry =
231 (EventEntry<FlowEntry>)event;
232 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800233 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700234 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800235
236 // FlowId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800237 if (event.eventData() instanceof Pair) {
238 EventEntry<Pair<FlowId, Dpid>> flowIdEventEntry =
239 (EventEntry<Pair<FlowId, Dpid>>)event;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800240 flowIdEvents.add(flowIdEventEntry);
241 continue;
242 }
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800243 // FlowEntryId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800244 // TODO: Fix the code below if we need again to handle
245 // the FlowEntryId events
246 /*
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800247 if (event.eventData() instanceof Pair) {
248 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
249 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
250 flowEntryIdEvents.add(flowEntryIdEventEntry);
251 continue;
252 }
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800253 */
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700254 }
255 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700256
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700257 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800258 synchronized (allFlowPaths) {
259 processEvents();
260 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700261 }
262 } catch (Exception exception) {
263 log.debug("Exception processing Network Events: ", exception);
264 }
265 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800266
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700267 /**
268 * Process the events (if any)
269 */
270 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800271 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700272
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800273 if (enableOnrc2014MeasurementsFlows) {
274
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800275 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800276 return; // Nothing to do
277 }
278
279 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
280
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800281 // Process the Flow ID events
282 processFlowIdEvents(mySwitches);
283
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800284 // Fetch the topology
285 processTopologyEvents();
286
287 // Recompute all affected Flow Paths and keep only the modified
288 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
289 if (recomputeFlowPath(flowPath))
290 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
291 }
292
293 // Assign the Flow Entry ID as needed
294 for (FlowPath flowPath : modifiedFlowPaths.values()) {
295 for (FlowEntry flowEntry : flowPath.flowEntries()) {
296 if (! flowEntry.isValidFlowEntryId()) {
297 long id = flowManager.getNextFlowEntryId();
298 flowEntry.setFlowEntryId(new FlowEntryId(id));
299 }
300 }
301 }
302
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800303 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800304 // Push the modified state to the database
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800305 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800306 flowManager.writeModifiedFlowPathsToDatabase(modifiedFlowPaths.values());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800307
308 // Cleanup
309 topologyEvents.clear();
310 flowIdEvents.clear();
311 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800312 // NOTE: Keep a cache with my Flow Paths
313 // allFlowPaths.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800314 shouldRecomputeFlowPaths.clear();
315 modifiedFlowPaths.clear();
316
317 return;
318 }
319
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700320 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800321 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700322 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700323 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700324
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800325 processFlowPathEvents();
326 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800327 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800328 processFlowEntryEvents();
329
330 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800331 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800332 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800333 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800334 }
335
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800336 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800337 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800338
339 // Assign missing Flow Entry IDs
340 assignFlowEntryId(modifiedFlowEntries);
341
342 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800343 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800344 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800345 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
346 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800347
348 //
349 // Remove Flow Entries that were deleted
350 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800351 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800352 flowPath.dataPath().removeDeletedFlowEntries();
353
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800354 //
355 // Check if Flow Paths have been installed into all switches,
356 // and generate the appropriate events.
357 //
358 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
359
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800360 // Cleanup
361 topologyEvents.clear();
362 flowPathEvents.clear();
363 flowEntryEvents.clear();
364 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800365 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800366 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800367 checkIfInstalledFlowPaths.clear();
368 }
369
370 /**
371 * Check if Flow Paths have been installed into all switches,
372 * and generate the appropriate events.
373 *
374 * @param flowPaths the flowPaths to process.
375 */
376 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
377 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
378
379 Kryo kryo = kryoFactory.newKryo();
380
381 for (FlowPath flowPath : flowPaths) {
382 boolean isInstalled = true;
383
384 //
385 // Check whether all Flow Entries have been installed
386 //
387 for (FlowEntry flowEntry : flowPath.flowEntries()) {
388 if (flowEntry.flowEntrySwitchState() !=
389 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
390 isInstalled = false;
391 break;
392 }
393 }
394
395 if (isInstalled) {
396 // Create a copy and add it to the list
397 FlowPath copyFlowPath = kryo.copy(flowPath);
398 installedFlowPaths.add(copyFlowPath);
399 }
400 }
401 kryoFactory.deleteKryo(kryo);
402
403 // Generate an event for the installed Flow Path.
404 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800405 }
406
407 /**
408 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800409 *
410 * @param modifiedFlowPaths the Flow Paths to process.
411 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800412 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800413 private Collection<FlowEntry> extractModifiedFlowEntries(
414 Collection<FlowPath> modifiedFlowPaths) {
415 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800416
417 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800418 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800419 for (FlowEntry flowEntry : flowPath.flowEntries()) {
420 if (flowEntry.flowEntrySwitchState() ==
421 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800422 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800423 }
424 }
425 }
426 return modifiedFlowEntries;
427 }
428
429 /**
430 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800431 *
432 * @param modifiedFlowEnries the collection of Flow Entries that need
433 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800434 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800435 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800436 if (modifiedFlowEntries.isEmpty())
437 return;
438
439 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
440
441 //
442 // Assign the Flow Entry ID only for Flow Entries for my switches
443 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800444 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800445 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
446 if (mySwitch == null)
447 continue;
448 if (! flowEntry.isValidFlowEntryId()) {
449 long id = flowManager.getNextFlowEntryId();
450 flowEntry.setFlowEntryId(new FlowEntryId(id));
451 }
452 }
453 }
454
455 /**
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800456 * Fix a flow fetched from the database.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800457 *
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800458 * @param flowPath the Flow to fix.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800459 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800460 private void fixFlowFromDatabase(FlowPath flowPath) {
461 //
462 // TODO: Bug workaround / fix :
463 // method FlowDatabaseOperation.extractFlowEntry() doesn't
464 // fetch the inPort and outPort, hence we assign them here.
465 //
466 // Assign the inPort and outPort for the Flow Entries
467 for (FlowEntry flowEntry : flowPath.flowEntries()) {
468 // Set the inPort
469 do {
470 if (flowEntry.inPort() != null)
471 break;
472 if (flowEntry.flowEntryMatch() == null)
473 break;
474 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
475 flowEntry.setInPort(inPort);
476 } while (false);
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800477
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800478 // Set the outPort
479 do {
480 if (flowEntry.outPort() != null)
481 break;
482 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
483 if (fa.actionOutput() != null) {
484 Port outPort = new Port(fa.actionOutput().port().value());
485 flowEntry.setOutPort(outPort);
486 break;
487 }
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800488 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800489 } while (false);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800490 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800491 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800492
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800493 /**
494 * Process the Flow ID events.
495 *
496 * @param mySwitches the collection of my switches.
497 */
498 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800499 List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
500
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800501 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800502 // Process all Flow Id events and update the appropriate state
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800503 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800504 for (EventEntry<Pair<FlowId, Dpid>> eventEntry : flowIdEvents) {
505 Pair<FlowId, Dpid> pair = eventEntry.eventData();
506 FlowId flowId = pair.first;
507 Dpid dpid = pair.second;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800508
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800509 log.debug("Flow ID Event: {} {} {}", eventEntry.eventType(),
510 flowId, dpid);
511
512 //
513 // Ignore Flows if the Source Switch is not controlled by this
514 // instance.
515 //
516 if (mySwitches.get(dpid.value()) == null)
517 continue;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800518
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800519 switch (eventEntry.eventType()) {
520 case ENTRY_ADD: {
521 //
522 // Add a new Flow Path
523 //
524 if (allFlowPaths.get(flowId.value()) != null) {
525 //
526 // TODO: What to do if the Flow Path already exists?
527 // Fow now, we just re-add it.
528 //
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800529 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800530 shouldFetchMyFlowIds.add(flowId);
531
532 break;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800533 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800534
535 case ENTRY_REMOVE: {
536 //
537 // Remove an existing Flow Path.
538 //
539 // Find the Flow Path, and mark the Flow and its Flow Entries
540 // for deletion.
541 //
542 FlowPath existingFlowPath =
543 allFlowPaths.get(flowId.value());
544 if (existingFlowPath == null)
545 continue; // Nothing to do
546
547 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
548 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
549 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
550 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
551 }
552
553 // Remove the Flow Path from the internal state
554 Long key = existingFlowPath.flowId().value();
555 allFlowPaths.remove(key);
556 shouldRecomputeFlowPaths.remove(key);
557 modifiedFlowPaths.put(key, existingFlowPath);
558
559 break;
560 }
561 }
562 }
563
564 // Get my Flows
565 Collection<FlowPath> myFlows =
566 FlowDatabaseOperation.getFlows(dbHandler, shouldFetchMyFlowIds);
567
568 for (FlowPath flowPath : myFlows) {
569 fixFlowFromDatabase(flowPath);
570
571 switch (flowPath.flowPathType()) {
572 case FP_TYPE_SHORTEST_PATH:
573 //
574 // Reset the Data Path, in case it was set already, because
575 // we are going to recompute it anyway.
576 //
577 flowPath.flowEntries().clear();
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800578 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
579 flowPath);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800580 break;
581 case FP_TYPE_EXPLICIT_PATH:
582 //
583 // Mark all Flow Entries for installation in the switches.
584 //
585 for (FlowEntry flowEntry : flowPath.flowEntries()) {
586 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
587 }
588 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
589 break;
590 case FP_TYPE_UNKNOWN:
591 log.error("FlowPath event with unknown type");
592 break;
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800593 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800594 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800595 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800596 }
597
598 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800599 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800600 *
601 * @param mySwitches the collection of my switches.
602 * @return a collection of modified Flow Entries this instance needs
603 * to push to its own switches.
604 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800605 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800606 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
607
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800608 //
609 // Process all Flow ID events and update the appropriate state
610 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800611 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
612 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
613 FlowEntryId flowEntryId = pair.first;
614 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800615
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800616 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
617 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800618
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800619 if (mySwitches.get(dpid.value()) == null)
620 continue;
621
622 // Fetch the Flow Entry
623 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
624 flowEntryId);
625 if (flowEntry == null) {
626 log.debug("Flow Entry ID {} : Flow Entry not found!",
627 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800628 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800629 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800630 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800631 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800632
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800633 return modifiedFlowEntries;
634 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800635
636 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800637 * Process the Flow Path events.
638 */
639 private void processFlowPathEvents() {
640 //
641 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700642 //
643 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
644 FlowPath flowPath = eventEntry.eventData();
645
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800646 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800647
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700648 switch (eventEntry.eventType()) {
649 case ENTRY_ADD: {
650 //
651 // Add a new Flow Path
652 //
653 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
654 //
655 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800656 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700657 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700658 }
659
660 switch (flowPath.flowPathType()) {
661 case FP_TYPE_SHORTEST_PATH:
662 //
663 // Reset the Data Path, in case it was set already, because
664 // we are going to recompute it anyway.
665 //
666 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800667 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
668 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700669 break;
670 case FP_TYPE_EXPLICIT_PATH:
671 //
672 // Mark all Flow Entries for installation in the switches.
673 //
674 for (FlowEntry flowEntry : flowPath.flowEntries()) {
675 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
676 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800677 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700678 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800679 case FP_TYPE_UNKNOWN:
680 log.error("FlowPath event with unknown type");
681 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700682 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800683 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700684
685 break;
686 }
687
688 case ENTRY_REMOVE: {
689 //
690 // Remove an existing Flow Path.
691 //
692 // Find the Flow Path, and mark the Flow and its Flow Entries
693 // for deletion.
694 //
695 FlowPath existingFlowPath =
696 allFlowPaths.get(flowPath.flowId().value());
697 if (existingFlowPath == null)
698 continue; // Nothing to do
699
700 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
701 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
702 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
703 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
704 }
705
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800706 // Remove the Flow Path from the internal state
707 Long key = existingFlowPath.flowId().value();
708 allFlowPaths.remove(key);
709 shouldRecomputeFlowPaths.remove(key);
710 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700711
712 break;
713 }
714 }
715 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800716 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700717
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800718 /**
719 * Process the Topology events.
720 */
721 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800722 boolean isTopologyModified = false;
723
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800724 if (enableOnrc2014MeasurementsTopology) {
725 if (topologyEvents.isEmpty())
726 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800727
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800728 // TODO: Code for debugging purpose only
729 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
730 TopologyElement topologyElement = eventEntry.eventData();
731 log.debug("Topology Event: {} {}", eventEntry.eventType(),
732 topologyElement.toString());
733 }
734
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800735 log.debug("[BEFORE] {}", topology.toString());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800736 topology.readFromDatabase(dbHandler);
737 log.debug("[AFTER] {}", topology.toString());
738 shouldRecomputeFlowPaths.putAll(allFlowPaths);
739 return;
740 }
741
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700742 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800743 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700744 //
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800745 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
746 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800747
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800748 log.debug("Topology Event: {} {}", eventEntry.eventType(),
749 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800750
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800751 switch (eventEntry.eventType()) {
752 case ENTRY_ADD:
Naoki Shiota9f6fc212014-01-09 21:38:08 -0800753 isTopologyModified |= topology.addTopologyElement(topologyElement);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800754 break;
755 case ENTRY_REMOVE:
Naoki Shiota9f6fc212014-01-09 21:38:08 -0800756 isTopologyModified |= topology.removeTopologyElement(topologyElement);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800757 break;
758 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700759 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700760 if (isTopologyModified) {
761 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800762 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700763 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800764 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700765
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800766 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800767 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800768 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800769 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800770 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800771 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800772
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700773 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800774 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700775 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800776 if (! unmatchedFlowEntryAdd.isEmpty()) {
777 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
778 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800779 // log.debug("Processing Unmatched Flow Entry: {}",
780 // flowEntry.toString());
781
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800782 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800783 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800784 remainingUpdates.put(flowEntry.flowEntryId().value(),
785 flowEntry);
786 continue;
787 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800788 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
789 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800790 remainingUpdates.put(flowEntry.flowEntryId().value(),
791 flowEntry);
792 continue;
793 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800794 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
795 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
796 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700797 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800798 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700799 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800800 }
801
802 /**
803 * Process the Flow Entry events.
804 */
805 private void processFlowEntryEvents() {
806 FlowPath flowPath;
807 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700808
809 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800810 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700811 //
812 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
813 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800814
815 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800816 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800817
818 if ((! flowEntry.isValidFlowId()) ||
819 (! flowEntry.isValidFlowEntryId())) {
820 continue;
821 }
822
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700823 switch (eventEntry.eventType()) {
824 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800825 flowPath = allFlowPaths.get(flowEntry.flowId().value());
826 if (flowPath == null) {
827 // Flow Path not found: keep the entry for later matching
828 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
829 flowEntry);
830 break;
831 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800832 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
833 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800834 // Flow Entry not found: keep the entry for later matching
835 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
836 flowEntry);
837 break;
838 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800839 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
840 // Add the updated Flow Path to the list of updated paths
841 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
842 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700843 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800844
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700845 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800846 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
847 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800848 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800849 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800850
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800851 flowPath = allFlowPaths.get(flowEntry.flowId().value());
852 if (flowPath == null) {
853 // Flow Path not found: ignore the update
854 break;
855 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800856 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
857 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800858 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800859 break;
860 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800861 if (updateFlowEntryRemove(flowPath, localFlowEntry,
862 flowEntry)) {
863 // Add the updated Flow Path to the list of updated paths
864 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
865 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700866 break;
867 }
868 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700869 }
870
871 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800872 * Find a Flow Entry that should be updated because of an external
873 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700874 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800875 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800876 * @param newFlowEntry the FlowEntry with the new state.
877 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700878 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800879 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
880 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700881 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800882 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700883 //
884 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800885 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800886 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700887 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800888 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700889
890 //
891 // Local Flow Entry match found
892 //
893 if (localFlowEntry.isValidFlowEntryId()) {
894 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800895 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700896 //
897 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800898 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700899 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800900 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700901 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700902 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800903 return localFlowEntry;
904 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700905
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800906 return null; // Entry not found
907 }
908
909 /**
910 * Update a Flow Entry because of an external ENTRY_ADD event.
911 *
912 * @param flowPath the FlowPath for the Flow Entry to update.
913 * @param localFlowEntry the local Flow Entry to update.
914 * @param newFlowEntry the FlowEntry with the new state.
915 * @return true if the local Flow Entry was updated, otherwise false.
916 */
917 private boolean updateFlowEntryAdd(FlowPath flowPath,
918 FlowEntry localFlowEntry,
919 FlowEntry newFlowEntry) {
920 boolean updated = false;
921
922 if (localFlowEntry.flowEntryUserState() ==
923 FlowEntryUserState.FE_USER_DELETE) {
924 // Don't add-back a Flow Entry that is already deleted
925 return false;
926 }
927
928 if (! localFlowEntry.isValidFlowEntryId()) {
929 // Update the Flow Entry ID
930 FlowEntryId flowEntryId =
931 new FlowEntryId(newFlowEntry.flowEntryId().value());
932 localFlowEntry.setFlowEntryId(flowEntryId);
933 updated = true;
934 }
935
936 //
937 // Update the local Flow Entry, and keep state to check
938 // if the Flow Path has been installed.
939 //
940 if (localFlowEntry.flowEntryUserState() !=
941 newFlowEntry.flowEntryUserState()) {
942 localFlowEntry.setFlowEntryUserState(
943 newFlowEntry.flowEntryUserState());
944 updated = true;
945 }
946 if (localFlowEntry.flowEntrySwitchState() !=
947 newFlowEntry.flowEntrySwitchState()) {
948 localFlowEntry.setFlowEntrySwitchState(
949 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800950 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800951 updated = true;
952 }
953
954 return updated;
955 }
956
957 /**
958 * Find a Flow Entry that should be updated because of an external
959 * ENTRY_REMOVE event.
960 *
961 * @param flowPath the FlowPath for the Flow Entry to update.
962 * @param newFlowEntry the FlowEntry with the new state.
963 * @return the Flow Entry that should be updated if found, otherwise null.
964 */
965 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
966 FlowEntry newFlowEntry) {
967 //
968 // Iterate over all Flow Entries and find a match based on
969 // the Flow Entry ID.
970 //
971 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
972 if (! localFlowEntry.isValidFlowEntryId())
973 continue;
974 if (localFlowEntry.flowEntryId().value() !=
975 newFlowEntry.flowEntryId().value()) {
976 continue;
977 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800978 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700979 }
980
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800981 return null; // Entry not found
982 }
983
984 /**
985 * Update a Flow Entry because of an external ENTRY_REMOVE event.
986 *
987 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800988 * @param localFlowEntry the local Flow Entry to update.
989 * @param newFlowEntry the FlowEntry with the new state.
990 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800991 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800992 private boolean updateFlowEntryRemove(FlowPath flowPath,
993 FlowEntry localFlowEntry,
994 FlowEntry newFlowEntry) {
995 boolean updated = false;
996
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800997 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800998 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800999 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001000 if (localFlowEntry.flowEntryUserState() !=
1001 newFlowEntry.flowEntryUserState()) {
1002 localFlowEntry.setFlowEntryUserState(
1003 newFlowEntry.flowEntryUserState());
1004 updated = true;
1005 }
1006 if (localFlowEntry.flowEntrySwitchState() !=
1007 newFlowEntry.flowEntrySwitchState()) {
1008 localFlowEntry.setFlowEntrySwitchState(
1009 newFlowEntry.flowEntrySwitchState());
1010 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001011 }
1012
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001013 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001014 }
1015
1016 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001017 * Recompute a Flow Path.
1018 *
1019 * @param flowPath the Flow Path to recompute.
1020 * @return true if the recomputed Flow Path has changed, otherwise false.
1021 */
1022 private boolean recomputeFlowPath(FlowPath flowPath) {
1023 boolean hasChanged = false;
1024
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001025 if (enableOnrc2014MeasurementsFlows) {
1026 // Cleanup the deleted Flow Entries from the earlier iteration
1027 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -08001028
1029 //
1030 // TODO: Fake it that the Flow Entries have been already pushed
1031 // into the switches, so we don't push them again.
1032 //
1033 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1034 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1035 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001036 }
1037
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001038 //
1039 // Test whether the Flow Path needs to be recomputed
1040 //
1041 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001042 case FP_TYPE_UNKNOWN:
1043 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001044 case FP_TYPE_SHORTEST_PATH:
1045 break;
1046 case FP_TYPE_EXPLICIT_PATH:
1047 return false; // An explicit path never changes
1048 }
1049
1050 DataPath oldDataPath = flowPath.dataPath();
1051
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001052 // Compute the new path
Naoki Shiota9f6fc212014-01-09 21:38:08 -08001053 DataPath newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001054 flowPath);
Naoki Shiotaf74d5f32014-01-09 21:29:38 -08001055
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001056 if (newDataPath == null) {
1057 // We need the DataPath to compare the paths
1058 newDataPath = new DataPath();
1059 }
1060 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1061
1062 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001063 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001064 //
1065 if (oldDataPath.flowEntries().size() !=
1066 newDataPath.flowEntries().size()) {
1067 hasChanged = true;
1068 } else {
1069 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1070 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1071 while (oldIter.hasNext() && newIter.hasNext()) {
1072 FlowEntry oldFlowEntry = oldIter.next();
1073 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001074 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1075 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001076 hasChanged = true;
1077 break;
1078 }
1079 }
1080 }
1081 if (! hasChanged)
1082 return hasChanged;
1083
1084 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001085 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001086 // - If a Flow Entry for a switch is in the old data path, but not
1087 // in the new data path, then mark it for deletion.
1088 // - If a Flow Entry for a switch is in the new data path, but not
1089 // in the old data path, then mark it for addition.
1090 // - If a Flow Entry for a switch is in both the old and the new
1091 // data path, but it has changed, e.g., the incoming and/or outgoing
1092 // port(s), then mark the old Flow Entry for deletion, and mark
1093 // the new Flow Entry for addition.
1094 // - If a Flow Entry for a switch is in both the old and the new
1095 // data path, and it hasn't changed, then just keep it.
1096 //
1097 // NOTE: We use the Switch DPID of each entry to match the entries
1098 //
1099 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1100 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1101 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1102 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1103
1104 // Prepare maps with the Flow Entries, so they are fast to lookup
1105 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1106 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1107 for (FlowEntry flowEntry : newDataPath.flowEntries())
1108 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1109
1110 //
1111 // Find the old Flow Entries that should be deleted
1112 //
1113 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1114 FlowEntry newFlowEntry =
1115 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1116 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001117 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001118 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1119 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1120 deletedFlowEntries.add(oldFlowEntry);
1121 }
1122 }
1123
1124 //
1125 // Find the new Flow Entries that should be added or updated
1126 //
1127 int idx = 0;
1128 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1129 FlowEntry oldFlowEntry =
1130 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1131
1132 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001133 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1134 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001135 //
1136 // Both Flow Entries are same
1137 //
1138 finalFlowEntries.add(oldFlowEntry);
1139 idx++;
1140 continue;
1141 }
1142
1143 if (oldFlowEntry != null) {
1144 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001145 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001146 //
1147 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1148 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1149 deletedFlowEntries.add(oldFlowEntry);
1150 }
1151
1152 //
1153 // Add the new Flow Entry
1154 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001155 //
1156 // NOTE: Assign only the Flow ID.
1157 // The Flow Entry ID is assigned later only for the Flow Entries
1158 // this instance is responsible for.
1159 //
1160 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001161
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001162 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001163 // Copy the Flow timeouts
1164 //
1165 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1166 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1167
1168 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001169 // Allocate the FlowEntryMatch by copying the default one
1170 // from the FlowPath (if set).
1171 //
1172 FlowEntryMatch flowEntryMatch = null;
1173 if (flowPath.flowEntryMatch() != null)
1174 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1175 else
1176 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001177 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001178
1179 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001180 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1181
1182 //
1183 // Set the actions:
1184 // If the first Flow Entry, copy the Flow Path actions to it.
1185 //
1186 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1187 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1188 FlowEntryActions flowActions =
1189 new FlowEntryActions(flowPath.flowEntryActions());
1190 for (FlowEntryAction action : flowActions.actions())
1191 flowEntryActions.addAction(action);
1192 }
1193 idx++;
1194
1195 //
1196 // Add the outgoing port output action
1197 //
1198 FlowEntryAction flowEntryAction = new FlowEntryAction();
1199 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1200 flowEntryActions.addAction(flowEntryAction);
1201
1202 //
1203 // Set the state of the new Flow Entry
1204 //
1205 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1206 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1207 finalFlowEntries.add(newFlowEntry);
1208 }
1209
1210 //
1211 // Replace the old Flow Entries with the new Flow Entries.
1212 // Note that the Flow Entries that will be deleted are added at
1213 // the end.
1214 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001215 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001216 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1217
1218 return hasChanged;
1219 }
1220
1221 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001222 * Receive a notification that a Flow is added.
1223 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001224 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001225 */
1226 @Override
1227 public void notificationRecvFlowAdded(FlowPath flowPath) {
1228 EventEntry<FlowPath> eventEntry =
1229 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1230 networkEvents.add(eventEntry);
1231 }
1232
1233 /**
1234 * Receive a notification that a Flow is removed.
1235 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001236 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001237 */
1238 @Override
1239 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1240 EventEntry<FlowPath> eventEntry =
1241 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1242 networkEvents.add(eventEntry);
1243 }
1244
1245 /**
1246 * Receive a notification that a Flow is updated.
1247 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001248 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001249 */
1250 @Override
1251 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1252 // NOTE: The ADD and UPDATE events are processed in same way
1253 EventEntry<FlowPath> eventEntry =
1254 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1255 networkEvents.add(eventEntry);
1256 }
1257
1258 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001259 * Receive a notification that a FlowEntry is added.
1260 *
1261 * @param flowEntry the FlowEntry that is added.
1262 */
1263 @Override
1264 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001265 if (enableOnrc2014MeasurementsFlows) {
1266 Collection entries = new ArrayList();
1267 entries.add(flowEntry);
1268 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1269 return;
1270 }
1271
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001272 EventEntry<FlowEntry> eventEntry =
1273 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1274 networkEvents.add(eventEntry);
1275 }
1276
1277 /**
1278 * Receive a notification that a FlowEntry is removed.
1279 *
1280 * @param flowEntry the FlowEntry that is removed.
1281 */
1282 @Override
1283 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001284 if (enableOnrc2014MeasurementsFlows) {
Pavlin Radoslavove4d2a432014-01-10 12:01:08 -08001285 //
1286 // NOTE: Must update the state to DELETE, because
1287 // the notification contains the original state.
1288 //
1289 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1290
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001291 Collection entries = new ArrayList();
1292 entries.add(flowEntry);
1293 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1294 return;
1295 }
1296
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001297 EventEntry<FlowEntry> eventEntry =
1298 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1299 networkEvents.add(eventEntry);
1300 }
1301
1302 /**
1303 * Receive a notification that a FlowEntry is updated.
1304 *
1305 * @param flowEntry the FlowEntry that is updated.
1306 */
1307 @Override
1308 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001309 if (enableOnrc2014MeasurementsFlows) {
1310 Collection entries = new ArrayList();
1311 entries.add(flowEntry);
1312 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1313 return;
1314 }
1315
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001316 // NOTE: The ADD and UPDATE events are processed in same way
1317 EventEntry<FlowEntry> eventEntry =
1318 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1319 networkEvents.add(eventEntry);
1320 }
1321
1322 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001323 * Receive a notification that a FlowId is added.
1324 *
1325 * @param flowId the FlowId that is added.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001326 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001327 */
1328 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001329 public void notificationRecvFlowIdAdded(FlowId flowId, Dpid dpid) {
1330 Pair flowIdPair = new Pair(flowId, dpid);
1331
1332 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1333 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001334 networkEvents.add(eventEntry);
1335 }
1336
1337 /**
1338 * Receive a notification that a FlowId is removed.
1339 *
1340 * @param flowId the FlowId that is removed.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001341 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001342 */
1343 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001344 public void notificationRecvFlowIdRemoved(FlowId flowId, Dpid dpid) {
1345 Pair flowIdPair = new Pair(flowId, dpid);
1346
1347 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1348 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001349 networkEvents.add(eventEntry);
1350 }
1351
1352 /**
1353 * Receive a notification that a FlowId is updated.
1354 *
1355 * @param flowId the FlowId that is updated.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001356 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001357 */
1358 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001359 public void notificationRecvFlowIdUpdated(FlowId flowId, Dpid dpid) {
1360 Pair flowIdPair = new Pair(flowId, dpid);
1361
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001362 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001363 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1364 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001365 networkEvents.add(eventEntry);
1366 }
1367
1368 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001369 * Receive a notification that a FlowEntryId is added.
1370 *
1371 * @param flowEntryId the FlowEntryId that is added.
1372 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1373 */
1374 @Override
1375 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1376 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001377 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1378
1379 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1380 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001381 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001382 }
1383
1384 /**
1385 * Receive a notification that a FlowEntryId is removed.
1386 *
1387 * @param flowEntryId the FlowEntryId that is removed.
1388 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1389 */
1390 @Override
1391 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1392 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001393 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1394
1395 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1396 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001397 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001398 }
1399
1400 /**
1401 * Receive a notification that a FlowEntryId is updated.
1402 *
1403 * @param flowEntryId the FlowEntryId that is updated.
1404 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1405 */
1406 @Override
1407 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1408 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001409 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1410
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001411 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001412 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1413 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001414 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001415 }
1416
1417 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001418 * Receive a notification that a Topology Element is added.
1419 *
1420 * @param topologyElement the Topology Element that is added.
1421 */
1422 @Override
1423 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1424 EventEntry<TopologyElement> eventEntry =
1425 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1426 networkEvents.add(eventEntry);
1427 }
1428
1429 /**
1430 * Receive a notification that a Topology Element is removed.
1431 *
1432 * @param topologyElement the Topology Element that is removed.
1433 */
1434 @Override
1435 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1436 EventEntry<TopologyElement> eventEntry =
1437 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1438 networkEvents.add(eventEntry);
1439 }
1440
1441 /**
1442 * Receive a notification that a Topology Element is updated.
1443 *
1444 * @param topologyElement the Topology Element that is updated.
1445 */
1446 @Override
1447 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1448 // NOTE: The ADD and UPDATE events are processed in same way
1449 EventEntry<TopologyElement> eventEntry =
1450 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1451 networkEvents.add(eventEntry);
1452 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001453
1454 /**
1455 * Get a sorted copy of all Flow Paths.
1456 *
1457 * @return a sorted copy of all Flow Paths.
1458 */
1459 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1460 SortedMap<Long, FlowPath> sortedFlowPaths =
1461 new TreeMap<Long, FlowPath>();
1462
1463 //
1464 // TODO: For now we use serialization/deserialization to create
1465 // a copy of each Flow Path. In the future, we should use proper
1466 // copy constructors.
1467 //
1468 Kryo kryo = kryoFactory.newKryo();
1469 synchronized (allFlowPaths) {
1470 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1471 FlowPath origFlowPath = entry.getValue();
1472 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1473 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1474 }
1475 }
1476 kryoFactory.deleteKryo(kryo);
1477
1478 return sortedFlowPaths;
1479 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001480}