blob: 5ff1dc5a0a8f42eb9ebad205d2c970171eb6fd70 [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
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -080054 private boolean enableOnrc2014MeasurementsFlows = true;
55 private boolean enableOnrc2014MeasurementsTopology = true;
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);
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070059
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -080060 private DBOperation dbHandler;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -080061
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070062 private FlowManager flowManager; // The Flow Manager to use
63 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070064 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080065 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070066
67 // The queue with Flow Path and Topology Element updates
68 private BlockingQueue<EventEntry<?>> networkEvents =
69 new LinkedBlockingQueue<EventEntry<?>>();
70
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070071 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070072 private List<EventEntry<TopologyElement>> topologyEvents =
73 new LinkedList<EventEntry<TopologyElement>>();
74 private List<EventEntry<FlowPath>> flowPathEvents =
75 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070076 private List<EventEntry<FlowEntry>> flowEntryEvents =
77 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2194d112014-01-10 13:36:00 -080078 private List<EventEntry<Pair<FlowId, Dpid>>> flowIdEvents =
79 new LinkedList<EventEntry<Pair<FlowId, Dpid>>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080080 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
81 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080082 private List<EventEntry<Dpid>> switchDpidEvents =
83 new LinkedList<EventEntry<Dpid>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070084
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080085 // All internally computed Flow Paths
86 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
87
88 // The Flow Entries received as notifications with unmatched Flow Paths
89 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
90 new HashMap<Long, FlowEntry>();
91
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080092 //
93 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080094 // - The Flow Paths that should be recomputed
95 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -080096 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080097 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080098 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
99 new HashMap<Long, FlowPath>();
100 private Map<Long, FlowPath> modifiedFlowPaths =
101 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800102 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
103 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800104
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700105 /**
106 * Constructor for a given Flow Manager and Datagrid Service.
107 *
108 * @param flowManager the Flow Manager to use.
109 * @param datagridService the Datagrid Service to use.
110 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700111 FlowEventHandler(FlowManager flowManager,
112 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700113 this.flowManager = flowManager;
114 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700115 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700116 }
117
118 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800119 * Get the network topology.
120 *
121 * @return the network topology.
122 */
123 protected Topology getTopology() { return this.topology; }
124
125 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800126 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700127 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800128 private void startup() {
Yoshi Muroi5804ce92014-02-08 03:58:04 -0800129 this.dbHandler = GraphDBManager.getDBOperation();
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800130
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700131 //
132 // Obtain the initial Topology state
133 //
134 Collection<TopologyElement> topologyElements =
135 datagridService.getAllTopologyElements();
136 for (TopologyElement topologyElement : topologyElements) {
137 EventEntry<TopologyElement> eventEntry =
138 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
139 topologyEvents.add(eventEntry);
140 }
141 //
142 // Obtain the initial Flow Path state
143 //
144 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
145 for (FlowPath flowPath : flowPaths) {
146 EventEntry<FlowPath> eventEntry =
147 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
148 flowPathEvents.add(eventEntry);
149 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700150 //
151 // Obtain the initial FlowEntry state
152 //
153 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
154 for (FlowEntry flowEntry : flowEntries) {
155 EventEntry<FlowEntry> eventEntry =
156 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
157 flowEntryEvents.add(eventEntry);
158 }
159
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800160 //
161 // Obtain the initial FlowId state
162 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800163 Collection<Pair<FlowId, Dpid>> flowIds =
164 datagridService.getAllFlowIds();
165 for (Pair<FlowId, Dpid> pair : flowIds) {
166 EventEntry<Pair<FlowId, Dpid>> eventEntry =
167 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800168 flowIdEvents.add(eventEntry);
169 }
170
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800171 //
172 // Obtain the initial FlowEntryId state
173 //
174 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
175 datagridService.getAllFlowEntryIds();
176 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
177 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
178 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
179 flowEntryIdEvents.add(eventEntry);
180 }
181
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800182 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800183 synchronized (allFlowPaths) {
184 processEvents();
185 }
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800186
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800187 }
188
189 /**
190 * Run the thread.
191 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800192 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800193 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800194 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800195 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700196
197 //
198 // The main loop
199 //
200 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
201 try {
202 while (true) {
203 EventEntry<?> eventEntry = networkEvents.take();
204 collection.add(eventEntry);
205 networkEvents.drainTo(collection);
206
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700207 //
208 // Demultiplex all events:
209 // - EventEntry<TopologyElement>
210 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700211 // - EventEntry<FlowEntry>
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800212 // - EventEntry<Pair<FlowId, Dpid>>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800213 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700214 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700215 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800216 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700217 if (event.eventData() instanceof TopologyElement) {
218 EventEntry<TopologyElement> topologyEventEntry =
219 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800220
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700221 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800222 continue;
223 }
224
225 // FlowPath event
226 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700227 EventEntry<FlowPath> flowPathEventEntry =
228 (EventEntry<FlowPath>)event;
229 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800230 continue;
231 }
232
233 // FlowEntry event
234 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700235 EventEntry<FlowEntry> flowEntryEventEntry =
236 (EventEntry<FlowEntry>)event;
237 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800238 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700239 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800240
241 // FlowId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800242 if (event.eventData() instanceof Pair) {
243 EventEntry<Pair<FlowId, Dpid>> flowIdEventEntry =
244 (EventEntry<Pair<FlowId, Dpid>>)event;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800245 flowIdEvents.add(flowIdEventEntry);
246 continue;
247 }
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800248
249 // Switch Dpid event
250 if (event.eventData() instanceof Dpid) {
251 EventEntry<Dpid> switchDpidEventEntry =
252 (EventEntry<Dpid>)event;
253 switchDpidEvents.add(switchDpidEventEntry);
254 continue;
255 }
256
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800257 // FlowEntryId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800258 // TODO: Fix the code below if we need again to handle
259 // the FlowEntryId events
260 /*
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800261 if (event.eventData() instanceof Pair) {
262 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
263 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
264 flowEntryIdEvents.add(flowEntryIdEventEntry);
265 continue;
266 }
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800267 */
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700268 }
269 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700270
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700271 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800272 synchronized (allFlowPaths) {
273 processEvents();
274 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700275 }
276 } catch (Exception exception) {
277 log.debug("Exception processing Network Events: ", exception);
278 }
279 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800280
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700281 /**
282 * Process the events (if any)
283 */
284 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800285 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700286
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800287 if (enableOnrc2014MeasurementsFlows) {
288
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800289 PerformanceMonitor.start("EventHandler.ProcessAllEvents");
290
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800291 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
292 switchDpidEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800293 return; // Nothing to do
294 }
295
296 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
297
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800298 // Process the Switch Dpid events
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800299 PerformanceMonitor.start("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800300 processSwitchDpidEvents();
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800301 PerformanceMonitor.stop("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800302
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800303 // Process the Flow ID events
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800304 PerformanceMonitor.start("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800305 processFlowIdEvents(mySwitches);
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800306 PerformanceMonitor.stop("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800307
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800308 // Fetch the topology
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800309 PerformanceMonitor.start("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800310 processTopologyEvents();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800311 PerformanceMonitor.stop("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800312
313 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800314 PerformanceMonitor.start("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800315 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
316 if (recomputeFlowPath(flowPath))
317 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
318 }
319
320 // Assign the Flow Entry ID as needed
321 for (FlowPath flowPath : modifiedFlowPaths.values()) {
322 for (FlowEntry flowEntry : flowPath.flowEntries()) {
323 if (! flowEntry.isValidFlowEntryId()) {
324 long id = flowManager.getNextFlowEntryId();
325 flowEntry.setFlowEntryId(new FlowEntryId(id));
326 }
327 }
328 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800329 PerformanceMonitor.stop("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800330
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800331 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800332 // Push the modified state to the database
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800333 //
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800334 PerformanceMonitor.start("EventHandler.WriteFlowsToDb");
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800335 for (FlowPath flowPath : modifiedFlowPaths.values()) {
336 //
337 // Delete the Flow Path from the Network Map
338 //
339 if (flowPath.flowPathUserState() ==
340 FlowPathUserState.FP_USER_DELETE) {
341 log.debug("Deleting Flow Path From Database: {}", flowPath);
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800342 // TODO: For now the deleting of a Flow Path is blocking
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800343 ParallelFlowDatabaseOperation.deleteFlow(dbHandler,
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800344 flowPath.flowId());
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800345 //
346 // NOTE: For now the sending of the notifications
347 // is outside of this loop, so the performance measurements
348 // are more accurate.
349 //
350 /*
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800351 // Send the notifications for the deleted Flow Entries
352 for (FlowEntry flowEntry : flowPath.flowEntries()) {
353 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
354 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800355 */
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800356
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800357 continue;
358 }
359
360 log.debug("Pushing Flow Path To Database: {}", flowPath);
361 //
362 // Write the Flow Path to the Network Map
363 //
364 ParallelFlowDatabaseOperation.addFlow(dbHandler, flowPath,
365 datagridService);
366 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800367 PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
368
369 //
370 // Send the notifications for the deleted Flow Entries
371 // NOTE: This code was pulled outside of the above loop,
372 // so the performance measurements are more accurate.
373 //
374 PerformanceMonitor.start("EventHandler.NotificationSend.FlowEntryRemoved");
375 for (FlowPath flowPath : modifiedFlowPaths.values()) {
376 if (flowPath.flowPathUserState() ==
377 FlowPathUserState.FP_USER_DELETE) {
378 for (FlowEntry flowEntry : flowPath.flowEntries()) {
379 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
380 }
381 }
382 }
Pavlin Radoslavovdbd09cc2014-01-12 18:13:35 -0800383 PerformanceMonitor.stop("EventHandler.NotificationSend.FlowEntryRemoved");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800384
385 // Cleanup
386 topologyEvents.clear();
387 flowIdEvents.clear();
Pavlin Radoslavov2d6e5f12014-01-10 16:34:05 -0800388 switchDpidEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800389 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800390 // NOTE: Keep a cache with my Flow Paths
391 // allFlowPaths.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800392 shouldRecomputeFlowPaths.clear();
393 modifiedFlowPaths.clear();
394
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800395 PerformanceMonitor.stop("EventHandler.ProcessAllEvents");
Pavlin Radoslavov8bd6d112014-01-12 20:12:37 -0800396
397
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800398// PerformanceMonitor.report("EventHandler.SwitchDpidEvents");
399// PerformanceMonitor.report("EventHandler.FlowIdEvents");
400// PerformanceMonitor.report("EventHandler.ReadTopology");
401// PerformanceMonitor.report("EventHandler.RecomputeFlows");
402// PerformanceMonitor.report("EventHandler.WriteFlowsToDb");
403// PerformanceMonitor.report("EventHandler.NotificationSend.FlowEntryRemoved");
404// PerformanceMonitor.report("EventHandler.ProcessAllEvents");
Brian O'Connor0d9963f2014-01-14 14:44:21 -0800405// PerformanceMonitor.report();
406// PerformanceMonitor.clear();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800407
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800408 return;
409 }
410
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700411 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
412 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700413 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700414 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700415
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800416 processFlowPathEvents();
417 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800418 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800419 processFlowEntryEvents();
420
421 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800422 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800423 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800424 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800425 }
426
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800427 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800428 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800429
430 // Assign missing Flow Entry IDs
431 assignFlowEntryId(modifiedFlowEntries);
432
433 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800434 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800435 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800436 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
437 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800438
439 //
440 // Remove Flow Entries that were deleted
441 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800442 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800443 flowPath.dataPath().removeDeletedFlowEntries();
444
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800445 //
446 // Check if Flow Paths have been installed into all switches,
447 // and generate the appropriate events.
448 //
449 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
450
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800451 // Cleanup
452 topologyEvents.clear();
453 flowPathEvents.clear();
454 flowEntryEvents.clear();
455 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800456 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800457 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800458 checkIfInstalledFlowPaths.clear();
459 }
460
461 /**
462 * Check if Flow Paths have been installed into all switches,
463 * and generate the appropriate events.
464 *
465 * @param flowPaths the flowPaths to process.
466 */
467 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
468 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
469
470 Kryo kryo = kryoFactory.newKryo();
471
472 for (FlowPath flowPath : flowPaths) {
473 boolean isInstalled = true;
Jonathan Hart0444d932014-01-22 15:06:17 -0800474
475 if (flowPath.flowEntries().isEmpty()) {
476 continue;
477 }
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800478
479 //
480 // Check whether all Flow Entries have been installed
481 //
482 for (FlowEntry flowEntry : flowPath.flowEntries()) {
483 if (flowEntry.flowEntrySwitchState() !=
484 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
485 isInstalled = false;
486 break;
487 }
488 }
489
490 if (isInstalled) {
491 // Create a copy and add it to the list
492 FlowPath copyFlowPath = kryo.copy(flowPath);
493 installedFlowPaths.add(copyFlowPath);
494 }
495 }
496 kryoFactory.deleteKryo(kryo);
497
498 // Generate an event for the installed Flow Path.
499 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800500 }
501
502 /**
503 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800504 *
505 * @param modifiedFlowPaths the Flow Paths to process.
506 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800507 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800508 private Collection<FlowEntry> extractModifiedFlowEntries(
509 Collection<FlowPath> modifiedFlowPaths) {
510 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800511
512 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800513 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800514 for (FlowEntry flowEntry : flowPath.flowEntries()) {
515 if (flowEntry.flowEntrySwitchState() ==
516 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800517 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800518 }
519 }
520 }
521 return modifiedFlowEntries;
522 }
523
524 /**
525 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800526 *
527 * @param modifiedFlowEnries the collection of Flow Entries that need
528 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800529 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800530 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800531 if (modifiedFlowEntries.isEmpty())
532 return;
533
534 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
535
536 //
537 // Assign the Flow Entry ID only for Flow Entries for my switches
538 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800539 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800540 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
541 if (mySwitch == null)
542 continue;
543 if (! flowEntry.isValidFlowEntryId()) {
544 long id = flowManager.getNextFlowEntryId();
545 flowEntry.setFlowEntryId(new FlowEntryId(id));
546 }
547 }
548 }
549
550 /**
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800551 * Fix a flow fetched from the database.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800552 *
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800553 * @param flowPath the Flow to fix.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800554 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800555 private void fixFlowFromDatabase(FlowPath flowPath) {
556 //
557 // TODO: Bug workaround / fix :
558 // method FlowDatabaseOperation.extractFlowEntry() doesn't
559 // fetch the inPort and outPort, hence we assign them here.
560 //
561 // Assign the inPort and outPort for the Flow Entries
562 for (FlowEntry flowEntry : flowPath.flowEntries()) {
563 // Set the inPort
564 do {
565 if (flowEntry.inPort() != null)
566 break;
567 if (flowEntry.flowEntryMatch() == null)
568 break;
569 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
570 flowEntry.setInPort(inPort);
571 } while (false);
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800572
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800573 // Set the outPort
574 do {
575 if (flowEntry.outPort() != null)
576 break;
577 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
578 if (fa.actionOutput() != null) {
579 Port outPort = new Port(fa.actionOutput().port().value());
580 flowEntry.setOutPort(outPort);
581 break;
582 }
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800583 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800584 } while (false);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800585 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800586 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800587
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800588 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800589 * Process the Switch Dpid events.
590 */
591 private void processSwitchDpidEvents() {
592 Map<Long, Dpid> addedSwitches = new HashMap<Long, Dpid>();
593 Map<Long, Dpid> removedSwitches = new HashMap<Long, Dpid>();
594
595 //
596 // Process all Switch Dpid events and update the appropriate state
597 //
598 for (EventEntry<Dpid> eventEntry : switchDpidEvents) {
599 Dpid dpid = eventEntry.eventData();
600
601 log.debug("SwitchDpid Event: {} {}", eventEntry.eventType(), dpid);
602
603 // Compute the final set of added and removed switches
604 switch (eventEntry.eventType()) {
605 case ENTRY_ADD:
606 addedSwitches.put(dpid.value(), dpid);
607 removedSwitches.remove(dpid.value());
608 break;
609 case ENTRY_REMOVE:
610 addedSwitches.remove(dpid.value());
611 removedSwitches.put(dpid.value(), dpid);
612 break;
613 }
614 }
615
616 //
617 // Remove the Flows from the local cache if the removed
618 // switch is the Source Switch.
619 //
620 // TODO: This search can be expensive for a large number of flows
621 // and should be optmized.
622 //
623 List<FlowId> deleteFlowIds = new LinkedList<FlowId>();
624 for (Dpid switchDpid : removedSwitches.values()) {
625 for (FlowPath flowPath : allFlowPaths.values()) {
626 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
627 if (srcDpid.value() == switchDpid.value())
628 deleteFlowIds.add(flowPath.flowId());
629 }
630 }
631 //
632 // Remove the Flows from the local cache
633 //
634 for (FlowId flowId : deleteFlowIds)
635 allFlowPaths.remove(flowId.value());
636
637 // Get the Flows for the added switches
638 Collection<FlowPath> flowPaths =
639 ParallelFlowDatabaseOperation.getFlowsForSwitches(dbHandler,
640 addedSwitches.values());
641 for (FlowPath flowPath : flowPaths) {
642 allFlowPaths.put(flowPath.flowId().value(), flowPath);
643 }
644 }
645
646 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800647 * Process the Flow ID events.
648 *
649 * @param mySwitches the collection of my switches.
650 */
651 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800652 List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
653
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800654 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800655 // Process all Flow Id events and update the appropriate state
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800656 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800657 for (EventEntry<Pair<FlowId, Dpid>> eventEntry : flowIdEvents) {
658 Pair<FlowId, Dpid> pair = eventEntry.eventData();
659 FlowId flowId = pair.first;
660 Dpid dpid = pair.second;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800661
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800662 log.debug("Flow ID Event: {} {} {}", eventEntry.eventType(),
663 flowId, dpid);
664
665 //
666 // Ignore Flows if the Source Switch is not controlled by this
667 // instance.
668 //
669 if (mySwitches.get(dpid.value()) == null)
670 continue;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800671
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800672 switch (eventEntry.eventType()) {
673 case ENTRY_ADD: {
674 //
675 // Add a new Flow Path
676 //
677 if (allFlowPaths.get(flowId.value()) != null) {
678 //
679 // TODO: What to do if the Flow Path already exists?
680 // Fow now, we just re-add it.
681 //
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800682 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800683 shouldFetchMyFlowIds.add(flowId);
684
685 break;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800686 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800687
688 case ENTRY_REMOVE: {
689 //
690 // Remove an existing Flow Path.
691 //
692 // Find the Flow Path, and mark the Flow and its Flow Entries
693 // for deletion.
694 //
695 FlowPath existingFlowPath =
696 allFlowPaths.get(flowId.value());
697 if (existingFlowPath == null)
698 continue; // Nothing to do
699
700 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
701 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
702 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
703 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
704 }
705
706 // Remove the Flow Path from the internal state
707 Long key = existingFlowPath.flowId().value();
708 allFlowPaths.remove(key);
709 shouldRecomputeFlowPaths.remove(key);
710 modifiedFlowPaths.put(key, existingFlowPath);
711
712 break;
713 }
714 }
715 }
716
717 // Get my Flows
718 Collection<FlowPath> myFlows =
Pavlin Radoslavov6602b6a2014-01-10 16:43:29 -0800719 ParallelFlowDatabaseOperation.getFlows(dbHandler,
720 shouldFetchMyFlowIds);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800721
722 for (FlowPath flowPath : myFlows) {
723 fixFlowFromDatabase(flowPath);
724
725 switch (flowPath.flowPathType()) {
726 case FP_TYPE_SHORTEST_PATH:
727 //
728 // Reset the Data Path, in case it was set already, because
729 // we are going to recompute it anyway.
730 //
731 flowPath.flowEntries().clear();
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800732 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
733 flowPath);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800734 break;
735 case FP_TYPE_EXPLICIT_PATH:
736 //
737 // Mark all Flow Entries for installation in the switches.
738 //
739 for (FlowEntry flowEntry : flowPath.flowEntries()) {
740 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
741 }
742 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
743 break;
744 case FP_TYPE_UNKNOWN:
745 log.error("FlowPath event with unknown type");
746 break;
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800747 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800748 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800749 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800750 }
751
752 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800753 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800754 *
755 * @param mySwitches the collection of my switches.
756 * @return a collection of modified Flow Entries this instance needs
757 * to push to its own switches.
758 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800759 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800760 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
761
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800762 //
763 // Process all Flow ID events and update the appropriate state
764 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800765 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
766 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
767 FlowEntryId flowEntryId = pair.first;
768 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800769
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800770 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
771 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800772
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800773 if (mySwitches.get(dpid.value()) == null)
774 continue;
775
776 // Fetch the Flow Entry
777 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
778 flowEntryId);
779 if (flowEntry == null) {
780 log.debug("Flow Entry ID {} : Flow Entry not found!",
781 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800782 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800783 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800784 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800785 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800786
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800787 return modifiedFlowEntries;
788 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800789
790 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800791 * Process the Flow Path events.
792 */
793 private void processFlowPathEvents() {
794 //
795 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700796 //
797 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
798 FlowPath flowPath = eventEntry.eventData();
799
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800800 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800801
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700802 switch (eventEntry.eventType()) {
803 case ENTRY_ADD: {
804 //
805 // Add a new Flow Path
806 //
807 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
808 //
809 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800810 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700811 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700812 }
813
814 switch (flowPath.flowPathType()) {
815 case FP_TYPE_SHORTEST_PATH:
816 //
817 // Reset the Data Path, in case it was set already, because
818 // we are going to recompute it anyway.
819 //
820 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800821 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
822 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700823 break;
824 case FP_TYPE_EXPLICIT_PATH:
825 //
826 // Mark all Flow Entries for installation in the switches.
827 //
828 for (FlowEntry flowEntry : flowPath.flowEntries()) {
829 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
830 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800831 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700832 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800833 case FP_TYPE_UNKNOWN:
834 log.error("FlowPath event with unknown type");
835 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700836 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800837 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700838
839 break;
840 }
841
842 case ENTRY_REMOVE: {
843 //
844 // Remove an existing Flow Path.
845 //
846 // Find the Flow Path, and mark the Flow and its Flow Entries
847 // for deletion.
848 //
849 FlowPath existingFlowPath =
850 allFlowPaths.get(flowPath.flowId().value());
851 if (existingFlowPath == null)
852 continue; // Nothing to do
853
854 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
855 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
856 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
857 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
858 }
859
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800860 // Remove the Flow Path from the internal state
861 Long key = existingFlowPath.flowId().value();
862 allFlowPaths.remove(key);
863 shouldRecomputeFlowPaths.remove(key);
864 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700865
866 break;
867 }
868 }
869 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800870 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700871
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800872 /**
873 * Process the Topology events.
874 */
875 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800876 boolean isTopologyModified = false;
877
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800878 if (enableOnrc2014MeasurementsTopology) {
879 if (topologyEvents.isEmpty())
880 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800881
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800882 // TODO: Code for debugging purpose only
883 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
884 TopologyElement topologyElement = eventEntry.eventData();
885 log.debug("Topology Event: {} {}", eventEntry.eventType(),
886 topologyElement.toString());
887 }
888
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800889 log.debug("[BEFORE] {}", topology.toString());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800890 topology.readFromDatabase(dbHandler);
891 log.debug("[AFTER] {}", topology.toString());
892 shouldRecomputeFlowPaths.putAll(allFlowPaths);
893 return;
894 }
895
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700896 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800897 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700898 //
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700899 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
900 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800901
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800902 log.debug("Topology Event: {} {}", eventEntry.eventType(),
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800903 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800904
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700905 switch (eventEntry.eventType()) {
906 case ENTRY_ADD:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800907 isTopologyModified |= topology.addTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700908 break;
909 case ENTRY_REMOVE:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800910 isTopologyModified |= topology.removeTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700911 break;
912 }
913 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700914 if (isTopologyModified) {
915 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800916 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700917 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800918 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700919
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800920 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800921 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800922 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800923 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800924 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800925 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800926
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700927 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800928 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700929 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800930 if (! unmatchedFlowEntryAdd.isEmpty()) {
931 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
932 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800933 // log.debug("Processing Unmatched Flow Entry: {}",
934 // flowEntry.toString());
935
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800936 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800937 if (flowPath == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800938 remainingUpdates.put(flowEntry.flowEntryId().value(),
939 flowEntry);
940 continue;
941 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800942 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
943 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800944 remainingUpdates.put(flowEntry.flowEntryId().value(),
945 flowEntry);
946 continue;
947 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800948 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
949 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
950 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700951 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800952 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700953 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800954 }
955
956 /**
957 * Process the Flow Entry events.
958 */
959 private void processFlowEntryEvents() {
960 FlowPath flowPath;
961 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700962
963 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800964 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700965 //
966 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
967 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800968
969 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800970 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800971
972 if ((! flowEntry.isValidFlowId()) ||
973 (! flowEntry.isValidFlowEntryId())) {
974 continue;
975 }
976
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700977 switch (eventEntry.eventType()) {
978 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800979 flowPath = allFlowPaths.get(flowEntry.flowId().value());
980 if (flowPath == null) {
981 // Flow Path not found: keep the entry for later matching
982 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
983 flowEntry);
984 break;
985 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800986 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
987 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800988 // Flow Entry 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 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
994 // Add the updated Flow Path to the list of updated paths
995 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
996 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700997 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800998
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700999 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001000 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1001 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001002 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001003 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001004
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001005 flowPath = allFlowPaths.get(flowEntry.flowId().value());
1006 if (flowPath == null) {
1007 // Flow Path not found: ignore the update
1008 break;
1009 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001010 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
1011 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001012 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001013 break;
1014 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001015 if (updateFlowEntryRemove(flowPath, localFlowEntry,
1016 flowEntry)) {
1017 // Add the updated Flow Path to the list of updated paths
1018 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
1019 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001020 break;
1021 }
1022 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001023 }
1024
1025 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001026 * Find a Flow Entry that should be updated because of an external
1027 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001028 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001029 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001030 * @param newFlowEntry the FlowEntry with the new state.
1031 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001032 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001033 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
1034 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001035 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001036 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001037 //
1038 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001039 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001040 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001041 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001042 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001043
1044 //
1045 // Local Flow Entry match found
1046 //
1047 if (localFlowEntry.isValidFlowEntryId()) {
1048 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001049 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001050 //
1051 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001052 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001053 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001054 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001055 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001056 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001057 return localFlowEntry;
1058 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001059
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001060 return null; // Entry not found
1061 }
1062
1063 /**
1064 * Update a Flow Entry because of an external ENTRY_ADD event.
1065 *
1066 * @param flowPath the FlowPath for the Flow Entry to update.
1067 * @param localFlowEntry the local Flow Entry to update.
1068 * @param newFlowEntry the FlowEntry with the new state.
1069 * @return true if the local Flow Entry was updated, otherwise false.
1070 */
1071 private boolean updateFlowEntryAdd(FlowPath flowPath,
1072 FlowEntry localFlowEntry,
1073 FlowEntry newFlowEntry) {
1074 boolean updated = false;
1075
1076 if (localFlowEntry.flowEntryUserState() ==
1077 FlowEntryUserState.FE_USER_DELETE) {
1078 // Don't add-back a Flow Entry that is already deleted
1079 return false;
1080 }
1081
1082 if (! localFlowEntry.isValidFlowEntryId()) {
1083 // Update the Flow Entry ID
1084 FlowEntryId flowEntryId =
1085 new FlowEntryId(newFlowEntry.flowEntryId().value());
1086 localFlowEntry.setFlowEntryId(flowEntryId);
1087 updated = true;
1088 }
1089
1090 //
1091 // Update the local Flow Entry, and keep state to check
1092 // if the Flow Path has been installed.
1093 //
1094 if (localFlowEntry.flowEntryUserState() !=
1095 newFlowEntry.flowEntryUserState()) {
1096 localFlowEntry.setFlowEntryUserState(
1097 newFlowEntry.flowEntryUserState());
1098 updated = true;
1099 }
1100 if (localFlowEntry.flowEntrySwitchState() !=
1101 newFlowEntry.flowEntrySwitchState()) {
1102 localFlowEntry.setFlowEntrySwitchState(
1103 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -08001104 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001105 updated = true;
1106 }
1107
1108 return updated;
1109 }
1110
1111 /**
1112 * Find a Flow Entry that should be updated because of an external
1113 * ENTRY_REMOVE event.
1114 *
1115 * @param flowPath the FlowPath for the Flow Entry to update.
1116 * @param newFlowEntry the FlowEntry with the new state.
1117 * @return the Flow Entry that should be updated if found, otherwise null.
1118 */
1119 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
1120 FlowEntry newFlowEntry) {
1121 //
1122 // Iterate over all Flow Entries and find a match based on
1123 // the Flow Entry ID.
1124 //
1125 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
1126 if (! localFlowEntry.isValidFlowEntryId())
1127 continue;
1128 if (localFlowEntry.flowEntryId().value() !=
1129 newFlowEntry.flowEntryId().value()) {
1130 continue;
1131 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001132 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001133 }
1134
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001135 return null; // Entry not found
1136 }
1137
1138 /**
1139 * Update a Flow Entry because of an external ENTRY_REMOVE event.
1140 *
1141 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001142 * @param localFlowEntry the local Flow Entry to update.
1143 * @param newFlowEntry the FlowEntry with the new state.
1144 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001145 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001146 private boolean updateFlowEntryRemove(FlowPath flowPath,
1147 FlowEntry localFlowEntry,
1148 FlowEntry newFlowEntry) {
1149 boolean updated = false;
1150
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001151 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001152 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001153 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001154 if (localFlowEntry.flowEntryUserState() !=
1155 newFlowEntry.flowEntryUserState()) {
1156 localFlowEntry.setFlowEntryUserState(
1157 newFlowEntry.flowEntryUserState());
1158 updated = true;
1159 }
1160 if (localFlowEntry.flowEntrySwitchState() !=
1161 newFlowEntry.flowEntrySwitchState()) {
1162 localFlowEntry.setFlowEntrySwitchState(
1163 newFlowEntry.flowEntrySwitchState());
1164 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001165 }
1166
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001167 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001168 }
1169
1170 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001171 * Recompute a Flow Path.
1172 *
1173 * @param flowPath the Flow Path to recompute.
1174 * @return true if the recomputed Flow Path has changed, otherwise false.
1175 */
1176 private boolean recomputeFlowPath(FlowPath flowPath) {
1177 boolean hasChanged = false;
1178
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001179 if (enableOnrc2014MeasurementsFlows) {
1180 // Cleanup the deleted Flow Entries from the earlier iteration
1181 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -08001182
1183 //
1184 // TODO: Fake it that the Flow Entries have been already pushed
1185 // into the switches, so we don't push them again.
1186 //
1187 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1188 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1189 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001190 }
1191
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001192 //
1193 // Test whether the Flow Path needs to be recomputed
1194 //
1195 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001196 case FP_TYPE_UNKNOWN:
1197 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001198 case FP_TYPE_SHORTEST_PATH:
1199 break;
1200 case FP_TYPE_EXPLICIT_PATH:
1201 return false; // An explicit path never changes
1202 }
1203
1204 DataPath oldDataPath = flowPath.dataPath();
1205
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001206 // Compute the new path
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001207 DataPath newDataPath;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001208 newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001209 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001210 if (newDataPath == null) {
1211 // We need the DataPath to compare the paths
1212 newDataPath = new DataPath();
1213 }
1214 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1215
1216 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001217 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001218 //
1219 if (oldDataPath.flowEntries().size() !=
1220 newDataPath.flowEntries().size()) {
1221 hasChanged = true;
1222 } else {
1223 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1224 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1225 while (oldIter.hasNext() && newIter.hasNext()) {
1226 FlowEntry oldFlowEntry = oldIter.next();
1227 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001228 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1229 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001230 hasChanged = true;
1231 break;
1232 }
1233 }
1234 }
1235 if (! hasChanged)
1236 return hasChanged;
1237
1238 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001239 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001240 // - If a Flow Entry for a switch is in the old data path, but not
1241 // in the new data path, then mark it for deletion.
1242 // - If a Flow Entry for a switch is in the new data path, but not
1243 // in the old data path, then mark it for addition.
1244 // - If a Flow Entry for a switch is in both the old and the new
1245 // data path, but it has changed, e.g., the incoming and/or outgoing
1246 // port(s), then mark the old Flow Entry for deletion, and mark
1247 // the new Flow Entry for addition.
1248 // - If a Flow Entry for a switch is in both the old and the new
1249 // data path, and it hasn't changed, then just keep it.
1250 //
1251 // NOTE: We use the Switch DPID of each entry to match the entries
1252 //
1253 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1254 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1255 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1256 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1257
1258 // Prepare maps with the Flow Entries, so they are fast to lookup
1259 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1260 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1261 for (FlowEntry flowEntry : newDataPath.flowEntries())
1262 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1263
1264 //
1265 // Find the old Flow Entries that should be deleted
1266 //
1267 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1268 FlowEntry newFlowEntry =
1269 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1270 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001271 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001272 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1273 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1274 deletedFlowEntries.add(oldFlowEntry);
1275 }
1276 }
1277
1278 //
1279 // Find the new Flow Entries that should be added or updated
1280 //
1281 int idx = 0;
1282 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1283 FlowEntry oldFlowEntry =
1284 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1285
1286 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001287 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1288 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001289 //
1290 // Both Flow Entries are same
1291 //
1292 finalFlowEntries.add(oldFlowEntry);
1293 idx++;
1294 continue;
1295 }
1296
1297 if (oldFlowEntry != null) {
1298 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001299 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001300 //
1301 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1302 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1303 deletedFlowEntries.add(oldFlowEntry);
1304 }
1305
1306 //
1307 // Add the new Flow Entry
1308 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001309 //
1310 // NOTE: Assign only the Flow ID.
1311 // The Flow Entry ID is assigned later only for the Flow Entries
1312 // this instance is responsible for.
1313 //
1314 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001315
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001316 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001317 // Copy the Flow timeouts
1318 //
1319 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1320 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1321
1322 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001323 // Allocate the FlowEntryMatch by copying the default one
1324 // from the FlowPath (if set).
1325 //
1326 FlowEntryMatch flowEntryMatch = null;
1327 if (flowPath.flowEntryMatch() != null)
1328 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1329 else
1330 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001331 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001332
1333 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001334 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1335
1336 //
1337 // Set the actions:
1338 // If the first Flow Entry, copy the Flow Path actions to it.
1339 //
1340 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1341 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1342 FlowEntryActions flowActions =
1343 new FlowEntryActions(flowPath.flowEntryActions());
1344 for (FlowEntryAction action : flowActions.actions())
1345 flowEntryActions.addAction(action);
1346 }
1347 idx++;
1348
1349 //
1350 // Add the outgoing port output action
1351 //
1352 FlowEntryAction flowEntryAction = new FlowEntryAction();
1353 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1354 flowEntryActions.addAction(flowEntryAction);
1355
1356 //
1357 // Set the state of the new Flow Entry
1358 //
1359 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1360 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1361 finalFlowEntries.add(newFlowEntry);
1362 }
1363
1364 //
1365 // Replace the old Flow Entries with the new Flow Entries.
1366 // Note that the Flow Entries that will be deleted are added at
1367 // the end.
1368 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001369 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001370 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1371
1372 return hasChanged;
1373 }
1374
1375 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001376 * Receive a notification that a Flow is added.
1377 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001378 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001379 */
1380 @Override
1381 public void notificationRecvFlowAdded(FlowPath flowPath) {
1382 EventEntry<FlowPath> eventEntry =
1383 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1384 networkEvents.add(eventEntry);
1385 }
1386
1387 /**
1388 * Receive a notification that a Flow is removed.
1389 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001390 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001391 */
1392 @Override
1393 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1394 EventEntry<FlowPath> eventEntry =
1395 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1396 networkEvents.add(eventEntry);
1397 }
1398
1399 /**
1400 * Receive a notification that a Flow is updated.
1401 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001402 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001403 */
1404 @Override
1405 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1406 // NOTE: The ADD and UPDATE events are processed in same way
1407 EventEntry<FlowPath> eventEntry =
1408 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1409 networkEvents.add(eventEntry);
1410 }
1411
1412 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001413 * Receive a notification that a FlowEntry is added.
1414 *
1415 * @param flowEntry the FlowEntry that is added.
1416 */
1417 @Override
1418 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001419 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001420// String tag = "EventHandler.AddFlowEntryToSwitch." + flowEntry.flowEntryId();
1421 String tag = "EventHandler.AddFlowEntryToSwitch";
1422 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001423 Collection entries = new ArrayList();
1424 entries.add(flowEntry);
1425 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001426// PerformanceMonitor.stop(tag);
1427 m.stop();
1428// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001429 return;
1430 }
1431
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001432 EventEntry<FlowEntry> eventEntry =
1433 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1434 networkEvents.add(eventEntry);
1435 }
1436
1437 /**
1438 * Receive a notification that a FlowEntry is removed.
1439 *
1440 * @param flowEntry the FlowEntry that is removed.
1441 */
1442 @Override
1443 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001444 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001445// String tag = "EventHandler.RemoveFlowEntryFromSwitch." + flowEntry.flowEntryId();
1446 String tag = "EventHandler.RemoveFlowEntryFromSwitch";
1447 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavove4d2a432014-01-10 12:01:08 -08001448 //
1449 // NOTE: Must update the state to DELETE, because
1450 // the notification contains the original state.
1451 //
1452 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1453
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001454 Collection entries = new ArrayList();
1455 entries.add(flowEntry);
1456 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001457// PerformanceMonitor.stop(tag);
1458 m.stop();
1459// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001460 return;
1461 }
1462
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001463 EventEntry<FlowEntry> eventEntry =
1464 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1465 networkEvents.add(eventEntry);
1466 }
1467
1468 /**
1469 * Receive a notification that a FlowEntry is updated.
1470 *
1471 * @param flowEntry the FlowEntry that is updated.
1472 */
1473 @Override
1474 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001475 if (enableOnrc2014MeasurementsFlows) {
1476 Collection entries = new ArrayList();
1477 entries.add(flowEntry);
1478 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1479 return;
1480 }
1481
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001482 // NOTE: The ADD and UPDATE events are processed in same way
1483 EventEntry<FlowEntry> eventEntry =
1484 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1485 networkEvents.add(eventEntry);
1486 }
1487
1488 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001489 * Receive a notification that a FlowId is added.
1490 *
1491 * @param flowId the FlowId that is added.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001492 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001493 */
1494 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001495 public void notificationRecvFlowIdAdded(FlowId flowId, Dpid dpid) {
1496 Pair flowIdPair = new Pair(flowId, dpid);
1497
1498 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1499 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001500 networkEvents.add(eventEntry);
1501 }
1502
1503 /**
1504 * Receive a notification that a FlowId is removed.
1505 *
1506 * @param flowId the FlowId that is removed.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001507 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001508 */
1509 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001510 public void notificationRecvFlowIdRemoved(FlowId flowId, Dpid dpid) {
1511 Pair flowIdPair = new Pair(flowId, dpid);
1512
1513 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1514 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001515 networkEvents.add(eventEntry);
1516 }
1517
1518 /**
1519 * Receive a notification that a FlowId is updated.
1520 *
1521 * @param flowId the FlowId that is updated.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001522 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001523 */
1524 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001525 public void notificationRecvFlowIdUpdated(FlowId flowId, Dpid dpid) {
1526 Pair flowIdPair = new Pair(flowId, dpid);
1527
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001528 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001529 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1530 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001531 networkEvents.add(eventEntry);
1532 }
1533
1534 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001535 * Receive a notification that a FlowEntryId is added.
1536 *
1537 * @param flowEntryId the FlowEntryId that is added.
1538 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1539 */
1540 @Override
1541 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1542 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001543 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1544
1545 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1546 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001547 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001548 }
1549
1550 /**
1551 * Receive a notification that a FlowEntryId is removed.
1552 *
1553 * @param flowEntryId the FlowEntryId that is removed.
1554 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1555 */
1556 @Override
1557 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1558 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001559 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1560
1561 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1562 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001563 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001564 }
1565
1566 /**
1567 * Receive a notification that a FlowEntryId is updated.
1568 *
1569 * @param flowEntryId the FlowEntryId that is updated.
1570 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1571 */
1572 @Override
1573 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1574 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001575 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1576
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001577 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001578 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1579 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001580 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001581 }
1582
1583 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001584 * Receive a notification that a Topology Element is added.
1585 *
1586 * @param topologyElement the Topology Element that is added.
1587 */
1588 @Override
1589 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1590 EventEntry<TopologyElement> eventEntry =
1591 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1592 networkEvents.add(eventEntry);
1593 }
1594
1595 /**
1596 * Receive a notification that a Topology Element is removed.
1597 *
1598 * @param topologyElement the Topology Element that is removed.
1599 */
1600 @Override
1601 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1602 EventEntry<TopologyElement> eventEntry =
1603 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1604 networkEvents.add(eventEntry);
1605 }
1606
1607 /**
1608 * Receive a notification that a Topology Element is updated.
1609 *
1610 * @param topologyElement the Topology Element that is updated.
1611 */
1612 @Override
1613 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1614 // NOTE: The ADD and UPDATE events are processed in same way
1615 EventEntry<TopologyElement> eventEntry =
1616 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1617 networkEvents.add(eventEntry);
1618 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001619
1620 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -08001621 * Receive a notification that a switch is added to this instance.
1622 *
1623 * @param sw the switch that is added.
1624 */
1625 @Override
1626 public void addedSwitch(IOFSwitch sw) {
1627 Dpid dpid = new Dpid(sw.getId());
1628 EventEntry<Dpid> eventEntry =
1629 new EventEntry<Dpid>(EventEntry.Type.ENTRY_ADD, dpid);
1630 networkEvents.add(eventEntry);
1631 }
1632
1633 /**
1634 * Receive a notification that a switch is removed from this instance.
1635 *
1636 * @param sw the switch that is removed.
1637 */
1638 @Override
1639 public void removedSwitch(IOFSwitch sw) {
1640 Dpid dpid = new Dpid(sw.getId());
1641 EventEntry<Dpid> eventEntry =
1642 new EventEntry<Dpid>(EventEntry.Type.ENTRY_REMOVE, dpid);
1643 networkEvents.add(eventEntry);
1644 }
1645
1646 /**
1647 * Receive a notification that the ports on a switch have changed.
1648 */
1649 @Override
1650 public void switchPortChanged(Long switchId) {
1651 // Nothing to do
1652 }
1653
1654 /**
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001655 * Get a sorted copy of all Flow Paths.
1656 *
1657 * @return a sorted copy of all Flow Paths.
1658 */
1659 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1660 SortedMap<Long, FlowPath> sortedFlowPaths =
1661 new TreeMap<Long, FlowPath>();
1662
1663 //
1664 // TODO: For now we use serialization/deserialization to create
1665 // a copy of each Flow Path. In the future, we should use proper
1666 // copy constructors.
1667 //
1668 Kryo kryo = kryoFactory.newKryo();
1669 synchronized (allFlowPaths) {
1670 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1671 FlowPath origFlowPath = entry.getValue();
1672 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1673 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1674 }
1675 }
1676 kryoFactory.deleteKryo(kryo);
1677
1678 return sortedFlowPaths;
1679 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001680}