blob: fd1a8b198f68980d30b1d134f9fc0b9702996225 [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 Radoslavovcc757162014-01-10 16:26:38 -080016import net.floodlightcontroller.core.IOFSwitchListener;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070017import net.onrc.onos.datagrid.IDatagridService;
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -080018import net.onrc.onos.graph.DBOperation;
19import net.onrc.onos.graph.GraphDBManager;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070020import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070021import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070022import net.onrc.onos.ofcontroller.topology.TopologyManager;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070023import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080024import net.onrc.onos.ofcontroller.util.Dpid;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070025import net.onrc.onos.ofcontroller.util.EventEntry;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070026import net.onrc.onos.ofcontroller.util.FlowEntry;
27import net.onrc.onos.ofcontroller.util.FlowEntryAction;
28import net.onrc.onos.ofcontroller.util.FlowEntryActions;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070029import net.onrc.onos.ofcontroller.util.FlowEntryId;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070030import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
31import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
32import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070033import net.onrc.onos.ofcontroller.util.FlowId;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070034import net.onrc.onos.ofcontroller.util.FlowPath;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070035import net.onrc.onos.ofcontroller.util.FlowPathUserState;
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080036import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080037import net.onrc.onos.ofcontroller.util.Port;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080038import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -070039import net.onrc.onos.registry.controller.IControllerRegistryService;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080040
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -080041import com.esotericsoftware.kryo.Kryo;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070042import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
45/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070046 * Class for FlowPath Maintenance.
47 * This class listens for FlowEvents to:
48 * - Maintain a local cache of the Network Topology.
49 * - Detect FlowPaths impacted by Topology change.
50 * - Recompute impacted FlowPath using cached Topology.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070051 */
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080052class FlowEventHandler extends Thread implements IFlowEventHandlerService,
53 IOFSwitchListener {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080054
Matteo Gerola468ce632014-02-26 20:10:49 -080055 private boolean enableOnrc2014MeasurementsFlows = false;
56 private boolean enableOnrc2014MeasurementsTopology = false;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080057
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070058 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070059 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
TeruU417fe022014-02-04 12:59:30 -080060
TeruU6464af02014-02-06 21:38:45 -080061 private final int FLOW_IDLE_TIMEOUT_ADDED_SECONDS = 5;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070062
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -080063 private DBOperation dbHandler;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -080064
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070065 private FlowManager flowManager; // The Flow Manager to use
66 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -070067 private IControllerRegistryService registryService; // The Registry Service
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070068 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080069 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070070
71 // The queue with Flow Path and Topology Element updates
72 private BlockingQueue<EventEntry<?>> networkEvents =
73 new LinkedBlockingQueue<EventEntry<?>>();
74
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070075 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070076 private List<EventEntry<TopologyElement>> topologyEvents =
77 new LinkedList<EventEntry<TopologyElement>>();
78 private List<EventEntry<FlowPath>> flowPathEvents =
79 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070080 private List<EventEntry<FlowEntry>> flowEntryEvents =
81 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2194d112014-01-10 13:36:00 -080082 private List<EventEntry<Pair<FlowId, Dpid>>> flowIdEvents =
83 new LinkedList<EventEntry<Pair<FlowId, Dpid>>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080084 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
85 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080086 private List<EventEntry<Dpid>> switchDpidEvents =
87 new LinkedList<EventEntry<Dpid>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070088
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080089 // All internally computed Flow Paths
90 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
91
92 // The Flow Entries received as notifications with unmatched Flow Paths
93 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
94 new HashMap<Long, FlowEntry>();
95
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080096 //
97 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080098 // - The Flow Paths that should be recomputed
99 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800100 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800101 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800102 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
103 new HashMap<Long, FlowPath>();
104 private Map<Long, FlowPath> modifiedFlowPaths =
105 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800106 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
107 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800108
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700109 /**
110 * Constructor for a given Flow Manager and Datagrid Service.
111 *
112 * @param flowManager the Flow Manager to use.
113 * @param datagridService the Datagrid Service to use.
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700114 * @param registryService the Registry Service to use.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700115 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700116 FlowEventHandler(FlowManager flowManager,
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700117 IDatagridService datagridService,
118 IControllerRegistryService registryService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700119 this.flowManager = flowManager;
120 this.datagridService = datagridService;
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700121 this.registryService = registryService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700122 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700123 }
124
125 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800126 * Get the network topology.
127 *
128 * @return the network topology.
129 */
130 protected Topology getTopology() { return this.topology; }
131
132 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800133 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700134 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800135 private void startup() {
Yoshi Muroi5804ce92014-02-08 03:58:04 -0800136 this.dbHandler = GraphDBManager.getDBOperation();
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800137
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700138 //
139 // Obtain the initial Topology state
140 //
141 Collection<TopologyElement> topologyElements =
142 datagridService.getAllTopologyElements();
143 for (TopologyElement topologyElement : topologyElements) {
144 EventEntry<TopologyElement> eventEntry =
145 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
146 topologyEvents.add(eventEntry);
147 }
148 //
149 // Obtain the initial Flow Path state
150 //
151 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
152 for (FlowPath flowPath : flowPaths) {
153 EventEntry<FlowPath> eventEntry =
154 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
155 flowPathEvents.add(eventEntry);
156 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700157 //
158 // Obtain the initial FlowEntry state
159 //
160 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
161 for (FlowEntry flowEntry : flowEntries) {
162 EventEntry<FlowEntry> eventEntry =
163 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
164 flowEntryEvents.add(eventEntry);
165 }
166
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800167 //
168 // Obtain the initial FlowId state
169 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800170 Collection<Pair<FlowId, Dpid>> flowIds =
171 datagridService.getAllFlowIds();
172 for (Pair<FlowId, Dpid> pair : flowIds) {
173 EventEntry<Pair<FlowId, Dpid>> eventEntry =
174 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800175 flowIdEvents.add(eventEntry);
176 }
177
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800178 //
179 // Obtain the initial FlowEntryId state
180 //
181 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
182 datagridService.getAllFlowEntryIds();
183 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
184 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
185 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
186 flowEntryIdEvents.add(eventEntry);
187 }
188
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800189 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800190 synchronized (allFlowPaths) {
191 processEvents();
192 }
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800193
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800194 }
195
196 /**
197 * Run the thread.
198 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800199 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800200 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800201 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800202 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700203
204 //
205 // The main loop
206 //
207 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
208 try {
209 while (true) {
210 EventEntry<?> eventEntry = networkEvents.take();
211 collection.add(eventEntry);
212 networkEvents.drainTo(collection);
213
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700214 //
215 // Demultiplex all events:
216 // - EventEntry<TopologyElement>
217 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700218 // - EventEntry<FlowEntry>
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800219 // - EventEntry<Pair<FlowId, Dpid>>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800220 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700221 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700222 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800223 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700224 if (event.eventData() instanceof TopologyElement) {
225 EventEntry<TopologyElement> topologyEventEntry =
226 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800227
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700228 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800229 continue;
230 }
231
232 // FlowPath event
233 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700234 EventEntry<FlowPath> flowPathEventEntry =
235 (EventEntry<FlowPath>)event;
236 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800237 continue;
238 }
239
240 // FlowEntry event
241 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700242 EventEntry<FlowEntry> flowEntryEventEntry =
243 (EventEntry<FlowEntry>)event;
244 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800245 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700246 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800247
248 // FlowId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800249 if (event.eventData() instanceof Pair) {
250 EventEntry<Pair<FlowId, Dpid>> flowIdEventEntry =
251 (EventEntry<Pair<FlowId, Dpid>>)event;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800252 flowIdEvents.add(flowIdEventEntry);
253 continue;
254 }
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800255
256 // Switch Dpid event
257 if (event.eventData() instanceof Dpid) {
258 EventEntry<Dpid> switchDpidEventEntry =
259 (EventEntry<Dpid>)event;
260 switchDpidEvents.add(switchDpidEventEntry);
261 continue;
262 }
263
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800264 // FlowEntryId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800265 // TODO: Fix the code below if we need again to handle
266 // the FlowEntryId events
267 /*
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800268 if (event.eventData() instanceof Pair) {
269 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
270 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
271 flowEntryIdEvents.add(flowEntryIdEventEntry);
272 continue;
273 }
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800274 */
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700275 }
276 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700277
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700278 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800279 synchronized (allFlowPaths) {
280 processEvents();
281 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700282 }
283 } catch (Exception exception) {
284 log.debug("Exception processing Network Events: ", exception);
285 }
286 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800287
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700288 /**
289 * Process the events (if any)
290 */
291 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800292 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700293
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800294 if (enableOnrc2014MeasurementsFlows) {
295
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800296 PerformanceMonitor.start("EventHandler.ProcessAllEvents");
297
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800298 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
299 switchDpidEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800300 return; // Nothing to do
301 }
302
303 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
304
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800305 // Process the Switch Dpid events
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800306 PerformanceMonitor.start("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800307 processSwitchDpidEvents();
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800308 PerformanceMonitor.stop("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800309
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800310 // Process the Flow ID events
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800311 PerformanceMonitor.start("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800312 processFlowIdEvents(mySwitches);
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800313 PerformanceMonitor.stop("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800314
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800315 // Fetch the topology
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800316 PerformanceMonitor.start("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800317 processTopologyEvents();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800318 PerformanceMonitor.stop("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800319
320 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800321 PerformanceMonitor.start("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800322 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
323 if (recomputeFlowPath(flowPath))
324 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
325 }
326
327 // Assign the Flow Entry ID as needed
328 for (FlowPath flowPath : modifiedFlowPaths.values()) {
329 for (FlowEntry flowEntry : flowPath.flowEntries()) {
330 if (! flowEntry.isValidFlowEntryId()) {
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700331 long id = registryService.getNextUniqueId();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800332 flowEntry.setFlowEntryId(new FlowEntryId(id));
333 }
334 }
335 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800336 PerformanceMonitor.stop("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800337
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800338 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800339 // Push the modified state to the database
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800340 //
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800341 PerformanceMonitor.start("EventHandler.WriteFlowsToDb");
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800342 for (FlowPath flowPath : modifiedFlowPaths.values()) {
343 //
344 // Delete the Flow Path from the Network Map
345 //
346 if (flowPath.flowPathUserState() ==
347 FlowPathUserState.FP_USER_DELETE) {
348 log.debug("Deleting Flow Path From Database: {}", flowPath);
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800349 // TODO: For now the deleting of a Flow Path is blocking
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800350 ParallelFlowDatabaseOperation.deleteFlow(dbHandler,
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800351 flowPath.flowId());
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800352 //
353 // NOTE: For now the sending of the notifications
354 // is outside of this loop, so the performance measurements
355 // are more accurate.
356 //
357 /*
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800358 // Send the notifications for the deleted Flow Entries
359 for (FlowEntry flowEntry : flowPath.flowEntries()) {
360 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
361 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800362 */
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800363
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800364 continue;
365 }
366
367 log.debug("Pushing Flow Path To Database: {}", flowPath);
368 //
369 // Write the Flow Path to the Network Map
370 //
371 ParallelFlowDatabaseOperation.addFlow(dbHandler, flowPath,
372 datagridService);
373 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800374 PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
375
376 //
377 // Send the notifications for the deleted Flow Entries
378 // NOTE: This code was pulled outside of the above loop,
379 // so the performance measurements are more accurate.
380 //
381 PerformanceMonitor.start("EventHandler.NotificationSend.FlowEntryRemoved");
382 for (FlowPath flowPath : modifiedFlowPaths.values()) {
383 if (flowPath.flowPathUserState() ==
384 FlowPathUserState.FP_USER_DELETE) {
385 for (FlowEntry flowEntry : flowPath.flowEntries()) {
386 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
387 }
388 }
389 }
Pavlin Radoslavovdbd09cc2014-01-12 18:13:35 -0800390 PerformanceMonitor.stop("EventHandler.NotificationSend.FlowEntryRemoved");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800391
392 // Cleanup
393 topologyEvents.clear();
394 flowIdEvents.clear();
Pavlin Radoslavov2d6e5f12014-01-10 16:34:05 -0800395 switchDpidEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800396 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800397 // NOTE: Keep a cache with my Flow Paths
398 // allFlowPaths.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800399 shouldRecomputeFlowPaths.clear();
400 modifiedFlowPaths.clear();
401
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800402 PerformanceMonitor.stop("EventHandler.ProcessAllEvents");
Pavlin Radoslavov8bd6d112014-01-12 20:12:37 -0800403
404
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800405// PerformanceMonitor.report("EventHandler.SwitchDpidEvents");
406// PerformanceMonitor.report("EventHandler.FlowIdEvents");
407// PerformanceMonitor.report("EventHandler.ReadTopology");
408// PerformanceMonitor.report("EventHandler.RecomputeFlows");
409// PerformanceMonitor.report("EventHandler.WriteFlowsToDb");
410// PerformanceMonitor.report("EventHandler.NotificationSend.FlowEntryRemoved");
411// PerformanceMonitor.report("EventHandler.ProcessAllEvents");
Brian O'Connor0d9963f2014-01-14 14:44:21 -0800412// PerformanceMonitor.report();
413// PerformanceMonitor.clear();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800414
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800415 return;
416 }
417
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700418 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
419 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700420 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700421 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700422
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800423 processFlowPathEvents();
424 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800425 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800426 processFlowEntryEvents();
427
428 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800429 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800430 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800431 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800432 }
433
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800434 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800435 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800436
437 // Assign missing Flow Entry IDs
438 assignFlowEntryId(modifiedFlowEntries);
439
440 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800441 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800442 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800443 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
444 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800445
446 //
447 // Remove Flow Entries that were deleted
448 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800449 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800450 flowPath.dataPath().removeDeletedFlowEntries();
451
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800452 //
453 // Check if Flow Paths have been installed into all switches,
454 // and generate the appropriate events.
455 //
456 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
457
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800458 // Cleanup
459 topologyEvents.clear();
460 flowPathEvents.clear();
461 flowEntryEvents.clear();
462 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800463 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800464 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800465 checkIfInstalledFlowPaths.clear();
466 }
467
468 /**
469 * Check if Flow Paths have been installed into all switches,
470 * and generate the appropriate events.
471 *
472 * @param flowPaths the flowPaths to process.
473 */
474 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
475 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
476
477 Kryo kryo = kryoFactory.newKryo();
478
479 for (FlowPath flowPath : flowPaths) {
480 boolean isInstalled = true;
Jonathan Hart0444d932014-01-22 15:06:17 -0800481
482 if (flowPath.flowEntries().isEmpty()) {
483 continue;
484 }
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800485
486 //
487 // Check whether all Flow Entries have been installed
488 //
489 for (FlowEntry flowEntry : flowPath.flowEntries()) {
490 if (flowEntry.flowEntrySwitchState() !=
491 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
492 isInstalled = false;
493 break;
494 }
495 }
496
497 if (isInstalled) {
498 // Create a copy and add it to the list
499 FlowPath copyFlowPath = kryo.copy(flowPath);
500 installedFlowPaths.add(copyFlowPath);
501 }
502 }
503 kryoFactory.deleteKryo(kryo);
504
505 // Generate an event for the installed Flow Path.
506 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800507 }
508
509 /**
510 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800511 *
512 * @param modifiedFlowPaths the Flow Paths to process.
513 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800514 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800515 private Collection<FlowEntry> extractModifiedFlowEntries(
516 Collection<FlowPath> modifiedFlowPaths) {
517 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800518
519 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800520 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800521 for (FlowEntry flowEntry : flowPath.flowEntries()) {
522 if (flowEntry.flowEntrySwitchState() ==
523 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800524 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800525 }
526 }
527 }
528 return modifiedFlowEntries;
529 }
530
531 /**
532 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800533 *
534 * @param modifiedFlowEnries the collection of Flow Entries that need
535 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800536 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800537 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800538 if (modifiedFlowEntries.isEmpty())
539 return;
540
541 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
542
543 //
544 // Assign the Flow Entry ID only for Flow Entries for my switches
545 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800546 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800547 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
548 if (mySwitch == null)
549 continue;
550 if (! flowEntry.isValidFlowEntryId()) {
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700551 long id = registryService.getNextUniqueId();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800552 flowEntry.setFlowEntryId(new FlowEntryId(id));
553 }
554 }
555 }
556
557 /**
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800558 * Fix a flow fetched from the database.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800559 *
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800560 * @param flowPath the Flow to fix.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800561 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800562 private void fixFlowFromDatabase(FlowPath flowPath) {
563 //
564 // TODO: Bug workaround / fix :
565 // method FlowDatabaseOperation.extractFlowEntry() doesn't
566 // fetch the inPort and outPort, hence we assign them here.
567 //
568 // Assign the inPort and outPort for the Flow Entries
569 for (FlowEntry flowEntry : flowPath.flowEntries()) {
570 // Set the inPort
571 do {
572 if (flowEntry.inPort() != null)
573 break;
574 if (flowEntry.flowEntryMatch() == null)
575 break;
576 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
577 flowEntry.setInPort(inPort);
578 } while (false);
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800579
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800580 // Set the outPort
581 do {
582 if (flowEntry.outPort() != null)
583 break;
584 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
585 if (fa.actionOutput() != null) {
586 Port outPort = new Port(fa.actionOutput().port().value());
587 flowEntry.setOutPort(outPort);
588 break;
589 }
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800590 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800591 } while (false);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800592 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800593 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800594
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800595 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800596 * Process the Switch Dpid events.
597 */
598 private void processSwitchDpidEvents() {
599 Map<Long, Dpid> addedSwitches = new HashMap<Long, Dpid>();
600 Map<Long, Dpid> removedSwitches = new HashMap<Long, Dpid>();
601
602 //
603 // Process all Switch Dpid events and update the appropriate state
604 //
605 for (EventEntry<Dpid> eventEntry : switchDpidEvents) {
606 Dpid dpid = eventEntry.eventData();
607
608 log.debug("SwitchDpid Event: {} {}", eventEntry.eventType(), dpid);
609
610 // Compute the final set of added and removed switches
611 switch (eventEntry.eventType()) {
612 case ENTRY_ADD:
613 addedSwitches.put(dpid.value(), dpid);
614 removedSwitches.remove(dpid.value());
615 break;
616 case ENTRY_REMOVE:
617 addedSwitches.remove(dpid.value());
618 removedSwitches.put(dpid.value(), dpid);
619 break;
620 }
621 }
622
623 //
624 // Remove the Flows from the local cache if the removed
625 // switch is the Source Switch.
626 //
627 // TODO: This search can be expensive for a large number of flows
628 // and should be optmized.
629 //
630 List<FlowId> deleteFlowIds = new LinkedList<FlowId>();
631 for (Dpid switchDpid : removedSwitches.values()) {
632 for (FlowPath flowPath : allFlowPaths.values()) {
633 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
634 if (srcDpid.value() == switchDpid.value())
635 deleteFlowIds.add(flowPath.flowId());
636 }
637 }
638 //
639 // Remove the Flows from the local cache
640 //
641 for (FlowId flowId : deleteFlowIds)
642 allFlowPaths.remove(flowId.value());
643
644 // Get the Flows for the added switches
645 Collection<FlowPath> flowPaths =
646 ParallelFlowDatabaseOperation.getFlowsForSwitches(dbHandler,
647 addedSwitches.values());
648 for (FlowPath flowPath : flowPaths) {
649 allFlowPaths.put(flowPath.flowId().value(), flowPath);
650 }
651 }
652
653 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800654 * Process the Flow ID events.
655 *
656 * @param mySwitches the collection of my switches.
657 */
658 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800659 List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
660
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800661 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800662 // Process all Flow Id events and update the appropriate state
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800663 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800664 for (EventEntry<Pair<FlowId, Dpid>> eventEntry : flowIdEvents) {
665 Pair<FlowId, Dpid> pair = eventEntry.eventData();
666 FlowId flowId = pair.first;
667 Dpid dpid = pair.second;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800668
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800669 log.debug("Flow ID Event: {} {} {}", eventEntry.eventType(),
670 flowId, dpid);
671
672 //
673 // Ignore Flows if the Source Switch is not controlled by this
674 // instance.
675 //
676 if (mySwitches.get(dpid.value()) == null)
677 continue;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800678
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800679 switch (eventEntry.eventType()) {
680 case ENTRY_ADD: {
681 //
682 // Add a new Flow Path
683 //
684 if (allFlowPaths.get(flowId.value()) != null) {
685 //
686 // TODO: What to do if the Flow Path already exists?
687 // Fow now, we just re-add it.
688 //
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800689 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800690 shouldFetchMyFlowIds.add(flowId);
691
692 break;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800693 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800694
695 case ENTRY_REMOVE: {
696 //
697 // Remove an existing Flow Path.
698 //
699 // Find the Flow Path, and mark the Flow and its Flow Entries
700 // for deletion.
701 //
702 FlowPath existingFlowPath =
703 allFlowPaths.get(flowId.value());
704 if (existingFlowPath == null)
705 continue; // Nothing to do
706
707 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
708 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
709 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
710 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
711 }
712
713 // Remove the Flow Path from the internal state
714 Long key = existingFlowPath.flowId().value();
715 allFlowPaths.remove(key);
716 shouldRecomputeFlowPaths.remove(key);
717 modifiedFlowPaths.put(key, existingFlowPath);
718
719 break;
720 }
721 }
722 }
723
724 // Get my Flows
725 Collection<FlowPath> myFlows =
Pavlin Radoslavov6602b6a2014-01-10 16:43:29 -0800726 ParallelFlowDatabaseOperation.getFlows(dbHandler,
727 shouldFetchMyFlowIds);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800728
729 for (FlowPath flowPath : myFlows) {
730 fixFlowFromDatabase(flowPath);
731
732 switch (flowPath.flowPathType()) {
733 case FP_TYPE_SHORTEST_PATH:
734 //
735 // Reset the Data Path, in case it was set already, because
736 // we are going to recompute it anyway.
737 //
738 flowPath.flowEntries().clear();
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800739 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
740 flowPath);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800741 break;
742 case FP_TYPE_EXPLICIT_PATH:
743 //
744 // Mark all Flow Entries for installation in the switches.
745 //
746 for (FlowEntry flowEntry : flowPath.flowEntries()) {
747 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
748 }
749 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
750 break;
751 case FP_TYPE_UNKNOWN:
752 log.error("FlowPath event with unknown type");
753 break;
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800754 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800755 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800756 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800757 }
758
759 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800760 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800761 *
762 * @param mySwitches the collection of my switches.
763 * @return a collection of modified Flow Entries this instance needs
764 * to push to its own switches.
765 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800766 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800767 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
768
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800769 //
770 // Process all Flow ID events and update the appropriate state
771 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800772 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
773 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
774 FlowEntryId flowEntryId = pair.first;
775 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800776
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800777 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
778 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800779
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800780 if (mySwitches.get(dpid.value()) == null)
781 continue;
782
783 // Fetch the Flow Entry
784 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
785 flowEntryId);
786 if (flowEntry == null) {
787 log.debug("Flow Entry ID {} : Flow Entry not found!",
788 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800789 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800790 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800791 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800792 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800793
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800794 return modifiedFlowEntries;
795 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800796
797 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800798 * Process the Flow Path events.
799 */
800 private void processFlowPathEvents() {
801 //
802 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700803 //
804 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
805 FlowPath flowPath = eventEntry.eventData();
806
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800807 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800808
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700809 switch (eventEntry.eventType()) {
810 case ENTRY_ADD: {
811 //
812 // Add a new Flow Path
813 //
814 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
815 //
816 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800817 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700818 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700819 }
820
821 switch (flowPath.flowPathType()) {
822 case FP_TYPE_SHORTEST_PATH:
823 //
824 // Reset the Data Path, in case it was set already, because
825 // we are going to recompute it anyway.
826 //
827 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800828 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
829 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700830 break;
831 case FP_TYPE_EXPLICIT_PATH:
832 //
833 // Mark all Flow Entries for installation in the switches.
834 //
835 for (FlowEntry flowEntry : flowPath.flowEntries()) {
836 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
837 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800838 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700839 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800840 case FP_TYPE_UNKNOWN:
841 log.error("FlowPath event with unknown type");
842 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700843 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800844 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700845
846 break;
847 }
848
849 case ENTRY_REMOVE: {
850 //
851 // Remove an existing Flow Path.
852 //
853 // Find the Flow Path, and mark the Flow and its Flow Entries
854 // for deletion.
855 //
856 FlowPath existingFlowPath =
857 allFlowPaths.get(flowPath.flowId().value());
858 if (existingFlowPath == null)
859 continue; // Nothing to do
860
861 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
862 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
863 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
864 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
865 }
866
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800867 // Remove the Flow Path from the internal state
868 Long key = existingFlowPath.flowId().value();
869 allFlowPaths.remove(key);
870 shouldRecomputeFlowPaths.remove(key);
871 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700872
873 break;
874 }
875 }
876 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800877 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700878
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800879 /**
880 * Process the Topology events.
881 */
882 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800883 boolean isTopologyModified = false;
884
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800885 if (enableOnrc2014MeasurementsTopology) {
886 if (topologyEvents.isEmpty())
887 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800888
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800889 // TODO: Code for debugging purpose only
890 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
891 TopologyElement topologyElement = eventEntry.eventData();
892 log.debug("Topology Event: {} {}", eventEntry.eventType(),
893 topologyElement.toString());
894 }
895
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800896 log.debug("[BEFORE] {}", topology.toString());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800897 topology.readFromDatabase(dbHandler);
898 log.debug("[AFTER] {}", topology.toString());
899 shouldRecomputeFlowPaths.putAll(allFlowPaths);
900 return;
901 }
902
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700903 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800904 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700905 //
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700906 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
907 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800908
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800909 log.debug("Topology Event: {} {}", eventEntry.eventType(),
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800910 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800911
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700912 switch (eventEntry.eventType()) {
913 case ENTRY_ADD:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800914 isTopologyModified |= topology.addTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700915 break;
916 case ENTRY_REMOVE:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800917 isTopologyModified |= topology.removeTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700918 break;
919 }
920 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700921 if (isTopologyModified) {
922 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800923 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700924 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800925 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700926
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800927 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800928 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800929 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800930 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800931 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800932 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800933
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700934 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800935 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700936 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800937 if (! unmatchedFlowEntryAdd.isEmpty()) {
938 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
939 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800940 // log.debug("Processing Unmatched Flow Entry: {}",
941 // flowEntry.toString());
942
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800943 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800944 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800945 remainingUpdates.put(flowEntry.flowEntryId().value(),
946 flowEntry);
947 continue;
948 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800949 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
950 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800951 remainingUpdates.put(flowEntry.flowEntryId().value(),
952 flowEntry);
953 continue;
954 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800955 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
956 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
957 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700958 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800959 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700960 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800961 }
962
963 /**
964 * Process the Flow Entry events.
965 */
966 private void processFlowEntryEvents() {
967 FlowPath flowPath;
968 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700969
970 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800971 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700972 //
973 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
974 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800975
976 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800977 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800978
979 if ((! flowEntry.isValidFlowId()) ||
980 (! flowEntry.isValidFlowEntryId())) {
981 continue;
982 }
983
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700984 switch (eventEntry.eventType()) {
985 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800986 flowPath = allFlowPaths.get(flowEntry.flowId().value());
987 if (flowPath == null) {
988 // Flow Path not found: keep the entry for later matching
989 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
990 flowEntry);
991 break;
992 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800993 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
994 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800995 // Flow Entry not found: keep the entry for later matching
996 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
997 flowEntry);
998 break;
999 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001000 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
1001 // Add the updated Flow Path to the list of updated paths
1002 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
1003 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001004 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001005
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001006 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001007 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1008 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001009 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001010 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001011
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001012 flowPath = allFlowPaths.get(flowEntry.flowId().value());
1013 if (flowPath == null) {
1014 // Flow Path not found: ignore the update
1015 break;
1016 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001017 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
1018 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001019 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001020 break;
1021 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001022 if (updateFlowEntryRemove(flowPath, localFlowEntry,
1023 flowEntry)) {
1024 // Add the updated Flow Path to the list of updated paths
1025 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
1026 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001027 break;
1028 }
1029 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001030 }
1031
1032 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001033 * Find a Flow Entry that should be updated because of an external
1034 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001035 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001036 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001037 * @param newFlowEntry the FlowEntry with the new state.
1038 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001039 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001040 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
1041 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001042 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001043 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001044 //
1045 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001046 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001047 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001048 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001049 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001050
1051 //
1052 // Local Flow Entry match found
1053 //
1054 if (localFlowEntry.isValidFlowEntryId()) {
1055 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001056 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001057 //
1058 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001059 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001060 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001061 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001062 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001063 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001064 return localFlowEntry;
1065 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001066
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001067 return null; // Entry not found
1068 }
1069
1070 /**
1071 * Update a Flow Entry because of an external ENTRY_ADD event.
1072 *
1073 * @param flowPath the FlowPath for the Flow Entry to update.
1074 * @param localFlowEntry the local Flow Entry to update.
1075 * @param newFlowEntry the FlowEntry with the new state.
1076 * @return true if the local Flow Entry was updated, otherwise false.
1077 */
1078 private boolean updateFlowEntryAdd(FlowPath flowPath,
1079 FlowEntry localFlowEntry,
1080 FlowEntry newFlowEntry) {
1081 boolean updated = false;
1082
1083 if (localFlowEntry.flowEntryUserState() ==
1084 FlowEntryUserState.FE_USER_DELETE) {
1085 // Don't add-back a Flow Entry that is already deleted
1086 return false;
1087 }
1088
1089 if (! localFlowEntry.isValidFlowEntryId()) {
1090 // Update the Flow Entry ID
1091 FlowEntryId flowEntryId =
1092 new FlowEntryId(newFlowEntry.flowEntryId().value());
1093 localFlowEntry.setFlowEntryId(flowEntryId);
1094 updated = true;
1095 }
1096
1097 //
1098 // Update the local Flow Entry, and keep state to check
1099 // if the Flow Path has been installed.
1100 //
1101 if (localFlowEntry.flowEntryUserState() !=
1102 newFlowEntry.flowEntryUserState()) {
1103 localFlowEntry.setFlowEntryUserState(
1104 newFlowEntry.flowEntryUserState());
1105 updated = true;
1106 }
1107 if (localFlowEntry.flowEntrySwitchState() !=
1108 newFlowEntry.flowEntrySwitchState()) {
1109 localFlowEntry.setFlowEntrySwitchState(
1110 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -08001111 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001112 updated = true;
1113 }
1114
1115 return updated;
1116 }
1117
1118 /**
1119 * Find a Flow Entry that should be updated because of an external
1120 * ENTRY_REMOVE event.
1121 *
1122 * @param flowPath the FlowPath for the Flow Entry to update.
1123 * @param newFlowEntry the FlowEntry with the new state.
1124 * @return the Flow Entry that should be updated if found, otherwise null.
1125 */
1126 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
1127 FlowEntry newFlowEntry) {
1128 //
1129 // Iterate over all Flow Entries and find a match based on
1130 // the Flow Entry ID.
1131 //
1132 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
1133 if (! localFlowEntry.isValidFlowEntryId())
1134 continue;
1135 if (localFlowEntry.flowEntryId().value() !=
1136 newFlowEntry.flowEntryId().value()) {
1137 continue;
1138 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001139 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001140 }
1141
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001142 return null; // Entry not found
1143 }
1144
1145 /**
1146 * Update a Flow Entry because of an external ENTRY_REMOVE event.
1147 *
1148 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001149 * @param localFlowEntry the local Flow Entry to update.
1150 * @param newFlowEntry the FlowEntry with the new state.
1151 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001152 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001153 private boolean updateFlowEntryRemove(FlowPath flowPath,
1154 FlowEntry localFlowEntry,
1155 FlowEntry newFlowEntry) {
1156 boolean updated = false;
1157
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001158 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001159 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001160 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001161 if (localFlowEntry.flowEntryUserState() !=
1162 newFlowEntry.flowEntryUserState()) {
1163 localFlowEntry.setFlowEntryUserState(
1164 newFlowEntry.flowEntryUserState());
1165 updated = true;
1166 }
1167 if (localFlowEntry.flowEntrySwitchState() !=
1168 newFlowEntry.flowEntrySwitchState()) {
1169 localFlowEntry.setFlowEntrySwitchState(
1170 newFlowEntry.flowEntrySwitchState());
1171 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001172 }
1173
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001174 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001175 }
1176
1177 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001178 * Recompute a Flow Path.
1179 *
1180 * @param flowPath the Flow Path to recompute.
1181 * @return true if the recomputed Flow Path has changed, otherwise false.
1182 */
1183 private boolean recomputeFlowPath(FlowPath flowPath) {
1184 boolean hasChanged = false;
1185
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001186 if (enableOnrc2014MeasurementsFlows) {
1187 // Cleanup the deleted Flow Entries from the earlier iteration
1188 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -08001189
1190 //
1191 // TODO: Fake it that the Flow Entries have been already pushed
1192 // into the switches, so we don't push them again.
1193 //
1194 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1195 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1196 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001197 }
1198
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001199 //
1200 // Test whether the Flow Path needs to be recomputed
1201 //
1202 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001203 case FP_TYPE_UNKNOWN:
1204 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001205 case FP_TYPE_SHORTEST_PATH:
1206 break;
1207 case FP_TYPE_EXPLICIT_PATH:
1208 return false; // An explicit path never changes
1209 }
1210
1211 DataPath oldDataPath = flowPath.dataPath();
1212
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001213 // Compute the new path
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001214 DataPath newDataPath;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001215 newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001216 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001217 if (newDataPath == null) {
1218 // We need the DataPath to compare the paths
1219 newDataPath = new DataPath();
1220 }
1221 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1222
1223 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001224 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001225 //
1226 if (oldDataPath.flowEntries().size() !=
1227 newDataPath.flowEntries().size()) {
1228 hasChanged = true;
1229 } else {
1230 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1231 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1232 while (oldIter.hasNext() && newIter.hasNext()) {
1233 FlowEntry oldFlowEntry = oldIter.next();
1234 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001235 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1236 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001237 hasChanged = true;
1238 break;
1239 }
1240 }
1241 }
1242 if (! hasChanged)
1243 return hasChanged;
1244
1245 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001246 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001247 // - If a Flow Entry for a switch is in the old data path, but not
1248 // in the new data path, then mark it for deletion.
1249 // - If a Flow Entry for a switch is in the new data path, but not
1250 // in the old data path, then mark it for addition.
1251 // - If a Flow Entry for a switch is in both the old and the new
1252 // data path, but it has changed, e.g., the incoming and/or outgoing
1253 // port(s), then mark the old Flow Entry for deletion, and mark
1254 // the new Flow Entry for addition.
1255 // - If a Flow Entry for a switch is in both the old and the new
1256 // data path, and it hasn't changed, then just keep it.
1257 //
1258 // NOTE: We use the Switch DPID of each entry to match the entries
1259 //
1260 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1261 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1262 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1263 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1264
1265 // Prepare maps with the Flow Entries, so they are fast to lookup
1266 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1267 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1268 for (FlowEntry flowEntry : newDataPath.flowEntries())
1269 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1270
1271 //
1272 // Find the old Flow Entries that should be deleted
1273 //
1274 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1275 FlowEntry newFlowEntry =
1276 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1277 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001278 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001279 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1280 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1281 deletedFlowEntries.add(oldFlowEntry);
1282 }
1283 }
1284
1285 //
1286 // Find the new Flow Entries that should be added or updated
1287 //
1288 int idx = 0;
1289 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1290 FlowEntry oldFlowEntry =
1291 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1292
1293 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001294 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1295 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001296 //
1297 // Both Flow Entries are same
1298 //
1299 finalFlowEntries.add(oldFlowEntry);
1300 idx++;
1301 continue;
1302 }
1303
1304 if (oldFlowEntry != null) {
1305 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001306 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001307 //
1308 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1309 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1310 deletedFlowEntries.add(oldFlowEntry);
1311 }
1312
1313 //
1314 // Add the new Flow Entry
1315 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001316 //
1317 // NOTE: Assign only the Flow ID.
1318 // The Flow Entry ID is assigned later only for the Flow Entries
1319 // this instance is responsible for.
1320 //
1321 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001322
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001323 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001324 // Copy the Flow timeouts
1325 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001326 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -08001327 newFlowEntry.setPriority(flowPath.priority());
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001328
TeruU417fe022014-02-04 12:59:30 -08001329 if (flowPath.idleTimeout() > 0) {
1330 if (idx == 0) {
1331 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1332 }
1333 else {
1334 newFlowEntry.setIdleTimeout(flowPath.idleTimeout() + FLOW_IDLE_TIMEOUT_ADDED_SECONDS);
1335 }
1336 } else if(flowPath.idleTimeout() == 0) {
1337 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1338 }
1339
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001340 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001341 // Allocate the FlowEntryMatch by copying the default one
1342 // from the FlowPath (if set).
1343 //
1344 FlowEntryMatch flowEntryMatch = null;
1345 if (flowPath.flowEntryMatch() != null)
1346 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1347 else
1348 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001349 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001350
1351 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001352 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1353
1354 //
1355 // Set the actions:
1356 // If the first Flow Entry, copy the Flow Path actions to it.
1357 //
1358 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1359 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1360 FlowEntryActions flowActions =
1361 new FlowEntryActions(flowPath.flowEntryActions());
1362 for (FlowEntryAction action : flowActions.actions())
1363 flowEntryActions.addAction(action);
1364 }
1365 idx++;
1366
1367 //
1368 // Add the outgoing port output action
1369 //
1370 FlowEntryAction flowEntryAction = new FlowEntryAction();
1371 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1372 flowEntryActions.addAction(flowEntryAction);
1373
1374 //
1375 // Set the state of the new Flow Entry
1376 //
1377 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1378 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1379 finalFlowEntries.add(newFlowEntry);
1380 }
1381
1382 //
1383 // Replace the old Flow Entries with the new Flow Entries.
1384 // Note that the Flow Entries that will be deleted are added at
1385 // the end.
1386 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001387 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001388 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1389
1390 return hasChanged;
1391 }
1392
1393 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001394 * Receive a notification that a Flow is added.
1395 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001396 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001397 */
1398 @Override
1399 public void notificationRecvFlowAdded(FlowPath flowPath) {
1400 EventEntry<FlowPath> eventEntry =
1401 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1402 networkEvents.add(eventEntry);
1403 }
1404
1405 /**
1406 * Receive a notification that a Flow is removed.
1407 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001408 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001409 */
1410 @Override
1411 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1412 EventEntry<FlowPath> eventEntry =
1413 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1414 networkEvents.add(eventEntry);
1415 }
1416
1417 /**
1418 * Receive a notification that a Flow is updated.
1419 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001420 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001421 */
1422 @Override
1423 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1424 // NOTE: The ADD and UPDATE events are processed in same way
1425 EventEntry<FlowPath> eventEntry =
1426 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1427 networkEvents.add(eventEntry);
1428 }
1429
1430 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001431 * Receive a notification that a FlowEntry is added.
1432 *
1433 * @param flowEntry the FlowEntry that is added.
1434 */
1435 @Override
1436 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001437 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001438// String tag = "EventHandler.AddFlowEntryToSwitch." + flowEntry.flowEntryId();
1439 String tag = "EventHandler.AddFlowEntryToSwitch";
1440 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001441 Collection entries = new ArrayList();
1442 entries.add(flowEntry);
1443 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001444// PerformanceMonitor.stop(tag);
1445 m.stop();
1446// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001447 return;
1448 }
1449
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001450 EventEntry<FlowEntry> eventEntry =
1451 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1452 networkEvents.add(eventEntry);
1453 }
1454
1455 /**
1456 * Receive a notification that a FlowEntry is removed.
1457 *
1458 * @param flowEntry the FlowEntry that is removed.
1459 */
1460 @Override
1461 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001462 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001463// String tag = "EventHandler.RemoveFlowEntryFromSwitch." + flowEntry.flowEntryId();
1464 String tag = "EventHandler.RemoveFlowEntryFromSwitch";
1465 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavove4d2a432014-01-10 12:01:08 -08001466 //
1467 // NOTE: Must update the state to DELETE, because
1468 // the notification contains the original state.
1469 //
1470 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1471
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001472 Collection entries = new ArrayList();
1473 entries.add(flowEntry);
1474 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001475// PerformanceMonitor.stop(tag);
1476 m.stop();
1477// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001478 return;
1479 }
1480
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001481 EventEntry<FlowEntry> eventEntry =
1482 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1483 networkEvents.add(eventEntry);
1484 }
1485
1486 /**
1487 * Receive a notification that a FlowEntry is updated.
1488 *
1489 * @param flowEntry the FlowEntry that is updated.
1490 */
1491 @Override
1492 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001493 if (enableOnrc2014MeasurementsFlows) {
1494 Collection entries = new ArrayList();
1495 entries.add(flowEntry);
1496 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1497 return;
1498 }
1499
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001500 // NOTE: The ADD and UPDATE events are processed in same way
1501 EventEntry<FlowEntry> eventEntry =
1502 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1503 networkEvents.add(eventEntry);
1504 }
1505
1506 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001507 * Receive a notification that a FlowId is added.
1508 *
1509 * @param flowId the FlowId that is added.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001510 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001511 */
1512 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001513 public void notificationRecvFlowIdAdded(FlowId flowId, Dpid dpid) {
1514 Pair flowIdPair = new Pair(flowId, dpid);
1515
1516 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1517 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001518 networkEvents.add(eventEntry);
1519 }
1520
1521 /**
1522 * Receive a notification that a FlowId is removed.
1523 *
1524 * @param flowId the FlowId that is removed.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001525 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001526 */
1527 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001528 public void notificationRecvFlowIdRemoved(FlowId flowId, Dpid dpid) {
1529 Pair flowIdPair = new Pair(flowId, dpid);
1530
1531 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1532 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001533 networkEvents.add(eventEntry);
1534 }
1535
1536 /**
1537 * Receive a notification that a FlowId is updated.
1538 *
1539 * @param flowId the FlowId that is updated.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001540 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001541 */
1542 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001543 public void notificationRecvFlowIdUpdated(FlowId flowId, Dpid dpid) {
1544 Pair flowIdPair = new Pair(flowId, dpid);
1545
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001546 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001547 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1548 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001549 networkEvents.add(eventEntry);
1550 }
1551
1552 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001553 * Receive a notification that a FlowEntryId is added.
1554 *
1555 * @param flowEntryId the FlowEntryId that is added.
1556 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1557 */
1558 @Override
1559 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1560 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001561 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1562
1563 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1564 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001565 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001566 }
1567
1568 /**
1569 * Receive a notification that a FlowEntryId is removed.
1570 *
1571 * @param flowEntryId the FlowEntryId that is removed.
1572 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1573 */
1574 @Override
1575 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1576 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001577 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1578
1579 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1580 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001581 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001582 }
1583
1584 /**
1585 * Receive a notification that a FlowEntryId is updated.
1586 *
1587 * @param flowEntryId the FlowEntryId that is updated.
1588 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1589 */
1590 @Override
1591 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1592 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001593 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1594
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001595 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001596 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1597 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001598 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001599 }
1600
1601 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001602 * Receive a notification that a Topology Element is added.
1603 *
1604 * @param topologyElement the Topology Element that is added.
1605 */
1606 @Override
1607 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1608 EventEntry<TopologyElement> eventEntry =
1609 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1610 networkEvents.add(eventEntry);
1611 }
1612
1613 /**
1614 * Receive a notification that a Topology Element is removed.
1615 *
1616 * @param topologyElement the Topology Element that is removed.
1617 */
1618 @Override
1619 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1620 EventEntry<TopologyElement> eventEntry =
1621 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1622 networkEvents.add(eventEntry);
1623 }
1624
1625 /**
1626 * Receive a notification that a Topology Element is updated.
1627 *
1628 * @param topologyElement the Topology Element that is updated.
1629 */
1630 @Override
1631 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1632 // NOTE: The ADD and UPDATE events are processed in same way
1633 EventEntry<TopologyElement> eventEntry =
1634 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1635 networkEvents.add(eventEntry);
1636 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001637
1638 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -08001639 * Receive a notification that a switch is added to this instance.
1640 *
1641 * @param sw the switch that is added.
1642 */
1643 @Override
1644 public void addedSwitch(IOFSwitch sw) {
1645 Dpid dpid = new Dpid(sw.getId());
1646 EventEntry<Dpid> eventEntry =
1647 new EventEntry<Dpid>(EventEntry.Type.ENTRY_ADD, dpid);
1648 networkEvents.add(eventEntry);
1649 }
1650
1651 /**
1652 * Receive a notification that a switch is removed from this instance.
1653 *
1654 * @param sw the switch that is removed.
1655 */
1656 @Override
1657 public void removedSwitch(IOFSwitch sw) {
1658 Dpid dpid = new Dpid(sw.getId());
1659 EventEntry<Dpid> eventEntry =
1660 new EventEntry<Dpid>(EventEntry.Type.ENTRY_REMOVE, dpid);
1661 networkEvents.add(eventEntry);
1662 }
1663
1664 /**
1665 * Receive a notification that the ports on a switch have changed.
1666 */
1667 @Override
1668 public void switchPortChanged(Long switchId) {
1669 // Nothing to do
1670 }
1671
1672 /**
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001673 * Get a sorted copy of all Flow Paths.
1674 *
1675 * @return a sorted copy of all Flow Paths.
1676 */
1677 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1678 SortedMap<Long, FlowPath> sortedFlowPaths =
1679 new TreeMap<Long, FlowPath>();
1680
1681 //
1682 // TODO: For now we use serialization/deserialization to create
1683 // a copy of each Flow Path. In the future, we should use proper
1684 // copy constructors.
1685 //
1686 Kryo kryo = kryoFactory.newKryo();
1687 synchronized (allFlowPaths) {
1688 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1689 FlowPath origFlowPath = entry.getValue();
1690 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1691 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1692 }
1693 }
1694 kryoFactory.deleteKryo(kryo);
1695
1696 return sortedFlowPaths;
1697 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001698}