blob: 116af1f041f3d3879ebca4dac48d4dc360fd22ab [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;
39
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -080040import com.esotericsoftware.kryo.Kryo;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
44/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070045 * Class for FlowPath Maintenance.
46 * This class listens for FlowEvents to:
47 * - Maintain a local cache of the Network Topology.
48 * - Detect FlowPaths impacted by Topology change.
49 * - Recompute impacted FlowPath using cached Topology.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070050 */
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080051class FlowEventHandler extends Thread implements IFlowEventHandlerService,
52 IOFSwitchListener {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080053
Matteo Gerola468ce632014-02-26 20:10:49 -080054 private boolean enableOnrc2014MeasurementsFlows = false;
55 private boolean enableOnrc2014MeasurementsTopology = false;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080056
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070057 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070058 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
TeruU417fe022014-02-04 12:59:30 -080059
TeruU6464af02014-02-06 21:38:45 -080060 private final int FLOW_IDLE_TIMEOUT_ADDED_SECONDS = 5;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070061
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -080062 private DBOperation dbHandler;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -080063
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070064 private FlowManager flowManager; // The Flow Manager to use
65 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070066 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080067 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070068
69 // The queue with Flow Path and Topology Element updates
70 private BlockingQueue<EventEntry<?>> networkEvents =
71 new LinkedBlockingQueue<EventEntry<?>>();
72
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070073 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070074 private List<EventEntry<TopologyElement>> topologyEvents =
75 new LinkedList<EventEntry<TopologyElement>>();
76 private List<EventEntry<FlowPath>> flowPathEvents =
77 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070078 private List<EventEntry<FlowEntry>> flowEntryEvents =
79 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2194d112014-01-10 13:36:00 -080080 private List<EventEntry<Pair<FlowId, Dpid>>> flowIdEvents =
81 new LinkedList<EventEntry<Pair<FlowId, Dpid>>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080082 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
83 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080084 private List<EventEntry<Dpid>> switchDpidEvents =
85 new LinkedList<EventEntry<Dpid>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070086
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080087 // All internally computed Flow Paths
88 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
89
90 // The Flow Entries received as notifications with unmatched Flow Paths
91 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
92 new HashMap<Long, FlowEntry>();
93
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080094 //
95 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080096 // - The Flow Paths that should be recomputed
97 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080098 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080099 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800100 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
101 new HashMap<Long, FlowPath>();
102 private Map<Long, FlowPath> modifiedFlowPaths =
103 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800104 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
105 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800106
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700107 /**
108 * Constructor for a given Flow Manager and Datagrid Service.
109 *
110 * @param flowManager the Flow Manager to use.
111 * @param datagridService the Datagrid Service to use.
112 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700113 FlowEventHandler(FlowManager flowManager,
114 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700115 this.flowManager = flowManager;
116 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700117 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700118 }
119
120 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800121 * Get the network topology.
122 *
123 * @return the network topology.
124 */
125 protected Topology getTopology() { return this.topology; }
126
127 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800128 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700129 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800130 private void startup() {
Yoshi Muroi5804ce92014-02-08 03:58:04 -0800131 this.dbHandler = GraphDBManager.getDBOperation();
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800132
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700133 //
134 // Obtain the initial Topology state
135 //
136 Collection<TopologyElement> topologyElements =
137 datagridService.getAllTopologyElements();
138 for (TopologyElement topologyElement : topologyElements) {
139 EventEntry<TopologyElement> eventEntry =
140 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
141 topologyEvents.add(eventEntry);
142 }
143 //
144 // Obtain the initial Flow Path state
145 //
146 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
147 for (FlowPath flowPath : flowPaths) {
148 EventEntry<FlowPath> eventEntry =
149 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
150 flowPathEvents.add(eventEntry);
151 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700152 //
153 // Obtain the initial FlowEntry state
154 //
155 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
156 for (FlowEntry flowEntry : flowEntries) {
157 EventEntry<FlowEntry> eventEntry =
158 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
159 flowEntryEvents.add(eventEntry);
160 }
161
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800162 //
163 // Obtain the initial FlowId state
164 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800165 Collection<Pair<FlowId, Dpid>> flowIds =
166 datagridService.getAllFlowIds();
167 for (Pair<FlowId, Dpid> pair : flowIds) {
168 EventEntry<Pair<FlowId, Dpid>> eventEntry =
169 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800170 flowIdEvents.add(eventEntry);
171 }
172
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800173 //
174 // Obtain the initial FlowEntryId state
175 //
176 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
177 datagridService.getAllFlowEntryIds();
178 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
179 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
180 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
181 flowEntryIdEvents.add(eventEntry);
182 }
183
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800184 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800185 synchronized (allFlowPaths) {
186 processEvents();
187 }
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800188
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800189 }
190
191 /**
192 * Run the thread.
193 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800194 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800195 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800196 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800197 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700198
199 //
200 // The main loop
201 //
202 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
203 try {
204 while (true) {
205 EventEntry<?> eventEntry = networkEvents.take();
206 collection.add(eventEntry);
207 networkEvents.drainTo(collection);
208
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700209 //
210 // Demultiplex all events:
211 // - EventEntry<TopologyElement>
212 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700213 // - EventEntry<FlowEntry>
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800214 // - EventEntry<Pair<FlowId, Dpid>>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800215 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700216 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700217 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800218 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700219 if (event.eventData() instanceof TopologyElement) {
220 EventEntry<TopologyElement> topologyEventEntry =
221 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800222
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700223 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800224 continue;
225 }
226
227 // FlowPath event
228 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700229 EventEntry<FlowPath> flowPathEventEntry =
230 (EventEntry<FlowPath>)event;
231 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800232 continue;
233 }
234
235 // FlowEntry event
236 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700237 EventEntry<FlowEntry> flowEntryEventEntry =
238 (EventEntry<FlowEntry>)event;
239 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800240 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700241 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800242
243 // FlowId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800244 if (event.eventData() instanceof Pair) {
245 EventEntry<Pair<FlowId, Dpid>> flowIdEventEntry =
246 (EventEntry<Pair<FlowId, Dpid>>)event;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800247 flowIdEvents.add(flowIdEventEntry);
248 continue;
249 }
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800250
251 // Switch Dpid event
252 if (event.eventData() instanceof Dpid) {
253 EventEntry<Dpid> switchDpidEventEntry =
254 (EventEntry<Dpid>)event;
255 switchDpidEvents.add(switchDpidEventEntry);
256 continue;
257 }
258
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800259 // FlowEntryId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800260 // TODO: Fix the code below if we need again to handle
261 // the FlowEntryId events
262 /*
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800263 if (event.eventData() instanceof Pair) {
264 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
265 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
266 flowEntryIdEvents.add(flowEntryIdEventEntry);
267 continue;
268 }
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800269 */
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700270 }
271 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700272
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700273 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800274 synchronized (allFlowPaths) {
275 processEvents();
276 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700277 }
278 } catch (Exception exception) {
279 log.debug("Exception processing Network Events: ", exception);
280 }
281 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800282
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700283 /**
284 * Process the events (if any)
285 */
286 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800287 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700288
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800289 if (enableOnrc2014MeasurementsFlows) {
290
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800291 PerformanceMonitor.start("EventHandler.ProcessAllEvents");
292
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800293 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
294 switchDpidEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800295 return; // Nothing to do
296 }
297
298 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
299
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800300 // Process the Switch Dpid events
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800301 PerformanceMonitor.start("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800302 processSwitchDpidEvents();
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800303 PerformanceMonitor.stop("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800304
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800305 // Process the Flow ID events
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800306 PerformanceMonitor.start("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800307 processFlowIdEvents(mySwitches);
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800308 PerformanceMonitor.stop("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800309
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800310 // Fetch the topology
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800311 PerformanceMonitor.start("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800312 processTopologyEvents();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800313 PerformanceMonitor.stop("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800314
315 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800316 PerformanceMonitor.start("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800317 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
318 if (recomputeFlowPath(flowPath))
319 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
320 }
321
322 // Assign the Flow Entry ID as needed
323 for (FlowPath flowPath : modifiedFlowPaths.values()) {
324 for (FlowEntry flowEntry : flowPath.flowEntries()) {
325 if (! flowEntry.isValidFlowEntryId()) {
326 long id = flowManager.getNextFlowEntryId();
327 flowEntry.setFlowEntryId(new FlowEntryId(id));
328 }
329 }
330 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800331 PerformanceMonitor.stop("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800332
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800333 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800334 // Push the modified state to the database
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800335 //
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800336 PerformanceMonitor.start("EventHandler.WriteFlowsToDb");
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800337 for (FlowPath flowPath : modifiedFlowPaths.values()) {
338 //
339 // Delete the Flow Path from the Network Map
340 //
341 if (flowPath.flowPathUserState() ==
342 FlowPathUserState.FP_USER_DELETE) {
343 log.debug("Deleting Flow Path From Database: {}", flowPath);
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800344 // TODO: For now the deleting of a Flow Path is blocking
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800345 ParallelFlowDatabaseOperation.deleteFlow(dbHandler,
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800346 flowPath.flowId());
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800347 //
348 // NOTE: For now the sending of the notifications
349 // is outside of this loop, so the performance measurements
350 // are more accurate.
351 //
352 /*
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800353 // Send the notifications for the deleted Flow Entries
354 for (FlowEntry flowEntry : flowPath.flowEntries()) {
355 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
356 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800357 */
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800358
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800359 continue;
360 }
361
362 log.debug("Pushing Flow Path To Database: {}", flowPath);
363 //
364 // Write the Flow Path to the Network Map
365 //
366 ParallelFlowDatabaseOperation.addFlow(dbHandler, flowPath,
367 datagridService);
368 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800369 PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
370
371 //
372 // Send the notifications for the deleted Flow Entries
373 // NOTE: This code was pulled outside of the above loop,
374 // so the performance measurements are more accurate.
375 //
376 PerformanceMonitor.start("EventHandler.NotificationSend.FlowEntryRemoved");
377 for (FlowPath flowPath : modifiedFlowPaths.values()) {
378 if (flowPath.flowPathUserState() ==
379 FlowPathUserState.FP_USER_DELETE) {
380 for (FlowEntry flowEntry : flowPath.flowEntries()) {
381 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
382 }
383 }
384 }
Pavlin Radoslavovdbd09cc2014-01-12 18:13:35 -0800385 PerformanceMonitor.stop("EventHandler.NotificationSend.FlowEntryRemoved");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800386
387 // Cleanup
388 topologyEvents.clear();
389 flowIdEvents.clear();
Pavlin Radoslavov2d6e5f12014-01-10 16:34:05 -0800390 switchDpidEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800391 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800392 // NOTE: Keep a cache with my Flow Paths
393 // allFlowPaths.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800394 shouldRecomputeFlowPaths.clear();
395 modifiedFlowPaths.clear();
396
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800397 PerformanceMonitor.stop("EventHandler.ProcessAllEvents");
Pavlin Radoslavov8bd6d112014-01-12 20:12:37 -0800398
399
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800400// PerformanceMonitor.report("EventHandler.SwitchDpidEvents");
401// PerformanceMonitor.report("EventHandler.FlowIdEvents");
402// PerformanceMonitor.report("EventHandler.ReadTopology");
403// PerformanceMonitor.report("EventHandler.RecomputeFlows");
404// PerformanceMonitor.report("EventHandler.WriteFlowsToDb");
405// PerformanceMonitor.report("EventHandler.NotificationSend.FlowEntryRemoved");
406// PerformanceMonitor.report("EventHandler.ProcessAllEvents");
Brian O'Connor0d9963f2014-01-14 14:44:21 -0800407// PerformanceMonitor.report();
408// PerformanceMonitor.clear();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800409
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800410 return;
411 }
412
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700413 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
414 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700415 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700416 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700417
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800418 processFlowPathEvents();
419 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800420 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800421 processFlowEntryEvents();
422
423 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800424 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800425 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800426 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800427 }
428
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800429 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800430 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800431
432 // Assign missing Flow Entry IDs
433 assignFlowEntryId(modifiedFlowEntries);
434
435 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800436 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800437 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800438 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
439 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800440
441 //
442 // Remove Flow Entries that were deleted
443 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800444 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800445 flowPath.dataPath().removeDeletedFlowEntries();
446
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800447 //
448 // Check if Flow Paths have been installed into all switches,
449 // and generate the appropriate events.
450 //
451 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
452
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800453 // Cleanup
454 topologyEvents.clear();
455 flowPathEvents.clear();
456 flowEntryEvents.clear();
457 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800458 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800459 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800460 checkIfInstalledFlowPaths.clear();
461 }
462
463 /**
464 * Check if Flow Paths have been installed into all switches,
465 * and generate the appropriate events.
466 *
467 * @param flowPaths the flowPaths to process.
468 */
469 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
470 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
471
472 Kryo kryo = kryoFactory.newKryo();
473
474 for (FlowPath flowPath : flowPaths) {
475 boolean isInstalled = true;
Jonathan Hart0444d932014-01-22 15:06:17 -0800476
477 if (flowPath.flowEntries().isEmpty()) {
478 continue;
479 }
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800480
481 //
482 // Check whether all Flow Entries have been installed
483 //
484 for (FlowEntry flowEntry : flowPath.flowEntries()) {
485 if (flowEntry.flowEntrySwitchState() !=
486 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
487 isInstalled = false;
488 break;
489 }
490 }
491
492 if (isInstalled) {
493 // Create a copy and add it to the list
494 FlowPath copyFlowPath = kryo.copy(flowPath);
495 installedFlowPaths.add(copyFlowPath);
496 }
497 }
498 kryoFactory.deleteKryo(kryo);
499
500 // Generate an event for the installed Flow Path.
501 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800502 }
503
504 /**
505 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800506 *
507 * @param modifiedFlowPaths the Flow Paths to process.
508 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800509 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800510 private Collection<FlowEntry> extractModifiedFlowEntries(
511 Collection<FlowPath> modifiedFlowPaths) {
512 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800513
514 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800515 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800516 for (FlowEntry flowEntry : flowPath.flowEntries()) {
517 if (flowEntry.flowEntrySwitchState() ==
518 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800519 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800520 }
521 }
522 }
523 return modifiedFlowEntries;
524 }
525
526 /**
527 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800528 *
529 * @param modifiedFlowEnries the collection of Flow Entries that need
530 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800531 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800532 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800533 if (modifiedFlowEntries.isEmpty())
534 return;
535
536 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
537
538 //
539 // Assign the Flow Entry ID only for Flow Entries for my switches
540 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800541 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800542 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
543 if (mySwitch == null)
544 continue;
545 if (! flowEntry.isValidFlowEntryId()) {
546 long id = flowManager.getNextFlowEntryId();
547 flowEntry.setFlowEntryId(new FlowEntryId(id));
548 }
549 }
550 }
551
552 /**
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800553 * Fix a flow fetched from the database.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800554 *
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800555 * @param flowPath the Flow to fix.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800556 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800557 private void fixFlowFromDatabase(FlowPath flowPath) {
558 //
559 // TODO: Bug workaround / fix :
560 // method FlowDatabaseOperation.extractFlowEntry() doesn't
561 // fetch the inPort and outPort, hence we assign them here.
562 //
563 // Assign the inPort and outPort for the Flow Entries
564 for (FlowEntry flowEntry : flowPath.flowEntries()) {
565 // Set the inPort
566 do {
567 if (flowEntry.inPort() != null)
568 break;
569 if (flowEntry.flowEntryMatch() == null)
570 break;
571 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
572 flowEntry.setInPort(inPort);
573 } while (false);
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800574
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800575 // Set the outPort
576 do {
577 if (flowEntry.outPort() != null)
578 break;
579 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
580 if (fa.actionOutput() != null) {
581 Port outPort = new Port(fa.actionOutput().port().value());
582 flowEntry.setOutPort(outPort);
583 break;
584 }
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800585 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800586 } while (false);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800587 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800588 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800589
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800590 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800591 * Process the Switch Dpid events.
592 */
593 private void processSwitchDpidEvents() {
594 Map<Long, Dpid> addedSwitches = new HashMap<Long, Dpid>();
595 Map<Long, Dpid> removedSwitches = new HashMap<Long, Dpid>();
596
597 //
598 // Process all Switch Dpid events and update the appropriate state
599 //
600 for (EventEntry<Dpid> eventEntry : switchDpidEvents) {
601 Dpid dpid = eventEntry.eventData();
602
603 log.debug("SwitchDpid Event: {} {}", eventEntry.eventType(), dpid);
604
605 // Compute the final set of added and removed switches
606 switch (eventEntry.eventType()) {
607 case ENTRY_ADD:
608 addedSwitches.put(dpid.value(), dpid);
609 removedSwitches.remove(dpid.value());
610 break;
611 case ENTRY_REMOVE:
612 addedSwitches.remove(dpid.value());
613 removedSwitches.put(dpid.value(), dpid);
614 break;
615 }
616 }
617
618 //
619 // Remove the Flows from the local cache if the removed
620 // switch is the Source Switch.
621 //
622 // TODO: This search can be expensive for a large number of flows
623 // and should be optmized.
624 //
625 List<FlowId> deleteFlowIds = new LinkedList<FlowId>();
626 for (Dpid switchDpid : removedSwitches.values()) {
627 for (FlowPath flowPath : allFlowPaths.values()) {
628 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
629 if (srcDpid.value() == switchDpid.value())
630 deleteFlowIds.add(flowPath.flowId());
631 }
632 }
633 //
634 // Remove the Flows from the local cache
635 //
636 for (FlowId flowId : deleteFlowIds)
637 allFlowPaths.remove(flowId.value());
638
639 // Get the Flows for the added switches
640 Collection<FlowPath> flowPaths =
641 ParallelFlowDatabaseOperation.getFlowsForSwitches(dbHandler,
642 addedSwitches.values());
643 for (FlowPath flowPath : flowPaths) {
644 allFlowPaths.put(flowPath.flowId().value(), flowPath);
645 }
646 }
647
648 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800649 * Process the Flow ID events.
650 *
651 * @param mySwitches the collection of my switches.
652 */
653 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800654 List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
655
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800656 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800657 // Process all Flow Id events and update the appropriate state
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800658 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800659 for (EventEntry<Pair<FlowId, Dpid>> eventEntry : flowIdEvents) {
660 Pair<FlowId, Dpid> pair = eventEntry.eventData();
661 FlowId flowId = pair.first;
662 Dpid dpid = pair.second;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800663
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800664 log.debug("Flow ID Event: {} {} {}", eventEntry.eventType(),
665 flowId, dpid);
666
667 //
668 // Ignore Flows if the Source Switch is not controlled by this
669 // instance.
670 //
671 if (mySwitches.get(dpid.value()) == null)
672 continue;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800673
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800674 switch (eventEntry.eventType()) {
675 case ENTRY_ADD: {
676 //
677 // Add a new Flow Path
678 //
679 if (allFlowPaths.get(flowId.value()) != null) {
680 //
681 // TODO: What to do if the Flow Path already exists?
682 // Fow now, we just re-add it.
683 //
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800684 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800685 shouldFetchMyFlowIds.add(flowId);
686
687 break;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800688 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800689
690 case ENTRY_REMOVE: {
691 //
692 // Remove an existing Flow Path.
693 //
694 // Find the Flow Path, and mark the Flow and its Flow Entries
695 // for deletion.
696 //
697 FlowPath existingFlowPath =
698 allFlowPaths.get(flowId.value());
699 if (existingFlowPath == null)
700 continue; // Nothing to do
701
702 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
703 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
704 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
705 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
706 }
707
708 // Remove the Flow Path from the internal state
709 Long key = existingFlowPath.flowId().value();
710 allFlowPaths.remove(key);
711 shouldRecomputeFlowPaths.remove(key);
712 modifiedFlowPaths.put(key, existingFlowPath);
713
714 break;
715 }
716 }
717 }
718
719 // Get my Flows
720 Collection<FlowPath> myFlows =
Pavlin Radoslavov6602b6a2014-01-10 16:43:29 -0800721 ParallelFlowDatabaseOperation.getFlows(dbHandler,
722 shouldFetchMyFlowIds);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800723
724 for (FlowPath flowPath : myFlows) {
725 fixFlowFromDatabase(flowPath);
726
727 switch (flowPath.flowPathType()) {
728 case FP_TYPE_SHORTEST_PATH:
729 //
730 // Reset the Data Path, in case it was set already, because
731 // we are going to recompute it anyway.
732 //
733 flowPath.flowEntries().clear();
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800734 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
735 flowPath);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800736 break;
737 case FP_TYPE_EXPLICIT_PATH:
738 //
739 // Mark all Flow Entries for installation in the switches.
740 //
741 for (FlowEntry flowEntry : flowPath.flowEntries()) {
742 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
743 }
744 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
745 break;
746 case FP_TYPE_UNKNOWN:
747 log.error("FlowPath event with unknown type");
748 break;
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800749 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800750 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800751 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800752 }
753
754 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800755 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800756 *
757 * @param mySwitches the collection of my switches.
758 * @return a collection of modified Flow Entries this instance needs
759 * to push to its own switches.
760 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800761 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800762 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
763
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800764 //
765 // Process all Flow ID events and update the appropriate state
766 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800767 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
768 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
769 FlowEntryId flowEntryId = pair.first;
770 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800771
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800772 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
773 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800774
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800775 if (mySwitches.get(dpid.value()) == null)
776 continue;
777
778 // Fetch the Flow Entry
779 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
780 flowEntryId);
781 if (flowEntry == null) {
782 log.debug("Flow Entry ID {} : Flow Entry not found!",
783 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800784 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800785 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800786 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800787 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800788
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800789 return modifiedFlowEntries;
790 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800791
792 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800793 * Process the Flow Path events.
794 */
795 private void processFlowPathEvents() {
796 //
797 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700798 //
799 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
800 FlowPath flowPath = eventEntry.eventData();
801
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800802 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800803
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700804 switch (eventEntry.eventType()) {
805 case ENTRY_ADD: {
806 //
807 // Add a new Flow Path
808 //
809 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
810 //
811 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800812 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700813 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700814 }
815
816 switch (flowPath.flowPathType()) {
817 case FP_TYPE_SHORTEST_PATH:
818 //
819 // Reset the Data Path, in case it was set already, because
820 // we are going to recompute it anyway.
821 //
822 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800823 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
824 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700825 break;
826 case FP_TYPE_EXPLICIT_PATH:
827 //
828 // Mark all Flow Entries for installation in the switches.
829 //
830 for (FlowEntry flowEntry : flowPath.flowEntries()) {
831 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
832 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800833 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700834 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800835 case FP_TYPE_UNKNOWN:
836 log.error("FlowPath event with unknown type");
837 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700838 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800839 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700840
841 break;
842 }
843
844 case ENTRY_REMOVE: {
845 //
846 // Remove an existing Flow Path.
847 //
848 // Find the Flow Path, and mark the Flow and its Flow Entries
849 // for deletion.
850 //
851 FlowPath existingFlowPath =
852 allFlowPaths.get(flowPath.flowId().value());
853 if (existingFlowPath == null)
854 continue; // Nothing to do
855
856 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
857 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
858 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
859 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
860 }
861
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800862 // Remove the Flow Path from the internal state
863 Long key = existingFlowPath.flowId().value();
864 allFlowPaths.remove(key);
865 shouldRecomputeFlowPaths.remove(key);
866 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700867
868 break;
869 }
870 }
871 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800872 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700873
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800874 /**
875 * Process the Topology events.
876 */
877 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800878 boolean isTopologyModified = false;
879
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800880 if (enableOnrc2014MeasurementsTopology) {
881 if (topologyEvents.isEmpty())
882 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800883
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800884 // TODO: Code for debugging purpose only
885 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
886 TopologyElement topologyElement = eventEntry.eventData();
887 log.debug("Topology Event: {} {}", eventEntry.eventType(),
888 topologyElement.toString());
889 }
890
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800891 log.debug("[BEFORE] {}", topology.toString());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800892 topology.readFromDatabase(dbHandler);
893 log.debug("[AFTER] {}", topology.toString());
894 shouldRecomputeFlowPaths.putAll(allFlowPaths);
895 return;
896 }
897
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700898 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800899 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700900 //
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700901 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
902 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800903
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800904 log.debug("Topology Event: {} {}", eventEntry.eventType(),
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800905 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800906
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700907 switch (eventEntry.eventType()) {
908 case ENTRY_ADD:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800909 isTopologyModified |= topology.addTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700910 break;
911 case ENTRY_REMOVE:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800912 isTopologyModified |= topology.removeTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700913 break;
914 }
915 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700916 if (isTopologyModified) {
917 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800918 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700919 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800920 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700921
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800922 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800923 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800924 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800925 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800926 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800927 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800928
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700929 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800930 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700931 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800932 if (! unmatchedFlowEntryAdd.isEmpty()) {
933 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
934 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800935 // log.debug("Processing Unmatched Flow Entry: {}",
936 // flowEntry.toString());
937
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800938 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800939 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800940 remainingUpdates.put(flowEntry.flowEntryId().value(),
941 flowEntry);
942 continue;
943 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800944 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
945 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800946 remainingUpdates.put(flowEntry.flowEntryId().value(),
947 flowEntry);
948 continue;
949 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800950 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
951 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
952 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700953 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800954 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700955 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800956 }
957
958 /**
959 * Process the Flow Entry events.
960 */
961 private void processFlowEntryEvents() {
962 FlowPath flowPath;
963 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700964
965 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800966 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700967 //
968 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
969 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800970
971 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800972 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800973
974 if ((! flowEntry.isValidFlowId()) ||
975 (! flowEntry.isValidFlowEntryId())) {
976 continue;
977 }
978
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700979 switch (eventEntry.eventType()) {
980 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800981 flowPath = allFlowPaths.get(flowEntry.flowId().value());
982 if (flowPath == null) {
983 // Flow Path not found: keep the entry for later matching
984 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
985 flowEntry);
986 break;
987 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800988 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
989 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800990 // Flow Entry not found: keep the entry for later matching
991 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
992 flowEntry);
993 break;
994 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800995 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
996 // Add the updated Flow Path to the list of updated paths
997 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
998 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700999 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001000
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001001 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001002 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1003 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001004 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001005 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001006
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001007 flowPath = allFlowPaths.get(flowEntry.flowId().value());
1008 if (flowPath == null) {
1009 // Flow Path not found: ignore the update
1010 break;
1011 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001012 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
1013 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001014 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001015 break;
1016 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001017 if (updateFlowEntryRemove(flowPath, localFlowEntry,
1018 flowEntry)) {
1019 // Add the updated Flow Path to the list of updated paths
1020 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
1021 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001022 break;
1023 }
1024 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001025 }
1026
1027 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001028 * Find a Flow Entry that should be updated because of an external
1029 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001030 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001031 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001032 * @param newFlowEntry the FlowEntry with the new state.
1033 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001034 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001035 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
1036 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001037 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001038 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001039 //
1040 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001041 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001042 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001043 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001044 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001045
1046 //
1047 // Local Flow Entry match found
1048 //
1049 if (localFlowEntry.isValidFlowEntryId()) {
1050 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001051 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001052 //
1053 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001054 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001055 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001056 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001057 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001058 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001059 return localFlowEntry;
1060 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001061
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001062 return null; // Entry not found
1063 }
1064
1065 /**
1066 * Update a Flow Entry because of an external ENTRY_ADD event.
1067 *
1068 * @param flowPath the FlowPath for the Flow Entry to update.
1069 * @param localFlowEntry the local Flow Entry to update.
1070 * @param newFlowEntry the FlowEntry with the new state.
1071 * @return true if the local Flow Entry was updated, otherwise false.
1072 */
1073 private boolean updateFlowEntryAdd(FlowPath flowPath,
1074 FlowEntry localFlowEntry,
1075 FlowEntry newFlowEntry) {
1076 boolean updated = false;
1077
1078 if (localFlowEntry.flowEntryUserState() ==
1079 FlowEntryUserState.FE_USER_DELETE) {
1080 // Don't add-back a Flow Entry that is already deleted
1081 return false;
1082 }
1083
1084 if (! localFlowEntry.isValidFlowEntryId()) {
1085 // Update the Flow Entry ID
1086 FlowEntryId flowEntryId =
1087 new FlowEntryId(newFlowEntry.flowEntryId().value());
1088 localFlowEntry.setFlowEntryId(flowEntryId);
1089 updated = true;
1090 }
1091
1092 //
1093 // Update the local Flow Entry, and keep state to check
1094 // if the Flow Path has been installed.
1095 //
1096 if (localFlowEntry.flowEntryUserState() !=
1097 newFlowEntry.flowEntryUserState()) {
1098 localFlowEntry.setFlowEntryUserState(
1099 newFlowEntry.flowEntryUserState());
1100 updated = true;
1101 }
1102 if (localFlowEntry.flowEntrySwitchState() !=
1103 newFlowEntry.flowEntrySwitchState()) {
1104 localFlowEntry.setFlowEntrySwitchState(
1105 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -08001106 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001107 updated = true;
1108 }
1109
1110 return updated;
1111 }
1112
1113 /**
1114 * Find a Flow Entry that should be updated because of an external
1115 * ENTRY_REMOVE event.
1116 *
1117 * @param flowPath the FlowPath for the Flow Entry to update.
1118 * @param newFlowEntry the FlowEntry with the new state.
1119 * @return the Flow Entry that should be updated if found, otherwise null.
1120 */
1121 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
1122 FlowEntry newFlowEntry) {
1123 //
1124 // Iterate over all Flow Entries and find a match based on
1125 // the Flow Entry ID.
1126 //
1127 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
1128 if (! localFlowEntry.isValidFlowEntryId())
1129 continue;
1130 if (localFlowEntry.flowEntryId().value() !=
1131 newFlowEntry.flowEntryId().value()) {
1132 continue;
1133 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001134 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001135 }
1136
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001137 return null; // Entry not found
1138 }
1139
1140 /**
1141 * Update a Flow Entry because of an external ENTRY_REMOVE event.
1142 *
1143 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001144 * @param localFlowEntry the local Flow Entry to update.
1145 * @param newFlowEntry the FlowEntry with the new state.
1146 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001147 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001148 private boolean updateFlowEntryRemove(FlowPath flowPath,
1149 FlowEntry localFlowEntry,
1150 FlowEntry newFlowEntry) {
1151 boolean updated = false;
1152
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001153 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001154 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001155 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001156 if (localFlowEntry.flowEntryUserState() !=
1157 newFlowEntry.flowEntryUserState()) {
1158 localFlowEntry.setFlowEntryUserState(
1159 newFlowEntry.flowEntryUserState());
1160 updated = true;
1161 }
1162 if (localFlowEntry.flowEntrySwitchState() !=
1163 newFlowEntry.flowEntrySwitchState()) {
1164 localFlowEntry.setFlowEntrySwitchState(
1165 newFlowEntry.flowEntrySwitchState());
1166 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001167 }
1168
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001169 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001170 }
1171
1172 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001173 * Recompute a Flow Path.
1174 *
1175 * @param flowPath the Flow Path to recompute.
1176 * @return true if the recomputed Flow Path has changed, otherwise false.
1177 */
1178 private boolean recomputeFlowPath(FlowPath flowPath) {
1179 boolean hasChanged = false;
1180
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001181 if (enableOnrc2014MeasurementsFlows) {
1182 // Cleanup the deleted Flow Entries from the earlier iteration
1183 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -08001184
1185 //
1186 // TODO: Fake it that the Flow Entries have been already pushed
1187 // into the switches, so we don't push them again.
1188 //
1189 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1190 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1191 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001192 }
1193
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001194 //
1195 // Test whether the Flow Path needs to be recomputed
1196 //
1197 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001198 case FP_TYPE_UNKNOWN:
1199 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001200 case FP_TYPE_SHORTEST_PATH:
1201 break;
1202 case FP_TYPE_EXPLICIT_PATH:
1203 return false; // An explicit path never changes
1204 }
1205
1206 DataPath oldDataPath = flowPath.dataPath();
1207
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001208 // Compute the new path
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001209 DataPath newDataPath;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001210 newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001211 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001212 if (newDataPath == null) {
1213 // We need the DataPath to compare the paths
1214 newDataPath = new DataPath();
1215 }
1216 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1217
1218 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001219 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001220 //
1221 if (oldDataPath.flowEntries().size() !=
1222 newDataPath.flowEntries().size()) {
1223 hasChanged = true;
1224 } else {
1225 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1226 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1227 while (oldIter.hasNext() && newIter.hasNext()) {
1228 FlowEntry oldFlowEntry = oldIter.next();
1229 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001230 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1231 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001232 hasChanged = true;
1233 break;
1234 }
1235 }
1236 }
1237 if (! hasChanged)
1238 return hasChanged;
1239
1240 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001241 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001242 // - If a Flow Entry for a switch is in the old data path, but not
1243 // in the new data path, then mark it for deletion.
1244 // - If a Flow Entry for a switch is in the new data path, but not
1245 // in the old data path, then mark it for addition.
1246 // - If a Flow Entry for a switch is in both the old and the new
1247 // data path, but it has changed, e.g., the incoming and/or outgoing
1248 // port(s), then mark the old Flow Entry for deletion, and mark
1249 // the new Flow Entry for addition.
1250 // - If a Flow Entry for a switch is in both the old and the new
1251 // data path, and it hasn't changed, then just keep it.
1252 //
1253 // NOTE: We use the Switch DPID of each entry to match the entries
1254 //
1255 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1256 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1257 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1258 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1259
1260 // Prepare maps with the Flow Entries, so they are fast to lookup
1261 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1262 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1263 for (FlowEntry flowEntry : newDataPath.flowEntries())
1264 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1265
1266 //
1267 // Find the old Flow Entries that should be deleted
1268 //
1269 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1270 FlowEntry newFlowEntry =
1271 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1272 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001273 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001274 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1275 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1276 deletedFlowEntries.add(oldFlowEntry);
1277 }
1278 }
1279
1280 //
1281 // Find the new Flow Entries that should be added or updated
1282 //
1283 int idx = 0;
1284 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1285 FlowEntry oldFlowEntry =
1286 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1287
1288 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001289 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1290 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001291 //
1292 // Both Flow Entries are same
1293 //
1294 finalFlowEntries.add(oldFlowEntry);
1295 idx++;
1296 continue;
1297 }
1298
1299 if (oldFlowEntry != null) {
1300 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001301 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001302 //
1303 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1304 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1305 deletedFlowEntries.add(oldFlowEntry);
1306 }
1307
1308 //
1309 // Add the new Flow Entry
1310 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001311 //
1312 // NOTE: Assign only the Flow ID.
1313 // The Flow Entry ID is assigned later only for the Flow Entries
1314 // this instance is responsible for.
1315 //
1316 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001317
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001318 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001319 // Copy the Flow timeouts
1320 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001321 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -08001322 newFlowEntry.setPriority(flowPath.priority());
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001323
TeruU417fe022014-02-04 12:59:30 -08001324 if (flowPath.idleTimeout() > 0) {
1325 if (idx == 0) {
1326 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1327 }
1328 else {
1329 newFlowEntry.setIdleTimeout(flowPath.idleTimeout() + FLOW_IDLE_TIMEOUT_ADDED_SECONDS);
1330 }
1331 } else if(flowPath.idleTimeout() == 0) {
1332 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1333 }
1334
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001335 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001336 // Allocate the FlowEntryMatch by copying the default one
1337 // from the FlowPath (if set).
1338 //
1339 FlowEntryMatch flowEntryMatch = null;
1340 if (flowPath.flowEntryMatch() != null)
1341 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1342 else
1343 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001344 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001345
1346 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001347 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1348
1349 //
1350 // Set the actions:
1351 // If the first Flow Entry, copy the Flow Path actions to it.
1352 //
1353 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1354 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1355 FlowEntryActions flowActions =
1356 new FlowEntryActions(flowPath.flowEntryActions());
1357 for (FlowEntryAction action : flowActions.actions())
1358 flowEntryActions.addAction(action);
1359 }
1360 idx++;
1361
1362 //
1363 // Add the outgoing port output action
1364 //
1365 FlowEntryAction flowEntryAction = new FlowEntryAction();
1366 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1367 flowEntryActions.addAction(flowEntryAction);
1368
1369 //
1370 // Set the state of the new Flow Entry
1371 //
1372 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1373 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1374 finalFlowEntries.add(newFlowEntry);
1375 }
1376
1377 //
1378 // Replace the old Flow Entries with the new Flow Entries.
1379 // Note that the Flow Entries that will be deleted are added at
1380 // the end.
1381 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001382 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001383 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1384
1385 return hasChanged;
1386 }
1387
1388 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001389 * Receive a notification that a Flow is added.
1390 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001391 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001392 */
1393 @Override
1394 public void notificationRecvFlowAdded(FlowPath flowPath) {
1395 EventEntry<FlowPath> eventEntry =
1396 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1397 networkEvents.add(eventEntry);
1398 }
1399
1400 /**
1401 * Receive a notification that a Flow is removed.
1402 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001403 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001404 */
1405 @Override
1406 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1407 EventEntry<FlowPath> eventEntry =
1408 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1409 networkEvents.add(eventEntry);
1410 }
1411
1412 /**
1413 * Receive a notification that a Flow is updated.
1414 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001415 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001416 */
1417 @Override
1418 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1419 // NOTE: The ADD and UPDATE events are processed in same way
1420 EventEntry<FlowPath> eventEntry =
1421 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1422 networkEvents.add(eventEntry);
1423 }
1424
1425 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001426 * Receive a notification that a FlowEntry is added.
1427 *
1428 * @param flowEntry the FlowEntry that is added.
1429 */
1430 @Override
1431 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001432 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001433// String tag = "EventHandler.AddFlowEntryToSwitch." + flowEntry.flowEntryId();
1434 String tag = "EventHandler.AddFlowEntryToSwitch";
1435 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001436 Collection entries = new ArrayList();
1437 entries.add(flowEntry);
1438 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001439// PerformanceMonitor.stop(tag);
1440 m.stop();
1441// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001442 return;
1443 }
1444
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001445 EventEntry<FlowEntry> eventEntry =
1446 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1447 networkEvents.add(eventEntry);
1448 }
1449
1450 /**
1451 * Receive a notification that a FlowEntry is removed.
1452 *
1453 * @param flowEntry the FlowEntry that is removed.
1454 */
1455 @Override
1456 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001457 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001458// String tag = "EventHandler.RemoveFlowEntryFromSwitch." + flowEntry.flowEntryId();
1459 String tag = "EventHandler.RemoveFlowEntryFromSwitch";
1460 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavove4d2a432014-01-10 12:01:08 -08001461 //
1462 // NOTE: Must update the state to DELETE, because
1463 // the notification contains the original state.
1464 //
1465 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1466
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001467 Collection entries = new ArrayList();
1468 entries.add(flowEntry);
1469 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001470// PerformanceMonitor.stop(tag);
1471 m.stop();
1472// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001473 return;
1474 }
1475
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001476 EventEntry<FlowEntry> eventEntry =
1477 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1478 networkEvents.add(eventEntry);
1479 }
1480
1481 /**
1482 * Receive a notification that a FlowEntry is updated.
1483 *
1484 * @param flowEntry the FlowEntry that is updated.
1485 */
1486 @Override
1487 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001488 if (enableOnrc2014MeasurementsFlows) {
1489 Collection entries = new ArrayList();
1490 entries.add(flowEntry);
1491 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1492 return;
1493 }
1494
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001495 // NOTE: The ADD and UPDATE events are processed in same way
1496 EventEntry<FlowEntry> eventEntry =
1497 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1498 networkEvents.add(eventEntry);
1499 }
1500
1501 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001502 * Receive a notification that a FlowId is added.
1503 *
1504 * @param flowId the FlowId that is added.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001505 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001506 */
1507 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001508 public void notificationRecvFlowIdAdded(FlowId flowId, Dpid dpid) {
1509 Pair flowIdPair = new Pair(flowId, dpid);
1510
1511 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1512 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001513 networkEvents.add(eventEntry);
1514 }
1515
1516 /**
1517 * Receive a notification that a FlowId is removed.
1518 *
1519 * @param flowId the FlowId that is removed.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001520 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001521 */
1522 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001523 public void notificationRecvFlowIdRemoved(FlowId flowId, Dpid dpid) {
1524 Pair flowIdPair = new Pair(flowId, dpid);
1525
1526 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1527 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001528 networkEvents.add(eventEntry);
1529 }
1530
1531 /**
1532 * Receive a notification that a FlowId is updated.
1533 *
1534 * @param flowId the FlowId that is updated.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001535 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001536 */
1537 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001538 public void notificationRecvFlowIdUpdated(FlowId flowId, Dpid dpid) {
1539 Pair flowIdPair = new Pair(flowId, dpid);
1540
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001541 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001542 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1543 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001544 networkEvents.add(eventEntry);
1545 }
1546
1547 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001548 * Receive a notification that a FlowEntryId is added.
1549 *
1550 * @param flowEntryId the FlowEntryId that is added.
1551 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1552 */
1553 @Override
1554 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1555 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001556 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1557
1558 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1559 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001560 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001561 }
1562
1563 /**
1564 * Receive a notification that a FlowEntryId is removed.
1565 *
1566 * @param flowEntryId the FlowEntryId that is removed.
1567 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1568 */
1569 @Override
1570 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1571 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001572 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1573
1574 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1575 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001576 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001577 }
1578
1579 /**
1580 * Receive a notification that a FlowEntryId is updated.
1581 *
1582 * @param flowEntryId the FlowEntryId that is updated.
1583 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1584 */
1585 @Override
1586 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1587 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001588 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1589
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001590 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001591 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1592 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001593 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001594 }
1595
1596 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001597 * Receive a notification that a Topology Element is added.
1598 *
1599 * @param topologyElement the Topology Element that is added.
1600 */
1601 @Override
1602 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1603 EventEntry<TopologyElement> eventEntry =
1604 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1605 networkEvents.add(eventEntry);
1606 }
1607
1608 /**
1609 * Receive a notification that a Topology Element is removed.
1610 *
1611 * @param topologyElement the Topology Element that is removed.
1612 */
1613 @Override
1614 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1615 EventEntry<TopologyElement> eventEntry =
1616 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1617 networkEvents.add(eventEntry);
1618 }
1619
1620 /**
1621 * Receive a notification that a Topology Element is updated.
1622 *
1623 * @param topologyElement the Topology Element that is updated.
1624 */
1625 @Override
1626 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1627 // NOTE: The ADD and UPDATE events are processed in same way
1628 EventEntry<TopologyElement> eventEntry =
1629 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1630 networkEvents.add(eventEntry);
1631 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001632
1633 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -08001634 * Receive a notification that a switch is added to this instance.
1635 *
1636 * @param sw the switch that is added.
1637 */
1638 @Override
1639 public void addedSwitch(IOFSwitch sw) {
1640 Dpid dpid = new Dpid(sw.getId());
1641 EventEntry<Dpid> eventEntry =
1642 new EventEntry<Dpid>(EventEntry.Type.ENTRY_ADD, dpid);
1643 networkEvents.add(eventEntry);
1644 }
1645
1646 /**
1647 * Receive a notification that a switch is removed from this instance.
1648 *
1649 * @param sw the switch that is removed.
1650 */
1651 @Override
1652 public void removedSwitch(IOFSwitch sw) {
1653 Dpid dpid = new Dpid(sw.getId());
1654 EventEntry<Dpid> eventEntry =
1655 new EventEntry<Dpid>(EventEntry.Type.ENTRY_REMOVE, dpid);
1656 networkEvents.add(eventEntry);
1657 }
1658
1659 /**
1660 * Receive a notification that the ports on a switch have changed.
1661 */
1662 @Override
1663 public void switchPortChanged(Long switchId) {
1664 // Nothing to do
1665 }
1666
1667 /**
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001668 * Get a sorted copy of all Flow Paths.
1669 *
1670 * @return a sorted copy of all Flow Paths.
1671 */
1672 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1673 SortedMap<Long, FlowPath> sortedFlowPaths =
1674 new TreeMap<Long, FlowPath>();
1675
1676 //
1677 // TODO: For now we use serialization/deserialization to create
1678 // a copy of each Flow Path. In the future, we should use proper
1679 // copy constructors.
1680 //
1681 Kryo kryo = kryoFactory.newKryo();
1682 synchronized (allFlowPaths) {
1683 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1684 FlowPath origFlowPath = entry.getValue();
1685 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1686 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1687 }
1688 }
1689 kryoFactory.deleteKryo(kryo);
1690
1691 return sortedFlowPaths;
1692 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001693}