blob: 1471c493ea29766c76a44ef2bd827a6e0b31ac0d [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;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -080011import java.util.Timer;
12import java.util.TimerTask;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080013import java.util.TreeMap;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070014import java.util.concurrent.BlockingQueue;
15import java.util.concurrent.LinkedBlockingQueue;
16
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080017import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080018import net.floodlightcontroller.core.IOFSwitchListener;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070019import net.onrc.onos.datagrid.IDatagridService;
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -080020import net.onrc.onos.graph.DBOperation;
21import net.onrc.onos.graph.GraphDBManager;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070022import net.onrc.onos.ofcontroller.topology.Topology;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070023import net.onrc.onos.ofcontroller.topology.TopologyElement;
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -070024import net.onrc.onos.ofcontroller.topology.TopologyManager;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070025import net.onrc.onos.ofcontroller.util.DataPath;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080026import net.onrc.onos.ofcontroller.util.Dpid;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070027import net.onrc.onos.ofcontroller.util.EventEntry;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070028import net.onrc.onos.ofcontroller.util.FlowEntry;
29import net.onrc.onos.ofcontroller.util.FlowEntryAction;
30import net.onrc.onos.ofcontroller.util.FlowEntryActions;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070031import net.onrc.onos.ofcontroller.util.FlowEntryId;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070032import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
33import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
34import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -070035import net.onrc.onos.ofcontroller.util.FlowId;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070036import net.onrc.onos.ofcontroller.util.FlowPath;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -070037import net.onrc.onos.ofcontroller.util.FlowPathUserState;
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080038import net.onrc.onos.ofcontroller.util.Pair;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080039import net.onrc.onos.ofcontroller.util.Port;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080040import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
41
42import com.esotericsoftware.kryo2.Kryo;
Yuta HIGUCHIe5ef3872014-01-07 12:35:59 -080043import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070044
45import org.slf4j.Logger;
46import org.slf4j.LoggerFactory;
47
48/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070049 * Class for FlowPath Maintenance.
50 * This class listens for FlowEvents to:
51 * - Maintain a local cache of the Network Topology.
52 * - Detect FlowPaths impacted by Topology change.
53 * - Recompute impacted FlowPath using cached Topology.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070054 */
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080055class FlowEventHandler extends Thread implements IFlowEventHandlerService,
56 IOFSwitchListener {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080057
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -080058 private boolean enableOnrc2014MeasurementsFlows = true;
59 private boolean enableOnrc2014MeasurementsTopology = true;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080060
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070061 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070062 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070063
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -080064 private DBOperation dbHandler;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -080065
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070066 private FlowManager flowManager; // The Flow Manager to use
67 private IDatagridService datagridService; // The Datagrid Service to use
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070068 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080069 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070070
71 // The queue with Flow Path and Topology Element updates
72 private BlockingQueue<EventEntry<?>> networkEvents =
73 new LinkedBlockingQueue<EventEntry<?>>();
74
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070075 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070076 private List<EventEntry<TopologyElement>> topologyEvents =
77 new LinkedList<EventEntry<TopologyElement>>();
78 private List<EventEntry<FlowPath>> flowPathEvents =
79 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070080 private List<EventEntry<FlowEntry>> flowEntryEvents =
81 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2194d112014-01-10 13:36:00 -080082 private List<EventEntry<Pair<FlowId, Dpid>>> flowIdEvents =
83 new LinkedList<EventEntry<Pair<FlowId, Dpid>>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080084 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
85 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080086 private List<EventEntry<Dpid>> switchDpidEvents =
87 new LinkedList<EventEntry<Dpid>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070088
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080089 // All internally computed Flow Paths
90 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
91
92 // The Flow Entries received as notifications with unmatched Flow Paths
93 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
94 new HashMap<Long, FlowEntry>();
95
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080096 //
97 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080098 // - The Flow Paths that should be recomputed
99 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800100 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800101 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800102 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
103 new HashMap<Long, FlowPath>();
104 private Map<Long, FlowPath> modifiedFlowPaths =
105 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800106 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
107 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800108
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700109 /**
110 * Constructor for a given Flow Manager and Datagrid Service.
111 *
112 * @param flowManager the Flow Manager to use.
113 * @param datagridService the Datagrid Service to use.
114 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700115 FlowEventHandler(FlowManager flowManager,
116 IDatagridService datagridService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700117 this.flowManager = flowManager;
118 this.datagridService = datagridService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700119 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700120 }
121
122 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800123 * Get the network topology.
124 *
125 * @return the network topology.
126 */
127 protected Topology getTopology() { return this.topology; }
128
129 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800130 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700131 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800132 private void startup() {
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800133 this.dbHandler = GraphDBManager.getDBOperation("ramcloud", "/tmp/ramcloudconf");
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800134
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700135 //
136 // Obtain the initial Topology state
137 //
138 Collection<TopologyElement> topologyElements =
139 datagridService.getAllTopologyElements();
140 for (TopologyElement topologyElement : topologyElements) {
141 EventEntry<TopologyElement> eventEntry =
142 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
143 topologyEvents.add(eventEntry);
144 }
145 //
146 // Obtain the initial Flow Path state
147 //
148 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
149 for (FlowPath flowPath : flowPaths) {
150 EventEntry<FlowPath> eventEntry =
151 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
152 flowPathEvents.add(eventEntry);
153 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700154 //
155 // Obtain the initial FlowEntry state
156 //
157 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
158 for (FlowEntry flowEntry : flowEntries) {
159 EventEntry<FlowEntry> eventEntry =
160 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
161 flowEntryEvents.add(eventEntry);
162 }
163
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800164 //
165 // Obtain the initial FlowId state
166 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800167 Collection<Pair<FlowId, Dpid>> flowIds =
168 datagridService.getAllFlowIds();
169 for (Pair<FlowId, Dpid> pair : flowIds) {
170 EventEntry<Pair<FlowId, Dpid>> eventEntry =
171 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800172 flowIdEvents.add(eventEntry);
173 }
174
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800175 //
176 // Obtain the initial FlowEntryId state
177 //
178 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
179 datagridService.getAllFlowEntryIds();
180 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
181 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
182 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
183 flowEntryIdEvents.add(eventEntry);
184 }
185
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800186 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800187 synchronized (allFlowPaths) {
188 processEvents();
189 }
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800190
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800191 }
192
193 /**
194 * Run the thread.
195 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800196 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800197 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800198 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800199 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700200
201 //
202 // The main loop
203 //
204 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
205 try {
206 while (true) {
207 EventEntry<?> eventEntry = networkEvents.take();
208 collection.add(eventEntry);
209 networkEvents.drainTo(collection);
210
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700211 //
212 // Demultiplex all events:
213 // - EventEntry<TopologyElement>
214 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700215 // - EventEntry<FlowEntry>
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800216 // - EventEntry<Pair<FlowId, Dpid>>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800217 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700218 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700219 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800220 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700221 if (event.eventData() instanceof TopologyElement) {
222 EventEntry<TopologyElement> topologyEventEntry =
223 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800224
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700225 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800226 continue;
227 }
228
229 // FlowPath event
230 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700231 EventEntry<FlowPath> flowPathEventEntry =
232 (EventEntry<FlowPath>)event;
233 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800234 continue;
235 }
236
237 // FlowEntry event
238 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700239 EventEntry<FlowEntry> flowEntryEventEntry =
240 (EventEntry<FlowEntry>)event;
241 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800242 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700243 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800244
245 // FlowId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800246 if (event.eventData() instanceof Pair) {
247 EventEntry<Pair<FlowId, Dpid>> flowIdEventEntry =
248 (EventEntry<Pair<FlowId, Dpid>>)event;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800249 flowIdEvents.add(flowIdEventEntry);
250 continue;
251 }
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800252
253 // Switch Dpid event
254 if (event.eventData() instanceof Dpid) {
255 EventEntry<Dpid> switchDpidEventEntry =
256 (EventEntry<Dpid>)event;
257 switchDpidEvents.add(switchDpidEventEntry);
258 continue;
259 }
260
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800261 // FlowEntryId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800262 // TODO: Fix the code below if we need again to handle
263 // the FlowEntryId events
264 /*
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800265 if (event.eventData() instanceof Pair) {
266 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
267 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
268 flowEntryIdEvents.add(flowEntryIdEventEntry);
269 continue;
270 }
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800271 */
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700272 }
273 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700274
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700275 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800276 synchronized (allFlowPaths) {
277 processEvents();
278 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700279 }
280 } catch (Exception exception) {
281 log.debug("Exception processing Network Events: ", exception);
282 }
283 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800284
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700285 /**
286 * Process the events (if any)
287 */
288 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800289 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700290
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800291 if (enableOnrc2014MeasurementsFlows) {
292
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800293 PerformanceMonitor.start("EventHandler.ProcessAllEvents");
294
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800295 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
296 switchDpidEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800297 return; // Nothing to do
298 }
299
300 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
301
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800302 // Process the Switch Dpid events
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800303 PerformanceMonitor.start("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800304 processSwitchDpidEvents();
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800305 PerformanceMonitor.stop("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800306
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800307 // Process the Flow ID events
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800308 PerformanceMonitor.start("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800309 processFlowIdEvents(mySwitches);
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800310 PerformanceMonitor.stop("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800311
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800312 // Fetch the topology
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800313 PerformanceMonitor.start("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800314 processTopologyEvents();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800315 PerformanceMonitor.stop("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800316
317 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800318 PerformanceMonitor.start("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800319 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
320 if (recomputeFlowPath(flowPath))
321 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
322 }
323
324 // Assign the Flow Entry ID as needed
325 for (FlowPath flowPath : modifiedFlowPaths.values()) {
326 for (FlowEntry flowEntry : flowPath.flowEntries()) {
327 if (! flowEntry.isValidFlowEntryId()) {
328 long id = flowManager.getNextFlowEntryId();
329 flowEntry.setFlowEntryId(new FlowEntryId(id));
330 }
331 }
332 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800333 PerformanceMonitor.stop("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800334
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800335 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800336 // Push the modified state to the database
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800337 //
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800338 PerformanceMonitor.start("EventHandler.WriteFlowsToDb");
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800339 for (FlowPath flowPath : modifiedFlowPaths.values()) {
340 //
341 // Delete the Flow Path from the Network Map
342 //
343 if (flowPath.flowPathUserState() ==
344 FlowPathUserState.FP_USER_DELETE) {
345 log.debug("Deleting Flow Path From Database: {}", flowPath);
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800346 // TODO: For now the deleting of a Flow Path is blocking
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800347 ParallelFlowDatabaseOperation.deleteFlow(dbHandler,
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800348 flowPath.flowId());
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800349 //
350 // NOTE: For now the sending of the notifications
351 // is outside of this loop, so the performance measurements
352 // are more accurate.
353 //
354 /*
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800355 // Send the notifications for the deleted Flow Entries
356 for (FlowEntry flowEntry : flowPath.flowEntries()) {
357 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
358 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800359 */
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800360
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800361 continue;
362 }
363
364 log.debug("Pushing Flow Path To Database: {}", flowPath);
365 //
366 // Write the Flow Path to the Network Map
367 //
368 ParallelFlowDatabaseOperation.addFlow(dbHandler, flowPath,
369 datagridService);
370 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800371 PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
372
373 //
374 // Send the notifications for the deleted Flow Entries
375 // NOTE: This code was pulled outside of the above loop,
376 // so the performance measurements are more accurate.
377 //
378 PerformanceMonitor.start("EventHandler.NotificationSend.FlowEntryRemoved");
379 for (FlowPath flowPath : modifiedFlowPaths.values()) {
380 if (flowPath.flowPathUserState() ==
381 FlowPathUserState.FP_USER_DELETE) {
382 for (FlowEntry flowEntry : flowPath.flowEntries()) {
383 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
384 }
385 }
386 }
Pavlin Radoslavovdbd09cc2014-01-12 18:13:35 -0800387 PerformanceMonitor.stop("EventHandler.NotificationSend.FlowEntryRemoved");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800388
389 // Cleanup
390 topologyEvents.clear();
391 flowIdEvents.clear();
Pavlin Radoslavov2d6e5f12014-01-10 16:34:05 -0800392 switchDpidEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800393 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800394 // NOTE: Keep a cache with my Flow Paths
395 // allFlowPaths.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800396 shouldRecomputeFlowPaths.clear();
397 modifiedFlowPaths.clear();
398
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800399 PerformanceMonitor.stop("EventHandler.ProcessAllEvents");
Pavlin Radoslavov8bd6d112014-01-12 20:12:37 -0800400
401
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800402 PerformanceMonitor.report("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800403 PerformanceMonitor.report("EventHandler.FlowIdEvents");
Pavlin Radoslavov8bd6d112014-01-12 20:12:37 -0800404 PerformanceMonitor.report("EventHandler.ReadTopology");
405 PerformanceMonitor.report("EventHandler.RecomputeFlows");
406 PerformanceMonitor.report("EventHandler.WriteFlowsToDb");
407 PerformanceMonitor.report("EventHandler.NotificationSend.FlowEntryRemoved");
408 PerformanceMonitor.report("EventHandler.ProcessAllEvents");
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;
476
477 //
478 // Check whether all Flow Entries have been installed
479 //
480 for (FlowEntry flowEntry : flowPath.flowEntries()) {
481 if (flowEntry.flowEntrySwitchState() !=
482 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
483 isInstalled = false;
484 break;
485 }
486 }
487
488 if (isInstalled) {
489 // Create a copy and add it to the list
490 FlowPath copyFlowPath = kryo.copy(flowPath);
491 installedFlowPaths.add(copyFlowPath);
492 }
493 }
494 kryoFactory.deleteKryo(kryo);
495
496 // Generate an event for the installed Flow Path.
497 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800498 }
499
500 /**
501 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800502 *
503 * @param modifiedFlowPaths the Flow Paths to process.
504 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800505 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800506 private Collection<FlowEntry> extractModifiedFlowEntries(
507 Collection<FlowPath> modifiedFlowPaths) {
508 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800509
510 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800511 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800512 for (FlowEntry flowEntry : flowPath.flowEntries()) {
513 if (flowEntry.flowEntrySwitchState() ==
514 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800515 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800516 }
517 }
518 }
519 return modifiedFlowEntries;
520 }
521
522 /**
523 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800524 *
525 * @param modifiedFlowEnries the collection of Flow Entries that need
526 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800527 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800528 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800529 if (modifiedFlowEntries.isEmpty())
530 return;
531
532 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
533
534 //
535 // Assign the Flow Entry ID only for Flow Entries for my switches
536 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800537 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800538 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
539 if (mySwitch == null)
540 continue;
541 if (! flowEntry.isValidFlowEntryId()) {
542 long id = flowManager.getNextFlowEntryId();
543 flowEntry.setFlowEntryId(new FlowEntryId(id));
544 }
545 }
546 }
547
548 /**
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800549 * Fix a flow fetched from the database.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800550 *
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800551 * @param flowPath the Flow to fix.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800552 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800553 private void fixFlowFromDatabase(FlowPath flowPath) {
554 //
555 // TODO: Bug workaround / fix :
556 // method FlowDatabaseOperation.extractFlowEntry() doesn't
557 // fetch the inPort and outPort, hence we assign them here.
558 //
559 // Assign the inPort and outPort for the Flow Entries
560 for (FlowEntry flowEntry : flowPath.flowEntries()) {
561 // Set the inPort
562 do {
563 if (flowEntry.inPort() != null)
564 break;
565 if (flowEntry.flowEntryMatch() == null)
566 break;
567 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
568 flowEntry.setInPort(inPort);
569 } while (false);
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800570
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800571 // Set the outPort
572 do {
573 if (flowEntry.outPort() != null)
574 break;
575 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
576 if (fa.actionOutput() != null) {
577 Port outPort = new Port(fa.actionOutput().port().value());
578 flowEntry.setOutPort(outPort);
579 break;
580 }
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800581 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800582 } while (false);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800583 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800584 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800585
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800586 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800587 * Process the Switch Dpid events.
588 */
589 private void processSwitchDpidEvents() {
590 Map<Long, Dpid> addedSwitches = new HashMap<Long, Dpid>();
591 Map<Long, Dpid> removedSwitches = new HashMap<Long, Dpid>();
592
593 //
594 // Process all Switch Dpid events and update the appropriate state
595 //
596 for (EventEntry<Dpid> eventEntry : switchDpidEvents) {
597 Dpid dpid = eventEntry.eventData();
598
599 log.debug("SwitchDpid Event: {} {}", eventEntry.eventType(), dpid);
600
601 // Compute the final set of added and removed switches
602 switch (eventEntry.eventType()) {
603 case ENTRY_ADD:
604 addedSwitches.put(dpid.value(), dpid);
605 removedSwitches.remove(dpid.value());
606 break;
607 case ENTRY_REMOVE:
608 addedSwitches.remove(dpid.value());
609 removedSwitches.put(dpid.value(), dpid);
610 break;
611 }
612 }
613
614 //
615 // Remove the Flows from the local cache if the removed
616 // switch is the Source Switch.
617 //
618 // TODO: This search can be expensive for a large number of flows
619 // and should be optmized.
620 //
621 List<FlowId> deleteFlowIds = new LinkedList<FlowId>();
622 for (Dpid switchDpid : removedSwitches.values()) {
623 for (FlowPath flowPath : allFlowPaths.values()) {
624 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
625 if (srcDpid.value() == switchDpid.value())
626 deleteFlowIds.add(flowPath.flowId());
627 }
628 }
629 //
630 // Remove the Flows from the local cache
631 //
632 for (FlowId flowId : deleteFlowIds)
633 allFlowPaths.remove(flowId.value());
634
635 // Get the Flows for the added switches
636 Collection<FlowPath> flowPaths =
637 ParallelFlowDatabaseOperation.getFlowsForSwitches(dbHandler,
638 addedSwitches.values());
639 for (FlowPath flowPath : flowPaths) {
640 allFlowPaths.put(flowPath.flowId().value(), flowPath);
641 }
642 }
643
644 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800645 * Process the Flow ID events.
646 *
647 * @param mySwitches the collection of my switches.
648 */
649 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800650 List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
651
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800652 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800653 // Process all Flow Id events and update the appropriate state
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800654 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800655 for (EventEntry<Pair<FlowId, Dpid>> eventEntry : flowIdEvents) {
656 Pair<FlowId, Dpid> pair = eventEntry.eventData();
657 FlowId flowId = pair.first;
658 Dpid dpid = pair.second;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800659
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800660 log.debug("Flow ID Event: {} {} {}", eventEntry.eventType(),
661 flowId, dpid);
662
663 //
664 // Ignore Flows if the Source Switch is not controlled by this
665 // instance.
666 //
667 if (mySwitches.get(dpid.value()) == null)
668 continue;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800669
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800670 switch (eventEntry.eventType()) {
671 case ENTRY_ADD: {
672 //
673 // Add a new Flow Path
674 //
675 if (allFlowPaths.get(flowId.value()) != null) {
676 //
677 // TODO: What to do if the Flow Path already exists?
678 // Fow now, we just re-add it.
679 //
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800680 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800681 shouldFetchMyFlowIds.add(flowId);
682
683 break;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800684 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800685
686 case ENTRY_REMOVE: {
687 //
688 // Remove an existing Flow Path.
689 //
690 // Find the Flow Path, and mark the Flow and its Flow Entries
691 // for deletion.
692 //
693 FlowPath existingFlowPath =
694 allFlowPaths.get(flowId.value());
695 if (existingFlowPath == null)
696 continue; // Nothing to do
697
698 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
699 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
700 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
701 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
702 }
703
704 // Remove the Flow Path from the internal state
705 Long key = existingFlowPath.flowId().value();
706 allFlowPaths.remove(key);
707 shouldRecomputeFlowPaths.remove(key);
708 modifiedFlowPaths.put(key, existingFlowPath);
709
710 break;
711 }
712 }
713 }
714
715 // Get my Flows
716 Collection<FlowPath> myFlows =
Pavlin Radoslavov6602b6a2014-01-10 16:43:29 -0800717 ParallelFlowDatabaseOperation.getFlows(dbHandler,
718 shouldFetchMyFlowIds);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800719
720 for (FlowPath flowPath : myFlows) {
721 fixFlowFromDatabase(flowPath);
722
723 switch (flowPath.flowPathType()) {
724 case FP_TYPE_SHORTEST_PATH:
725 //
726 // Reset the Data Path, in case it was set already, because
727 // we are going to recompute it anyway.
728 //
729 flowPath.flowEntries().clear();
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800730 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
731 flowPath);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800732 break;
733 case FP_TYPE_EXPLICIT_PATH:
734 //
735 // Mark all Flow Entries for installation in the switches.
736 //
737 for (FlowEntry flowEntry : flowPath.flowEntries()) {
738 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
739 }
740 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
741 break;
742 case FP_TYPE_UNKNOWN:
743 log.error("FlowPath event with unknown type");
744 break;
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800745 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800746 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800747 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800748 }
749
750 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800751 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800752 *
753 * @param mySwitches the collection of my switches.
754 * @return a collection of modified Flow Entries this instance needs
755 * to push to its own switches.
756 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800757 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800758 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
759
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800760 //
761 // Process all Flow ID events and update the appropriate state
762 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800763 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
764 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
765 FlowEntryId flowEntryId = pair.first;
766 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800767
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800768 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
769 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800770
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800771 if (mySwitches.get(dpid.value()) == null)
772 continue;
773
774 // Fetch the Flow Entry
775 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
776 flowEntryId);
777 if (flowEntry == null) {
778 log.debug("Flow Entry ID {} : Flow Entry not found!",
779 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800780 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800781 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800782 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800783 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800784
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800785 return modifiedFlowEntries;
786 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800787
788 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800789 * Process the Flow Path events.
790 */
791 private void processFlowPathEvents() {
792 //
793 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700794 //
795 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
796 FlowPath flowPath = eventEntry.eventData();
797
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800798 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800799
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700800 switch (eventEntry.eventType()) {
801 case ENTRY_ADD: {
802 //
803 // Add a new Flow Path
804 //
805 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
806 //
807 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800808 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700809 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700810 }
811
812 switch (flowPath.flowPathType()) {
813 case FP_TYPE_SHORTEST_PATH:
814 //
815 // Reset the Data Path, in case it was set already, because
816 // we are going to recompute it anyway.
817 //
818 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800819 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
820 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700821 break;
822 case FP_TYPE_EXPLICIT_PATH:
823 //
824 // Mark all Flow Entries for installation in the switches.
825 //
826 for (FlowEntry flowEntry : flowPath.flowEntries()) {
827 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
828 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800829 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700830 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800831 case FP_TYPE_UNKNOWN:
832 log.error("FlowPath event with unknown type");
833 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700834 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800835 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700836
837 break;
838 }
839
840 case ENTRY_REMOVE: {
841 //
842 // Remove an existing Flow Path.
843 //
844 // Find the Flow Path, and mark the Flow and its Flow Entries
845 // for deletion.
846 //
847 FlowPath existingFlowPath =
848 allFlowPaths.get(flowPath.flowId().value());
849 if (existingFlowPath == null)
850 continue; // Nothing to do
851
852 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
853 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
854 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
855 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
856 }
857
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800858 // Remove the Flow Path from the internal state
859 Long key = existingFlowPath.flowId().value();
860 allFlowPaths.remove(key);
861 shouldRecomputeFlowPaths.remove(key);
862 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700863
864 break;
865 }
866 }
867 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800868 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700869
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800870 /**
871 * Process the Topology events.
872 */
873 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800874 boolean isTopologyModified = false;
875
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800876 if (enableOnrc2014MeasurementsTopology) {
877 if (topologyEvents.isEmpty())
878 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800879
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800880 // TODO: Code for debugging purpose only
881 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
882 TopologyElement topologyElement = eventEntry.eventData();
883 log.debug("Topology Event: {} {}", eventEntry.eventType(),
884 topologyElement.toString());
885 }
886
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800887 log.debug("[BEFORE] {}", topology.toString());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800888 topology.readFromDatabase(dbHandler);
889 log.debug("[AFTER] {}", topology.toString());
890 shouldRecomputeFlowPaths.putAll(allFlowPaths);
891 return;
892 }
893
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700894 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800895 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700896 //
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700897 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
898 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800899
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800900 log.debug("Topology Event: {} {}", eventEntry.eventType(),
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800901 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800902
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700903 switch (eventEntry.eventType()) {
904 case ENTRY_ADD:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800905 synchronized (topology) {
906 isTopologyModified |= topology.addTopologyElement(topologyElement);
907 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700908 break;
909 case ENTRY_REMOVE:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800910 synchronized (topology) {
911 isTopologyModified |= topology.removeTopologyElement(topologyElement);
912 }
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;
1210 synchronized (topology) {
1211 newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001212 flowPath);
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001213 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001214 if (newDataPath == null) {
1215 // We need the DataPath to compare the paths
1216 newDataPath = new DataPath();
1217 }
1218 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1219
1220 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001221 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001222 //
1223 if (oldDataPath.flowEntries().size() !=
1224 newDataPath.flowEntries().size()) {
1225 hasChanged = true;
1226 } else {
1227 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1228 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1229 while (oldIter.hasNext() && newIter.hasNext()) {
1230 FlowEntry oldFlowEntry = oldIter.next();
1231 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001232 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1233 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001234 hasChanged = true;
1235 break;
1236 }
1237 }
1238 }
1239 if (! hasChanged)
1240 return hasChanged;
1241
1242 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001243 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001244 // - If a Flow Entry for a switch is in the old data path, but not
1245 // in the new data path, then mark it for deletion.
1246 // - If a Flow Entry for a switch is in the new data path, but not
1247 // in the old data path, then mark it for addition.
1248 // - If a Flow Entry for a switch is in both the old and the new
1249 // data path, but it has changed, e.g., the incoming and/or outgoing
1250 // port(s), then mark the old Flow Entry for deletion, and mark
1251 // the new Flow Entry for addition.
1252 // - If a Flow Entry for a switch is in both the old and the new
1253 // data path, and it hasn't changed, then just keep it.
1254 //
1255 // NOTE: We use the Switch DPID of each entry to match the entries
1256 //
1257 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1258 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1259 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1260 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1261
1262 // Prepare maps with the Flow Entries, so they are fast to lookup
1263 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1264 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1265 for (FlowEntry flowEntry : newDataPath.flowEntries())
1266 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1267
1268 //
1269 // Find the old Flow Entries that should be deleted
1270 //
1271 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1272 FlowEntry newFlowEntry =
1273 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1274 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001275 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001276 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1277 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1278 deletedFlowEntries.add(oldFlowEntry);
1279 }
1280 }
1281
1282 //
1283 // Find the new Flow Entries that should be added or updated
1284 //
1285 int idx = 0;
1286 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1287 FlowEntry oldFlowEntry =
1288 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1289
1290 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001291 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1292 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001293 //
1294 // Both Flow Entries are same
1295 //
1296 finalFlowEntries.add(oldFlowEntry);
1297 idx++;
1298 continue;
1299 }
1300
1301 if (oldFlowEntry != null) {
1302 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001303 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001304 //
1305 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1306 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1307 deletedFlowEntries.add(oldFlowEntry);
1308 }
1309
1310 //
1311 // Add the new Flow Entry
1312 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001313 //
1314 // NOTE: Assign only the Flow ID.
1315 // The Flow Entry ID is assigned later only for the Flow Entries
1316 // this instance is responsible for.
1317 //
1318 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001319
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001320 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001321 // Copy the Flow timeouts
1322 //
1323 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1324 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
1325
1326 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001327 // Allocate the FlowEntryMatch by copying the default one
1328 // from the FlowPath (if set).
1329 //
1330 FlowEntryMatch flowEntryMatch = null;
1331 if (flowPath.flowEntryMatch() != null)
1332 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1333 else
1334 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001335 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001336
1337 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001338 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1339
1340 //
1341 // Set the actions:
1342 // If the first Flow Entry, copy the Flow Path actions to it.
1343 //
1344 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1345 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1346 FlowEntryActions flowActions =
1347 new FlowEntryActions(flowPath.flowEntryActions());
1348 for (FlowEntryAction action : flowActions.actions())
1349 flowEntryActions.addAction(action);
1350 }
1351 idx++;
1352
1353 //
1354 // Add the outgoing port output action
1355 //
1356 FlowEntryAction flowEntryAction = new FlowEntryAction();
1357 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1358 flowEntryActions.addAction(flowEntryAction);
1359
1360 //
1361 // Set the state of the new Flow Entry
1362 //
1363 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1364 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1365 finalFlowEntries.add(newFlowEntry);
1366 }
1367
1368 //
1369 // Replace the old Flow Entries with the new Flow Entries.
1370 // Note that the Flow Entries that will be deleted are added at
1371 // the end.
1372 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001373 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001374 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1375
1376 return hasChanged;
1377 }
1378
1379 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001380 * Receive a notification that a Flow is added.
1381 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001382 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001383 */
1384 @Override
1385 public void notificationRecvFlowAdded(FlowPath flowPath) {
1386 EventEntry<FlowPath> eventEntry =
1387 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1388 networkEvents.add(eventEntry);
1389 }
1390
1391 /**
1392 * Receive a notification that a Flow is removed.
1393 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001394 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001395 */
1396 @Override
1397 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1398 EventEntry<FlowPath> eventEntry =
1399 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1400 networkEvents.add(eventEntry);
1401 }
1402
1403 /**
1404 * Receive a notification that a Flow is updated.
1405 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001406 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001407 */
1408 @Override
1409 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1410 // NOTE: The ADD and UPDATE events are processed in same way
1411 EventEntry<FlowPath> eventEntry =
1412 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1413 networkEvents.add(eventEntry);
1414 }
1415
1416 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001417 * Receive a notification that a FlowEntry is added.
1418 *
1419 * @param flowEntry the FlowEntry that is added.
1420 */
1421 @Override
1422 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001423 if (enableOnrc2014MeasurementsFlows) {
Pavlin Radoslavov9fbdc992014-01-12 20:56:58 -08001424 String tag = "EventHandler.AddFlowEntryToSwitch." + flowEntry.flowEntryId();
1425 PerformanceMonitor.start(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001426 Collection entries = new ArrayList();
1427 entries.add(flowEntry);
1428 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Pavlin Radoslavov9fbdc992014-01-12 20:56:58 -08001429 PerformanceMonitor.stop(tag);
1430 PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001431 return;
1432 }
1433
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001434 EventEntry<FlowEntry> eventEntry =
1435 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1436 networkEvents.add(eventEntry);
1437 }
1438
1439 /**
1440 * Receive a notification that a FlowEntry is removed.
1441 *
1442 * @param flowEntry the FlowEntry that is removed.
1443 */
1444 @Override
1445 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001446 if (enableOnrc2014MeasurementsFlows) {
Pavlin Radoslavov9fbdc992014-01-12 20:56:58 -08001447 String tag = "EventHandler.RemoveFlowEntryFromSwitch." + flowEntry.flowEntryId();
1448 PerformanceMonitor.start(tag);
Pavlin Radoslavove4d2a432014-01-10 12:01:08 -08001449 //
1450 // NOTE: Must update the state to DELETE, because
1451 // the notification contains the original state.
1452 //
1453 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1454
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001455 Collection entries = new ArrayList();
1456 entries.add(flowEntry);
1457 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Pavlin Radoslavov9fbdc992014-01-12 20:56:58 -08001458 PerformanceMonitor.stop(tag);
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}