blob: 4c2bdf8ee94d0b95da538f23a861d830113150be [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 Radoslavov6b3b4ad2014-03-19 11:58:06 -070037import net.onrc.onos.ofcontroller.util.PerformanceMonitor;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -080038import net.onrc.onos.ofcontroller.util.Port;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080039import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -070040import net.onrc.onos.registry.controller.IControllerRegistryService;
Pavlin Radoslavov53219802013-12-06 11:02:04 -080041
Yuta HIGUCHI2d5ac522014-01-22 10:21:41 -080042import com.esotericsoftware.kryo.Kryo;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070043import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
46/**
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -070047 * Class for FlowPath Maintenance.
48 * This class listens for FlowEvents to:
49 * - Maintain a local cache of the Network Topology.
50 * - Detect FlowPaths impacted by Topology change.
51 * - Recompute impacted FlowPath using cached Topology.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070052 */
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080053class FlowEventHandler extends Thread implements IFlowEventHandlerService,
54 IOFSwitchListener {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080055
Matteo Gerola468ce632014-02-26 20:10:49 -080056 private boolean enableOnrc2014MeasurementsFlows = false;
57 private boolean enableOnrc2014MeasurementsTopology = false;
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -080058
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070059 /** The logger. */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -070060 private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
TeruU417fe022014-02-04 12:59:30 -080061
TeruU6464af02014-02-06 21:38:45 -080062 private final int FLOW_IDLE_TIMEOUT_ADDED_SECONDS = 5;
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 Radoslavov52163ed2014-03-19 11:39:34 -070068 private IControllerRegistryService registryService; // The Registry Service
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070069 private Topology topology; // The network topology
Pavlin Radoslavov53219802013-12-06 11:02:04 -080070 private KryoFactory kryoFactory = new KryoFactory();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070071
72 // The queue with Flow Path and Topology Element updates
73 private BlockingQueue<EventEntry<?>> networkEvents =
74 new LinkedBlockingQueue<EventEntry<?>>();
75
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070076 // The pending Topology, FlowPath, and FlowEntry events
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070077 private List<EventEntry<TopologyElement>> topologyEvents =
78 new LinkedList<EventEntry<TopologyElement>>();
79 private List<EventEntry<FlowPath>> flowPathEvents =
80 new LinkedList<EventEntry<FlowPath>>();
Pavlin Radoslavovb7506842013-10-29 17:46:54 -070081 private List<EventEntry<FlowEntry>> flowEntryEvents =
82 new LinkedList<EventEntry<FlowEntry>>();
Pavlin Radoslavov2194d112014-01-10 13:36:00 -080083 private List<EventEntry<Pair<FlowId, Dpid>>> flowIdEvents =
84 new LinkedList<EventEntry<Pair<FlowId, Dpid>>>();
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -080085 private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
86 new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
Pavlin Radoslavovcc757162014-01-10 16:26:38 -080087 private List<EventEntry<Dpid>> switchDpidEvents =
88 new LinkedList<EventEntry<Dpid>>();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -070089
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080090 // All internally computed Flow Paths
91 private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
92
93 // The Flow Entries received as notifications with unmatched Flow Paths
94 private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
95 new HashMap<Long, FlowEntry>();
96
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080097 //
98 // Transient state for processing the Flow Paths:
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -080099 // - The Flow Paths that should be recomputed
100 // - The Flow Paths with modified Flow Entries
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800101 // - The Flow Paths that we should check if installed in all switches
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800102 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800103 private Map<Long, FlowPath> shouldRecomputeFlowPaths =
104 new HashMap<Long, FlowPath>();
105 private Map<Long, FlowPath> modifiedFlowPaths =
106 new HashMap<Long, FlowPath>();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800107 private Map<Long, FlowPath> checkIfInstalledFlowPaths =
108 new HashMap<Long, FlowPath>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800109
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700110 /**
111 * Constructor for a given Flow Manager and Datagrid Service.
112 *
113 * @param flowManager the Flow Manager to use.
114 * @param datagridService the Datagrid Service to use.
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700115 * @param registryService the Registry Service to use.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700116 */
Pavlin Radoslavov9a859022013-10-30 10:08:24 -0700117 FlowEventHandler(FlowManager flowManager,
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700118 IDatagridService datagridService,
119 IControllerRegistryService registryService) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700120 this.flowManager = flowManager;
121 this.datagridService = datagridService;
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700122 this.registryService = registryService;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700123 this.topology = new Topology();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700124 }
125
126 /**
Pavlin Radoslavoved0f4a82013-11-04 16:38:36 -0800127 * Get the network topology.
128 *
129 * @return the network topology.
130 */
131 protected Topology getTopology() { return this.topology; }
132
133 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800134 * Startup processing.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700135 */
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800136 private void startup() {
Yoshi Muroi5804ce92014-02-08 03:58:04 -0800137 this.dbHandler = GraphDBManager.getDBOperation();
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800138
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700139 //
140 // Obtain the initial Topology state
141 //
142 Collection<TopologyElement> topologyElements =
143 datagridService.getAllTopologyElements();
144 for (TopologyElement topologyElement : topologyElements) {
145 EventEntry<TopologyElement> eventEntry =
146 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
147 topologyEvents.add(eventEntry);
148 }
149 //
150 // Obtain the initial Flow Path state
151 //
152 Collection<FlowPath> flowPaths = datagridService.getAllFlows();
153 for (FlowPath flowPath : flowPaths) {
154 EventEntry<FlowPath> eventEntry =
155 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
156 flowPathEvents.add(eventEntry);
157 }
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700158 //
159 // Obtain the initial FlowEntry state
160 //
161 Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
162 for (FlowEntry flowEntry : flowEntries) {
163 EventEntry<FlowEntry> eventEntry =
164 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
165 flowEntryEvents.add(eventEntry);
166 }
167
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800168 //
169 // Obtain the initial FlowId state
170 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800171 Collection<Pair<FlowId, Dpid>> flowIds =
172 datagridService.getAllFlowIds();
173 for (Pair<FlowId, Dpid> pair : flowIds) {
174 EventEntry<Pair<FlowId, Dpid>> eventEntry =
175 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800176 flowIdEvents.add(eventEntry);
177 }
178
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800179 //
180 // Obtain the initial FlowEntryId state
181 //
182 Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
183 datagridService.getAllFlowEntryIds();
184 for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
185 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
186 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
187 flowEntryIdEvents.add(eventEntry);
188 }
189
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800190 // Process the initial events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800191 synchronized (allFlowPaths) {
192 processEvents();
193 }
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800194
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800195 }
196
197 /**
198 * Run the thread.
199 */
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800200 @Override
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800201 public void run() {
Yuta HIGUCHI61509a42013-12-17 10:41:04 -0800202 this.setName("FlowEventHandler " + this.getId());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800203 startup();
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700204
205 //
206 // The main loop
207 //
208 Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
209 try {
210 while (true) {
211 EventEntry<?> eventEntry = networkEvents.take();
212 collection.add(eventEntry);
213 networkEvents.drainTo(collection);
214
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700215 //
216 // Demultiplex all events:
217 // - EventEntry<TopologyElement>
218 // - EventEntry<FlowPath>
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700219 // - EventEntry<FlowEntry>
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800220 // - EventEntry<Pair<FlowId, Dpid>>
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800221 // - EventEntry<Pair<FlowEntryId, Dpid>>
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700222 //
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700223 for (EventEntry<?> event : collection) {
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800224 // Topology event
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700225 if (event.eventData() instanceof TopologyElement) {
226 EventEntry<TopologyElement> topologyEventEntry =
227 (EventEntry<TopologyElement>)event;
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800228
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700229 topologyEvents.add(topologyEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800230 continue;
231 }
232
233 // FlowPath event
234 if (event.eventData() instanceof FlowPath) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700235 EventEntry<FlowPath> flowPathEventEntry =
236 (EventEntry<FlowPath>)event;
237 flowPathEvents.add(flowPathEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800238 continue;
239 }
240
241 // FlowEntry event
242 if (event.eventData() instanceof FlowEntry) {
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700243 EventEntry<FlowEntry> flowEntryEventEntry =
244 (EventEntry<FlowEntry>)event;
245 flowEntryEvents.add(flowEntryEventEntry);
Pavlin Radoslavovc8038a82013-12-02 17:43:20 -0800246 continue;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700247 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800248
249 // FlowId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800250 if (event.eventData() instanceof Pair) {
251 EventEntry<Pair<FlowId, Dpid>> flowIdEventEntry =
252 (EventEntry<Pair<FlowId, Dpid>>)event;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800253 flowIdEvents.add(flowIdEventEntry);
254 continue;
255 }
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800256
257 // Switch Dpid event
258 if (event.eventData() instanceof Dpid) {
259 EventEntry<Dpid> switchDpidEventEntry =
260 (EventEntry<Dpid>)event;
261 switchDpidEvents.add(switchDpidEventEntry);
262 continue;
263 }
264
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800265 // FlowEntryId event
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800266 // TODO: Fix the code below if we need again to handle
267 // the FlowEntryId events
268 /*
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -0800269 if (event.eventData() instanceof Pair) {
270 EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
271 (EventEntry<Pair<FlowEntryId, Dpid>>)event;
272 flowEntryIdEvents.add(flowEntryIdEventEntry);
273 continue;
274 }
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800275 */
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700276 }
277 collection.clear();
Pavlin Radoslavoved4c7a92013-10-26 21:36:21 -0700278
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700279 // Process the events (if any)
Pavlin Radoslavov53219802013-12-06 11:02:04 -0800280 synchronized (allFlowPaths) {
281 processEvents();
282 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700283 }
284 } catch (Exception exception) {
285 log.debug("Exception processing Network Events: ", exception);
286 }
287 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800288
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700289 /**
290 * Process the events (if any)
291 */
292 private void processEvents() {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800293 Collection<FlowEntry> modifiedFlowEntries;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700294
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800295 if (enableOnrc2014MeasurementsFlows) {
296
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800297 PerformanceMonitor.start("EventHandler.ProcessAllEvents");
298
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800299 if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
300 switchDpidEvents.isEmpty()) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800301 return; // Nothing to do
302 }
303
304 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
305
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800306 // Process the Switch Dpid events
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800307 PerformanceMonitor.start("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800308 processSwitchDpidEvents();
Pavlin Radoslavov51800822014-01-12 22:33:40 -0800309 PerformanceMonitor.stop("EventHandler.SwitchDpidEvents");
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800310
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800311 // Process the Flow ID events
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800312 PerformanceMonitor.start("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800313 processFlowIdEvents(mySwitches);
Pavlin Radoslavovcfcd2722014-01-12 22:32:36 -0800314 PerformanceMonitor.stop("EventHandler.FlowIdEvents");
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800315
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800316 // Fetch the topology
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800317 PerformanceMonitor.start("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800318 processTopologyEvents();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800319 PerformanceMonitor.stop("EventHandler.ReadTopology");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800320
321 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800322 PerformanceMonitor.start("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800323 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
324 if (recomputeFlowPath(flowPath))
325 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
326 }
327
328 // Assign the Flow Entry ID as needed
329 for (FlowPath flowPath : modifiedFlowPaths.values()) {
330 for (FlowEntry flowEntry : flowPath.flowEntries()) {
331 if (! flowEntry.isValidFlowEntryId()) {
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700332 long id = registryService.getNextUniqueId();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800333 flowEntry.setFlowEntryId(new FlowEntryId(id));
334 }
335 }
336 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800337 PerformanceMonitor.stop("EventHandler.RecomputeFlows");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800338
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800339 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800340 // Push the modified state to the database
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800341 //
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800342 PerformanceMonitor.start("EventHandler.WriteFlowsToDb");
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800343 for (FlowPath flowPath : modifiedFlowPaths.values()) {
344 //
345 // Delete the Flow Path from the Network Map
346 //
347 if (flowPath.flowPathUserState() ==
348 FlowPathUserState.FP_USER_DELETE) {
349 log.debug("Deleting Flow Path From Database: {}", flowPath);
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800350 // TODO: For now the deleting of a Flow Path is blocking
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800351 ParallelFlowDatabaseOperation.deleteFlow(dbHandler,
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800352 flowPath.flowId());
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800353 //
354 // NOTE: For now the sending of the notifications
355 // is outside of this loop, so the performance measurements
356 // are more accurate.
357 //
358 /*
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800359 // Send the notifications for the deleted Flow Entries
360 for (FlowEntry flowEntry : flowPath.flowEntries()) {
361 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
362 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800363 */
Pavlin Radoslavov6c3e6802014-01-10 19:27:34 -0800364
Pavlin Radoslavov85d81c02014-01-10 17:22:22 -0800365 continue;
366 }
367
368 log.debug("Pushing Flow Path To Database: {}", flowPath);
369 //
370 // Write the Flow Path to the Network Map
371 //
372 ParallelFlowDatabaseOperation.addFlow(dbHandler, flowPath,
373 datagridService);
374 }
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800375 PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
376
377 //
378 // Send the notifications for the deleted Flow Entries
379 // NOTE: This code was pulled outside of the above loop,
380 // so the performance measurements are more accurate.
381 //
382 PerformanceMonitor.start("EventHandler.NotificationSend.FlowEntryRemoved");
383 for (FlowPath flowPath : modifiedFlowPaths.values()) {
384 if (flowPath.flowPathUserState() ==
385 FlowPathUserState.FP_USER_DELETE) {
386 for (FlowEntry flowEntry : flowPath.flowEntries()) {
387 datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
388 }
389 }
390 }
Pavlin Radoslavovdbd09cc2014-01-12 18:13:35 -0800391 PerformanceMonitor.stop("EventHandler.NotificationSend.FlowEntryRemoved");
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800392
393 // Cleanup
394 topologyEvents.clear();
395 flowIdEvents.clear();
Pavlin Radoslavov2d6e5f12014-01-10 16:34:05 -0800396 switchDpidEvents.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800397 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800398 // NOTE: Keep a cache with my Flow Paths
399 // allFlowPaths.clear();
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800400 shouldRecomputeFlowPaths.clear();
401 modifiedFlowPaths.clear();
402
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800403 PerformanceMonitor.stop("EventHandler.ProcessAllEvents");
Pavlin Radoslavov8bd6d112014-01-12 20:12:37 -0800404
405
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800406// PerformanceMonitor.report("EventHandler.SwitchDpidEvents");
407// PerformanceMonitor.report("EventHandler.FlowIdEvents");
408// PerformanceMonitor.report("EventHandler.ReadTopology");
409// PerformanceMonitor.report("EventHandler.RecomputeFlows");
410// PerformanceMonitor.report("EventHandler.WriteFlowsToDb");
411// PerformanceMonitor.report("EventHandler.NotificationSend.FlowEntryRemoved");
412// PerformanceMonitor.report("EventHandler.ProcessAllEvents");
Brian O'Connor0d9963f2014-01-14 14:44:21 -0800413// PerformanceMonitor.report();
414// PerformanceMonitor.clear();
Pavlin Radoslavove2497672014-01-12 18:03:35 -0800415
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800416 return;
417 }
418
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700419 if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
420 flowEntryEvents.isEmpty()) {
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700421 return; // Nothing to do
Pavlin Radoslavovb7506842013-10-29 17:46:54 -0700422 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -0700423
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800424 processFlowPathEvents();
425 processTopologyEvents();
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800426 processUnmatchedFlowEntryAdd();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800427 processFlowEntryEvents();
428
429 // Recompute all affected Flow Paths and keep only the modified
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800430 for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800431 if (recomputeFlowPath(flowPath))
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800432 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800433 }
434
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800435 // Extract the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800436 modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800437
438 // Assign missing Flow Entry IDs
439 assignFlowEntryId(modifiedFlowEntries);
440
441 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800442 // Push the modified state to the Flow Manager
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800443 //
Pavlin Radoslavova0c16362013-12-04 13:18:08 -0800444 flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
445 modifiedFlowEntries);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800446
447 //
448 // Remove Flow Entries that were deleted
449 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800450 for (FlowPath flowPath : modifiedFlowPaths.values())
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800451 flowPath.dataPath().removeDeletedFlowEntries();
452
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800453 //
454 // Check if Flow Paths have been installed into all switches,
455 // and generate the appropriate events.
456 //
457 checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
458
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800459 // Cleanup
460 topologyEvents.clear();
461 flowPathEvents.clear();
462 flowEntryEvents.clear();
463 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800464 shouldRecomputeFlowPaths.clear();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800465 modifiedFlowPaths.clear();
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800466 checkIfInstalledFlowPaths.clear();
467 }
468
469 /**
470 * Check if Flow Paths have been installed into all switches,
471 * and generate the appropriate events.
472 *
473 * @param flowPaths the flowPaths to process.
474 */
475 private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
476 List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
477
478 Kryo kryo = kryoFactory.newKryo();
479
480 for (FlowPath flowPath : flowPaths) {
481 boolean isInstalled = true;
Jonathan Hart0444d932014-01-22 15:06:17 -0800482
483 if (flowPath.flowEntries().isEmpty()) {
484 continue;
485 }
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -0800486
487 //
488 // Check whether all Flow Entries have been installed
489 //
490 for (FlowEntry flowEntry : flowPath.flowEntries()) {
491 if (flowEntry.flowEntrySwitchState() !=
492 FlowEntrySwitchState.FE_SWITCH_UPDATED) {
493 isInstalled = false;
494 break;
495 }
496 }
497
498 if (isInstalled) {
499 // Create a copy and add it to the list
500 FlowPath copyFlowPath = kryo.copy(flowPath);
501 installedFlowPaths.add(copyFlowPath);
502 }
503 }
504 kryoFactory.deleteKryo(kryo);
505
506 // Generate an event for the installed Flow Path.
507 flowManager.notificationFlowPathsInstalled(installedFlowPaths);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800508 }
509
510 /**
511 * Extract the modified Flow Entries.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800512 *
513 * @param modifiedFlowPaths the Flow Paths to process.
514 * @return a collection with the modified Flow Entries.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800515 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800516 private Collection<FlowEntry> extractModifiedFlowEntries(
517 Collection<FlowPath> modifiedFlowPaths) {
518 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800519
520 // Extract only the modified Flow Entries
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800521 for (FlowPath flowPath : modifiedFlowPaths) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800522 for (FlowEntry flowEntry : flowPath.flowEntries()) {
523 if (flowEntry.flowEntrySwitchState() ==
524 FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800525 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800526 }
527 }
528 }
529 return modifiedFlowEntries;
530 }
531
532 /**
533 * Assign the Flow Entry ID as needed.
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800534 *
535 * @param modifiedFlowEnries the collection of Flow Entries that need
536 * Flow Entry ID assigned.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800537 */
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800538 private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800539 if (modifiedFlowEntries.isEmpty())
540 return;
541
542 Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
543
544 //
545 // Assign the Flow Entry ID only for Flow Entries for my switches
546 //
Pavlin Radoslavovafc4aa92013-12-04 12:44:23 -0800547 for (FlowEntry flowEntry : modifiedFlowEntries) {
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800548 IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
549 if (mySwitch == null)
550 continue;
551 if (! flowEntry.isValidFlowEntryId()) {
Pavlin Radoslavov52163ed2014-03-19 11:39:34 -0700552 long id = registryService.getNextUniqueId();
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800553 flowEntry.setFlowEntryId(new FlowEntryId(id));
554 }
555 }
556 }
557
558 /**
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800559 * Fix a flow fetched from the database.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800560 *
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800561 * @param flowPath the Flow to fix.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800562 */
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800563 private void fixFlowFromDatabase(FlowPath flowPath) {
564 //
565 // TODO: Bug workaround / fix :
566 // method FlowDatabaseOperation.extractFlowEntry() doesn't
567 // fetch the inPort and outPort, hence we assign them here.
568 //
569 // Assign the inPort and outPort for the Flow Entries
570 for (FlowEntry flowEntry : flowPath.flowEntries()) {
571 // Set the inPort
572 do {
573 if (flowEntry.inPort() != null)
574 break;
575 if (flowEntry.flowEntryMatch() == null)
576 break;
577 Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
578 flowEntry.setInPort(inPort);
579 } while (false);
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800580
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800581 // Set the outPort
582 do {
583 if (flowEntry.outPort() != null)
584 break;
585 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
586 if (fa.actionOutput() != null) {
587 Port outPort = new Port(fa.actionOutput().port().value());
588 flowEntry.setOutPort(outPort);
589 break;
590 }
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800591 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800592 } while (false);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800593 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800594 }
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800595
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800596 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -0800597 * Process the Switch Dpid events.
598 */
599 private void processSwitchDpidEvents() {
600 Map<Long, Dpid> addedSwitches = new HashMap<Long, Dpid>();
601 Map<Long, Dpid> removedSwitches = new HashMap<Long, Dpid>();
602
603 //
604 // Process all Switch Dpid events and update the appropriate state
605 //
606 for (EventEntry<Dpid> eventEntry : switchDpidEvents) {
607 Dpid dpid = eventEntry.eventData();
608
609 log.debug("SwitchDpid Event: {} {}", eventEntry.eventType(), dpid);
610
611 // Compute the final set of added and removed switches
612 switch (eventEntry.eventType()) {
613 case ENTRY_ADD:
614 addedSwitches.put(dpid.value(), dpid);
615 removedSwitches.remove(dpid.value());
616 break;
617 case ENTRY_REMOVE:
618 addedSwitches.remove(dpid.value());
619 removedSwitches.put(dpid.value(), dpid);
620 break;
621 }
622 }
623
624 //
625 // Remove the Flows from the local cache if the removed
626 // switch is the Source Switch.
627 //
628 // TODO: This search can be expensive for a large number of flows
629 // and should be optmized.
630 //
631 List<FlowId> deleteFlowIds = new LinkedList<FlowId>();
632 for (Dpid switchDpid : removedSwitches.values()) {
633 for (FlowPath flowPath : allFlowPaths.values()) {
634 Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
635 if (srcDpid.value() == switchDpid.value())
636 deleteFlowIds.add(flowPath.flowId());
637 }
638 }
639 //
640 // Remove the Flows from the local cache
641 //
642 for (FlowId flowId : deleteFlowIds)
643 allFlowPaths.remove(flowId.value());
644
645 // Get the Flows for the added switches
646 Collection<FlowPath> flowPaths =
647 ParallelFlowDatabaseOperation.getFlowsForSwitches(dbHandler,
648 addedSwitches.values());
649 for (FlowPath flowPath : flowPaths) {
650 allFlowPaths.put(flowPath.flowId().value(), flowPath);
651 }
652 }
653
654 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800655 * Process the Flow ID events.
656 *
657 * @param mySwitches the collection of my switches.
658 */
659 private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800660 List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
661
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800662 //
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800663 // Process all Flow Id events and update the appropriate state
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800664 //
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800665 for (EventEntry<Pair<FlowId, Dpid>> eventEntry : flowIdEvents) {
666 Pair<FlowId, Dpid> pair = eventEntry.eventData();
667 FlowId flowId = pair.first;
668 Dpid dpid = pair.second;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800669
Pavlin Radoslavov2194d112014-01-10 13:36:00 -0800670 log.debug("Flow ID Event: {} {} {}", eventEntry.eventType(),
671 flowId, dpid);
672
673 //
674 // Ignore Flows if the Source Switch is not controlled by this
675 // instance.
676 //
677 if (mySwitches.get(dpid.value()) == null)
678 continue;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800679
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800680 switch (eventEntry.eventType()) {
681 case ENTRY_ADD: {
682 //
683 // Add a new Flow Path
684 //
685 if (allFlowPaths.get(flowId.value()) != null) {
686 //
687 // TODO: What to do if the Flow Path already exists?
688 // Fow now, we just re-add it.
689 //
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800690 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800691 shouldFetchMyFlowIds.add(flowId);
692
693 break;
Pavlin Radoslavov3a7cc902014-01-09 02:32:08 -0800694 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800695
696 case ENTRY_REMOVE: {
697 //
698 // Remove an existing Flow Path.
699 //
700 // Find the Flow Path, and mark the Flow and its Flow Entries
701 // for deletion.
702 //
703 FlowPath existingFlowPath =
704 allFlowPaths.get(flowId.value());
705 if (existingFlowPath == null)
706 continue; // Nothing to do
707
708 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
709 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
710 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
711 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
712 }
713
714 // Remove the Flow Path from the internal state
715 Long key = existingFlowPath.flowId().value();
716 allFlowPaths.remove(key);
717 shouldRecomputeFlowPaths.remove(key);
718 modifiedFlowPaths.put(key, existingFlowPath);
719
720 break;
721 }
722 }
723 }
724
725 // Get my Flows
726 Collection<FlowPath> myFlows =
Pavlin Radoslavov6602b6a2014-01-10 16:43:29 -0800727 ParallelFlowDatabaseOperation.getFlows(dbHandler,
728 shouldFetchMyFlowIds);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800729
730 for (FlowPath flowPath : myFlows) {
731 fixFlowFromDatabase(flowPath);
732
733 switch (flowPath.flowPathType()) {
734 case FP_TYPE_SHORTEST_PATH:
735 //
736 // Reset the Data Path, in case it was set already, because
737 // we are going to recompute it anyway.
738 //
739 flowPath.flowEntries().clear();
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800740 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
741 flowPath);
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800742 break;
743 case FP_TYPE_EXPLICIT_PATH:
744 //
745 // Mark all Flow Entries for installation in the switches.
746 //
747 for (FlowEntry flowEntry : flowPath.flowEntries()) {
748 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
749 }
750 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
751 break;
752 case FP_TYPE_UNKNOWN:
753 log.error("FlowPath event with unknown type");
754 break;
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800755 }
Pavlin Radoslavov417398f2014-01-10 13:04:33 -0800756 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovdb1f91c2014-01-08 16:04:17 -0800757 }
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800758 }
759
760 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800761 * Process the Flow Entry ID events.
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800762 *
763 * @param mySwitches the collection of my switches.
764 * @return a collection of modified Flow Entries this instance needs
765 * to push to its own switches.
766 */
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800767 private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800768 List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
769
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800770 //
771 // Process all Flow ID events and update the appropriate state
772 //
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800773 for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
774 Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
775 FlowEntryId flowEntryId = pair.first;
776 Dpid dpid = pair.second;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800777
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800778 log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
779 flowEntryId, dpid);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800780
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800781 if (mySwitches.get(dpid.value()) == null)
782 continue;
783
784 // Fetch the Flow Entry
785 FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
786 flowEntryId);
787 if (flowEntry == null) {
788 log.debug("Flow Entry ID {} : Flow Entry not found!",
789 flowEntryId);
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800790 continue;
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800791 }
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800792 modifiedFlowEntries.add(flowEntry);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800793 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800794
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800795 return modifiedFlowEntries;
796 }
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -0800797
798 /**
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800799 * Process the Flow Path events.
800 */
801 private void processFlowPathEvents() {
802 //
803 // Process all Flow Path events and update the appropriate state
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700804 //
805 for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
806 FlowPath flowPath = eventEntry.eventData();
807
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800808 log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800809
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700810 switch (eventEntry.eventType()) {
811 case ENTRY_ADD: {
812 //
813 // Add a new Flow Path
814 //
815 if (allFlowPaths.get(flowPath.flowId().value()) != null) {
816 //
817 // TODO: What to do if the Flow Path already exists?
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800818 // Fow now, we just re-add it.
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700819 //
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700820 }
821
822 switch (flowPath.flowPathType()) {
823 case FP_TYPE_SHORTEST_PATH:
824 //
825 // Reset the Data Path, in case it was set already, because
826 // we are going to recompute it anyway.
827 //
828 flowPath.flowEntries().clear();
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800829 shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
830 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700831 break;
832 case FP_TYPE_EXPLICIT_PATH:
833 //
834 // Mark all Flow Entries for installation in the switches.
835 //
836 for (FlowEntry flowEntry : flowPath.flowEntries()) {
837 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
838 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800839 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700840 break;
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800841 case FP_TYPE_UNKNOWN:
842 log.error("FlowPath event with unknown type");
843 break;
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700844 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800845 allFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700846
847 break;
848 }
849
850 case ENTRY_REMOVE: {
851 //
852 // Remove an existing Flow Path.
853 //
854 // Find the Flow Path, and mark the Flow and its Flow Entries
855 // for deletion.
856 //
857 FlowPath existingFlowPath =
858 allFlowPaths.get(flowPath.flowId().value());
859 if (existingFlowPath == null)
860 continue; // Nothing to do
861
862 existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
863 for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
864 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
865 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
866 }
867
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800868 // Remove the Flow Path from the internal state
869 Long key = existingFlowPath.flowId().value();
870 allFlowPaths.remove(key);
871 shouldRecomputeFlowPaths.remove(key);
872 modifiedFlowPaths.put(key, existingFlowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700873
874 break;
875 }
876 }
877 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800878 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700879
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800880 /**
881 * Process the Topology events.
882 */
883 private void processTopologyEvents() {
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800884 boolean isTopologyModified = false;
885
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800886 if (enableOnrc2014MeasurementsTopology) {
887 if (topologyEvents.isEmpty())
888 return;
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800889
Pavlin Radoslavov2a8b9de2014-01-09 15:58:32 -0800890 // TODO: Code for debugging purpose only
891 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
892 TopologyElement topologyElement = eventEntry.eventData();
893 log.debug("Topology Event: {} {}", eventEntry.eventType(),
894 topologyElement.toString());
895 }
896
Pavlin Radoslavov1b454902014-01-09 16:28:27 -0800897 log.debug("[BEFORE] {}", topology.toString());
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800898 topology.readFromDatabase(dbHandler);
899 log.debug("[AFTER] {}", topology.toString());
900 shouldRecomputeFlowPaths.putAll(allFlowPaths);
901 return;
902 }
903
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700904 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800905 // Process all Topology events and update the appropriate state
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700906 //
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700907 for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
908 TopologyElement topologyElement = eventEntry.eventData();
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800909
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800910 log.debug("Topology Event: {} {}", eventEntry.eventType(),
Pavlin Radoslavov80bc3cf2014-01-08 11:17:30 -0800911 topologyElement.toString());
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -0800912
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700913 switch (eventEntry.eventType()) {
914 case ENTRY_ADD:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800915 isTopologyModified |= topology.addTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700916 break;
917 case ENTRY_REMOVE:
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800918 isTopologyModified |= topology.removeTopologyElement(topologyElement);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700919 break;
920 }
921 }
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700922 if (isTopologyModified) {
923 // TODO: For now, if the topology changes, we recompute all Flows
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800924 shouldRecomputeFlowPaths.putAll(allFlowPaths);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -0700925 }
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800926 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700927
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800928 /**
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800929 * Process previously received Flow Entries with unmatched Flow Paths.
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800930 */
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800931 private void processUnmatchedFlowEntryAdd() {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800932 FlowPath flowPath;
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800933 FlowEntry localFlowEntry;
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800934
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -0700935 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800936 // Update Flow Entries with previously unmatched Flow Entry updates
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700937 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800938 if (! unmatchedFlowEntryAdd.isEmpty()) {
939 Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
940 for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800941 // log.debug("Processing Unmatched Flow Entry: {}",
942 // flowEntry.toString());
943
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800944 flowPath = allFlowPaths.get(flowEntry.flowId().value());
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800945 if (flowPath == 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 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
951 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800952 remainingUpdates.put(flowEntry.flowEntryId().value(),
953 flowEntry);
954 continue;
955 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800956 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
957 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
958 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700959 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800960 unmatchedFlowEntryAdd = remainingUpdates;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700961 }
Pavlin Radoslavov9bb40552013-12-18 21:08:30 -0800962 }
963
964 /**
965 * Process the Flow Entry events.
966 */
967 private void processFlowEntryEvents() {
968 FlowPath flowPath;
969 FlowEntry localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700970
971 //
Pavlin Radoslavov9f33edb2013-11-06 18:24:37 -0800972 // Process all Flow Entry events and update the appropriate state
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700973 //
974 for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
975 FlowEntry flowEntry = eventEntry.eventData();
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800976
977 log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800978 flowEntry);
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800979
980 if ((! flowEntry.isValidFlowId()) ||
981 (! flowEntry.isValidFlowEntryId())) {
982 continue;
983 }
984
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -0700985 switch (eventEntry.eventType()) {
986 case ENTRY_ADD:
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800987 flowPath = allFlowPaths.get(flowEntry.flowId().value());
988 if (flowPath == null) {
989 // Flow Path not found: keep the entry for later matching
990 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
991 flowEntry);
992 break;
993 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -0800994 localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
995 if (localFlowEntry == null) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -0800996 // Flow Entry not found: keep the entry for later matching
997 unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
998 flowEntry);
999 break;
1000 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001001 if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
1002 // Add the updated Flow Path to the list of updated paths
1003 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
1004 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001005 break;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001006
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001007 case ENTRY_REMOVE:
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001008 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1009 if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001010 continue; // Removed previously unmatched entry
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001011 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001012
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001013 flowPath = allFlowPaths.get(flowEntry.flowId().value());
1014 if (flowPath == null) {
1015 // Flow Path not found: ignore the update
1016 break;
1017 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001018 localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
1019 if (localFlowEntry == null) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -08001020 // Flow Entry not found: ignore it
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001021 break;
1022 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001023 if (updateFlowEntryRemove(flowPath, localFlowEntry,
1024 flowEntry)) {
1025 // Add the updated Flow Path to the list of updated paths
1026 modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
1027 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001028 break;
1029 }
1030 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001031 }
1032
1033 /**
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001034 * Find a Flow Entry that should be updated because of an external
1035 * ENTRY_ADD event.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001036 *
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001037 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001038 * @param newFlowEntry the FlowEntry with the new state.
1039 * @return the Flow Entry that should be updated if found, otherwise null.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001040 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001041 private FlowEntry findFlowEntryAdd(FlowPath flowPath,
1042 FlowEntry newFlowEntry) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001043 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001044 // Iterate over all Flow Entries and find a match.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001045 //
1046 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001047 if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001048 newFlowEntry)) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001049 continue;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001050 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001051
1052 //
1053 // Local Flow Entry match found
1054 //
1055 if (localFlowEntry.isValidFlowEntryId()) {
1056 if (localFlowEntry.flowEntryId().value() !=
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001057 newFlowEntry.flowEntryId().value()) {
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001058 //
1059 // Find a local Flow Entry, but the Flow Entry ID doesn't
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001060 // match. Keep looking.
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001061 //
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001062 continue;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001063 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001064 }
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001065 return localFlowEntry;
1066 }
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001067
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001068 return null; // Entry not found
1069 }
1070
1071 /**
1072 * Update a Flow Entry because of an external ENTRY_ADD event.
1073 *
1074 * @param flowPath the FlowPath for the Flow Entry to update.
1075 * @param localFlowEntry the local Flow Entry to update.
1076 * @param newFlowEntry the FlowEntry with the new state.
1077 * @return true if the local Flow Entry was updated, otherwise false.
1078 */
1079 private boolean updateFlowEntryAdd(FlowPath flowPath,
1080 FlowEntry localFlowEntry,
1081 FlowEntry newFlowEntry) {
1082 boolean updated = false;
1083
1084 if (localFlowEntry.flowEntryUserState() ==
1085 FlowEntryUserState.FE_USER_DELETE) {
1086 // Don't add-back a Flow Entry that is already deleted
1087 return false;
1088 }
1089
1090 if (! localFlowEntry.isValidFlowEntryId()) {
1091 // Update the Flow Entry ID
1092 FlowEntryId flowEntryId =
1093 new FlowEntryId(newFlowEntry.flowEntryId().value());
1094 localFlowEntry.setFlowEntryId(flowEntryId);
1095 updated = true;
1096 }
1097
1098 //
1099 // Update the local Flow Entry, and keep state to check
1100 // if the Flow Path has been installed.
1101 //
1102 if (localFlowEntry.flowEntryUserState() !=
1103 newFlowEntry.flowEntryUserState()) {
1104 localFlowEntry.setFlowEntryUserState(
1105 newFlowEntry.flowEntryUserState());
1106 updated = true;
1107 }
1108 if (localFlowEntry.flowEntrySwitchState() !=
1109 newFlowEntry.flowEntrySwitchState()) {
1110 localFlowEntry.setFlowEntrySwitchState(
1111 newFlowEntry.flowEntrySwitchState());
Pavlin Radoslavov7208e9a2013-12-11 14:31:07 -08001112 checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001113 updated = true;
1114 }
1115
1116 return updated;
1117 }
1118
1119 /**
1120 * Find a Flow Entry that should be updated because of an external
1121 * ENTRY_REMOVE event.
1122 *
1123 * @param flowPath the FlowPath for the Flow Entry to update.
1124 * @param newFlowEntry the FlowEntry with the new state.
1125 * @return the Flow Entry that should be updated if found, otherwise null.
1126 */
1127 private FlowEntry findFlowEntryRemove(FlowPath flowPath,
1128 FlowEntry newFlowEntry) {
1129 //
1130 // Iterate over all Flow Entries and find a match based on
1131 // the Flow Entry ID.
1132 //
1133 for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
1134 if (! localFlowEntry.isValidFlowEntryId())
1135 continue;
1136 if (localFlowEntry.flowEntryId().value() !=
1137 newFlowEntry.flowEntryId().value()) {
1138 continue;
1139 }
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001140 return localFlowEntry;
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001141 }
1142
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001143 return null; // Entry not found
1144 }
1145
1146 /**
1147 * Update a Flow Entry because of an external ENTRY_REMOVE event.
1148 *
1149 * @param flowPath the FlowPath for the Flow Entry to update.
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001150 * @param localFlowEntry the local Flow Entry to update.
1151 * @param newFlowEntry the FlowEntry with the new state.
1152 * @return true if the local Flow Entry was updated, otherwise false.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001153 */
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001154 private boolean updateFlowEntryRemove(FlowPath flowPath,
1155 FlowEntry localFlowEntry,
1156 FlowEntry newFlowEntry) {
1157 boolean updated = false;
1158
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001159 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001160 // Update the local Flow Entry.
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001161 //
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001162 if (localFlowEntry.flowEntryUserState() !=
1163 newFlowEntry.flowEntryUserState()) {
1164 localFlowEntry.setFlowEntryUserState(
1165 newFlowEntry.flowEntryUserState());
1166 updated = true;
1167 }
1168 if (localFlowEntry.flowEntrySwitchState() !=
1169 newFlowEntry.flowEntrySwitchState()) {
1170 localFlowEntry.setFlowEntrySwitchState(
1171 newFlowEntry.flowEntrySwitchState());
1172 updated = true;
Pavlin Radoslavov63117172013-11-07 02:18:37 -08001173 }
1174
Pavlin Radoslavov237fde72013-12-17 22:21:06 -08001175 return updated;
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001176 }
1177
1178 /**
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001179 * Recompute a Flow Path.
1180 *
1181 * @param flowPath the Flow Path to recompute.
1182 * @return true if the recomputed Flow Path has changed, otherwise false.
1183 */
1184 private boolean recomputeFlowPath(FlowPath flowPath) {
1185 boolean hasChanged = false;
1186
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001187 if (enableOnrc2014MeasurementsFlows) {
1188 // Cleanup the deleted Flow Entries from the earlier iteration
1189 flowPath.dataPath().removeDeletedFlowEntries();
Pavlin Radoslavov737aa522014-01-09 15:35:00 -08001190
1191 //
1192 // TODO: Fake it that the Flow Entries have been already pushed
1193 // into the switches, so we don't push them again.
1194 //
1195 for (FlowEntry flowEntry : flowPath.flowEntries()) {
1196 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
1197 }
Pavlin Radoslavov7bf837a2014-01-09 14:22:05 -08001198 }
1199
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001200 //
1201 // Test whether the Flow Path needs to be recomputed
1202 //
1203 switch (flowPath.flowPathType()) {
Yuta HIGUCHIe1038fb2013-10-30 15:35:18 -07001204 case FP_TYPE_UNKNOWN:
1205 return false; // Can't recompute on Unknown FlowType
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001206 case FP_TYPE_SHORTEST_PATH:
1207 break;
1208 case FP_TYPE_EXPLICIT_PATH:
1209 return false; // An explicit path never changes
1210 }
1211
1212 DataPath oldDataPath = flowPath.dataPath();
1213
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001214 // Compute the new path
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001215 DataPath newDataPath;
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08001216 newDataPath = TopologyManager.computeNetworkPath(topology,
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001217 flowPath);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001218 if (newDataPath == null) {
1219 // We need the DataPath to compare the paths
1220 newDataPath = new DataPath();
1221 }
1222 newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
1223
1224 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001225 // Test whether the new path is same
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001226 //
1227 if (oldDataPath.flowEntries().size() !=
1228 newDataPath.flowEntries().size()) {
1229 hasChanged = true;
1230 } else {
1231 Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
1232 Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
1233 while (oldIter.hasNext() && newIter.hasNext()) {
1234 FlowEntry oldFlowEntry = oldIter.next();
1235 FlowEntry newFlowEntry = newIter.next();
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001236 if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1237 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001238 hasChanged = true;
1239 break;
1240 }
1241 }
1242 }
1243 if (! hasChanged)
1244 return hasChanged;
1245
1246 //
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001247 // Merge the changes in the path:
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001248 // - If a Flow Entry for a switch is in the old data path, but not
1249 // in the new data path, then mark it for deletion.
1250 // - If a Flow Entry for a switch is in the new data path, but not
1251 // in the old data path, then mark it for addition.
1252 // - If a Flow Entry for a switch is in both the old and the new
1253 // data path, but it has changed, e.g., the incoming and/or outgoing
1254 // port(s), then mark the old Flow Entry for deletion, and mark
1255 // the new Flow Entry for addition.
1256 // - If a Flow Entry for a switch is in both the old and the new
1257 // data path, and it hasn't changed, then just keep it.
1258 //
1259 // NOTE: We use the Switch DPID of each entry to match the entries
1260 //
1261 Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
1262 Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
1263 ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
1264 List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
1265
1266 // Prepare maps with the Flow Entries, so they are fast to lookup
1267 for (FlowEntry flowEntry : oldDataPath.flowEntries())
1268 oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1269 for (FlowEntry flowEntry : newDataPath.flowEntries())
1270 newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
1271
1272 //
1273 // Find the old Flow Entries that should be deleted
1274 //
1275 for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
1276 FlowEntry newFlowEntry =
1277 newFlowEntriesMap.get(oldFlowEntry.dpid().value());
1278 if (newFlowEntry == null) {
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001279 // The old Flow Entry should be deleted: not on the path
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001280 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1281 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1282 deletedFlowEntries.add(oldFlowEntry);
1283 }
1284 }
1285
1286 //
1287 // Find the new Flow Entries that should be added or updated
1288 //
1289 int idx = 0;
1290 for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
1291 FlowEntry oldFlowEntry =
1292 oldFlowEntriesMap.get(newFlowEntry.dpid().value());
1293
1294 if ((oldFlowEntry != null) &&
Pavlin Radoslavov3ecd41e2013-10-29 14:29:30 -07001295 TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
1296 newFlowEntry)) {
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001297 //
1298 // Both Flow Entries are same
1299 //
1300 finalFlowEntries.add(oldFlowEntry);
1301 idx++;
1302 continue;
1303 }
1304
1305 if (oldFlowEntry != null) {
1306 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001307 // The old Flow Entry should be deleted: path diverges
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001308 //
1309 oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1310 oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1311 deletedFlowEntries.add(oldFlowEntry);
1312 }
1313
1314 //
1315 // Add the new Flow Entry
1316 //
Pavlin Radoslavov1c24f222013-10-30 13:56:46 -07001317 //
1318 // NOTE: Assign only the Flow ID.
1319 // The Flow Entry ID is assigned later only for the Flow Entries
1320 // this instance is responsible for.
1321 //
1322 newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001323
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001324 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001325 // Copy the Flow timeouts
1326 //
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001327 newFlowEntry.setHardTimeout(flowPath.hardTimeout());
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -08001328 newFlowEntry.setPriority(flowPath.priority());
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001329
TeruU417fe022014-02-04 12:59:30 -08001330 if (flowPath.idleTimeout() > 0) {
1331 if (idx == 0) {
1332 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1333 }
1334 else {
1335 newFlowEntry.setIdleTimeout(flowPath.idleTimeout() + FLOW_IDLE_TIMEOUT_ADDED_SECONDS);
1336 }
1337 } else if(flowPath.idleTimeout() == 0) {
1338 newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
1339 }
1340
Pavlin Radoslavov6fde2172013-12-10 11:23:18 -08001341 //
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001342 // Allocate the FlowEntryMatch by copying the default one
1343 // from the FlowPath (if set).
1344 //
1345 FlowEntryMatch flowEntryMatch = null;
1346 if (flowPath.flowEntryMatch() != null)
1347 flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
1348 else
1349 flowEntryMatch = new FlowEntryMatch();
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001350 newFlowEntry.setFlowEntryMatch(flowEntryMatch);
Pavlin Radoslavova4df9522013-12-03 11:03:04 -08001351
1352 // Set the incoming port matching
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001353 flowEntryMatch.enableInPort(newFlowEntry.inPort());
1354
1355 //
1356 // Set the actions:
1357 // If the first Flow Entry, copy the Flow Path actions to it.
1358 //
1359 FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
1360 if ((idx == 0) && (flowPath.flowEntryActions() != null)) {
1361 FlowEntryActions flowActions =
1362 new FlowEntryActions(flowPath.flowEntryActions());
1363 for (FlowEntryAction action : flowActions.actions())
1364 flowEntryActions.addAction(action);
1365 }
1366 idx++;
1367
1368 //
1369 // Add the outgoing port output action
1370 //
1371 FlowEntryAction flowEntryAction = new FlowEntryAction();
1372 flowEntryAction.setActionOutput(newFlowEntry.outPort());
1373 flowEntryActions.addAction(flowEntryAction);
1374
1375 //
1376 // Set the state of the new Flow Entry
1377 //
1378 newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
1379 newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
1380 finalFlowEntries.add(newFlowEntry);
1381 }
1382
1383 //
1384 // Replace the old Flow Entries with the new Flow Entries.
1385 // Note that the Flow Entries that will be deleted are added at
1386 // the end.
1387 //
Pavlin Radoslavovfb94edc2013-11-04 16:29:40 -08001388 finalFlowEntries.addAll(deletedFlowEntries);
Pavlin Radoslavovfb06a9e2013-10-28 23:56:15 -07001389 flowPath.dataPath().setFlowEntries(finalFlowEntries);
1390
1391 return hasChanged;
1392 }
1393
1394 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001395 * Receive a notification that a Flow is added.
1396 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001397 * @param flowPath the Flow that is added.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001398 */
1399 @Override
1400 public void notificationRecvFlowAdded(FlowPath flowPath) {
1401 EventEntry<FlowPath> eventEntry =
1402 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1403 networkEvents.add(eventEntry);
1404 }
1405
1406 /**
1407 * Receive a notification that a Flow is removed.
1408 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001409 * @param flowPath the Flow that is removed.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001410 */
1411 @Override
1412 public void notificationRecvFlowRemoved(FlowPath flowPath) {
1413 EventEntry<FlowPath> eventEntry =
1414 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
1415 networkEvents.add(eventEntry);
1416 }
1417
1418 /**
1419 * Receive a notification that a Flow is updated.
1420 *
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001421 * @param flowPath the Flow that is updated.
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001422 */
1423 @Override
1424 public void notificationRecvFlowUpdated(FlowPath flowPath) {
1425 // NOTE: The ADD and UPDATE events are processed in same way
1426 EventEntry<FlowPath> eventEntry =
1427 new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
1428 networkEvents.add(eventEntry);
1429 }
1430
1431 /**
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001432 * Receive a notification that a FlowEntry is added.
1433 *
1434 * @param flowEntry the FlowEntry that is added.
1435 */
1436 @Override
1437 public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001438 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001439// String tag = "EventHandler.AddFlowEntryToSwitch." + flowEntry.flowEntryId();
1440 String tag = "EventHandler.AddFlowEntryToSwitch";
1441 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001442 Collection entries = new ArrayList();
1443 entries.add(flowEntry);
1444 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001445// PerformanceMonitor.stop(tag);
1446 m.stop();
1447// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001448 return;
1449 }
1450
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001451 EventEntry<FlowEntry> eventEntry =
1452 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1453 networkEvents.add(eventEntry);
1454 }
1455
1456 /**
1457 * Receive a notification that a FlowEntry is removed.
1458 *
1459 * @param flowEntry the FlowEntry that is removed.
1460 */
1461 @Override
1462 public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001463 if (enableOnrc2014MeasurementsFlows) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001464// String tag = "EventHandler.RemoveFlowEntryFromSwitch." + flowEntry.flowEntryId();
1465 String tag = "EventHandler.RemoveFlowEntryFromSwitch";
1466 PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
Pavlin Radoslavove4d2a432014-01-10 12:01:08 -08001467 //
1468 // NOTE: Must update the state to DELETE, because
1469 // the notification contains the original state.
1470 //
1471 flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
1472
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001473 Collection entries = new ArrayList();
1474 entries.add(flowEntry);
1475 flowManager.pushModifiedFlowEntriesToSwitches(entries);
Brian O'Connor2daf7a92014-01-14 11:26:35 -08001476// PerformanceMonitor.stop(tag);
1477 m.stop();
1478// PerformanceMonitor.report(tag);
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001479 return;
1480 }
1481
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001482 EventEntry<FlowEntry> eventEntry =
1483 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
1484 networkEvents.add(eventEntry);
1485 }
1486
1487 /**
1488 * Receive a notification that a FlowEntry is updated.
1489 *
1490 * @param flowEntry the FlowEntry that is updated.
1491 */
1492 @Override
1493 public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -08001494 if (enableOnrc2014MeasurementsFlows) {
1495 Collection entries = new ArrayList();
1496 entries.add(flowEntry);
1497 flowManager.pushModifiedFlowEntriesToSwitches(entries);
1498 return;
1499 }
1500
Pavlin Radoslavovb7506842013-10-29 17:46:54 -07001501 // NOTE: The ADD and UPDATE events are processed in same way
1502 EventEntry<FlowEntry> eventEntry =
1503 new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
1504 networkEvents.add(eventEntry);
1505 }
1506
1507 /**
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001508 * Receive a notification that a FlowId is added.
1509 *
1510 * @param flowId the FlowId that is added.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001511 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001512 */
1513 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001514 public void notificationRecvFlowIdAdded(FlowId flowId, Dpid dpid) {
1515 Pair flowIdPair = new Pair(flowId, dpid);
1516
1517 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1518 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001519 networkEvents.add(eventEntry);
1520 }
1521
1522 /**
1523 * Receive a notification that a FlowId is removed.
1524 *
1525 * @param flowId the FlowId that is removed.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001526 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001527 */
1528 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001529 public void notificationRecvFlowIdRemoved(FlowId flowId, Dpid dpid) {
1530 Pair flowIdPair = new Pair(flowId, dpid);
1531
1532 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1533 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001534 networkEvents.add(eventEntry);
1535 }
1536
1537 /**
1538 * Receive a notification that a FlowId is updated.
1539 *
1540 * @param flowId the FlowId that is updated.
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001541 * @param dpid the Source Switch Dpid for the corresponding Flow.
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001542 */
1543 @Override
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001544 public void notificationRecvFlowIdUpdated(FlowId flowId, Dpid dpid) {
1545 Pair flowIdPair = new Pair(flowId, dpid);
1546
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001547 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavov2194d112014-01-10 13:36:00 -08001548 EventEntry<Pair<FlowId, Dpid>> eventEntry =
1549 new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
Pavlin Radoslavov2004fa02014-01-07 14:46:42 -08001550 networkEvents.add(eventEntry);
1551 }
1552
1553 /**
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001554 * Receive a notification that a FlowEntryId is added.
1555 *
1556 * @param flowEntryId the FlowEntryId that is added.
1557 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1558 */
1559 @Override
1560 public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
1561 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001562 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1563
1564 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1565 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001566 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001567 }
1568
1569 /**
1570 * Receive a notification that a FlowEntryId is removed.
1571 *
1572 * @param flowEntryId the FlowEntryId that is removed.
1573 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1574 */
1575 @Override
1576 public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
1577 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001578 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1579
1580 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1581 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001582 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001583 }
1584
1585 /**
1586 * Receive a notification that a FlowEntryId is updated.
1587 *
1588 * @param flowEntryId the FlowEntryId that is updated.
1589 * @param dpid the Switch Dpid for the corresponding Flow Entry.
1590 */
1591 @Override
1592 public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
1593 Dpid dpid) {
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001594 Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
1595
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001596 // NOTE: The ADD and UPDATE events are processed in same way
Pavlin Radoslavova9c0c3b2014-01-09 10:54:45 -08001597 EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
1598 new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001599 networkEvents.add(eventEntry);
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -08001600 }
1601
1602 /**
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001603 * Receive a notification that a Topology Element is added.
1604 *
1605 * @param topologyElement the Topology Element that is added.
1606 */
1607 @Override
1608 public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
1609 EventEntry<TopologyElement> eventEntry =
1610 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1611 networkEvents.add(eventEntry);
1612 }
1613
1614 /**
1615 * Receive a notification that a Topology Element is removed.
1616 *
1617 * @param topologyElement the Topology Element that is removed.
1618 */
1619 @Override
1620 public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
1621 EventEntry<TopologyElement> eventEntry =
1622 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
1623 networkEvents.add(eventEntry);
1624 }
1625
1626 /**
1627 * Receive a notification that a Topology Element is updated.
1628 *
1629 * @param topologyElement the Topology Element that is updated.
1630 */
1631 @Override
1632 public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
1633 // NOTE: The ADD and UPDATE events are processed in same way
1634 EventEntry<TopologyElement> eventEntry =
1635 new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
1636 networkEvents.add(eventEntry);
1637 }
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001638
1639 /**
Pavlin Radoslavovcc757162014-01-10 16:26:38 -08001640 * Receive a notification that a switch is added to this instance.
1641 *
1642 * @param sw the switch that is added.
1643 */
1644 @Override
1645 public void addedSwitch(IOFSwitch sw) {
1646 Dpid dpid = new Dpid(sw.getId());
1647 EventEntry<Dpid> eventEntry =
1648 new EventEntry<Dpid>(EventEntry.Type.ENTRY_ADD, dpid);
1649 networkEvents.add(eventEntry);
1650 }
1651
1652 /**
1653 * Receive a notification that a switch is removed from this instance.
1654 *
1655 * @param sw the switch that is removed.
1656 */
1657 @Override
1658 public void removedSwitch(IOFSwitch sw) {
1659 Dpid dpid = new Dpid(sw.getId());
1660 EventEntry<Dpid> eventEntry =
1661 new EventEntry<Dpid>(EventEntry.Type.ENTRY_REMOVE, dpid);
1662 networkEvents.add(eventEntry);
1663 }
1664
1665 /**
1666 * Receive a notification that the ports on a switch have changed.
1667 */
1668 @Override
1669 public void switchPortChanged(Long switchId) {
1670 // Nothing to do
1671 }
1672
1673 /**
Pavlin Radoslavov53219802013-12-06 11:02:04 -08001674 * Get a sorted copy of all Flow Paths.
1675 *
1676 * @return a sorted copy of all Flow Paths.
1677 */
1678 synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
1679 SortedMap<Long, FlowPath> sortedFlowPaths =
1680 new TreeMap<Long, FlowPath>();
1681
1682 //
1683 // TODO: For now we use serialization/deserialization to create
1684 // a copy of each Flow Path. In the future, we should use proper
1685 // copy constructors.
1686 //
1687 Kryo kryo = kryoFactory.newKryo();
1688 synchronized (allFlowPaths) {
1689 for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
1690 FlowPath origFlowPath = entry.getValue();
1691 FlowPath copyFlowPath = kryo.copy(origFlowPath);
1692 sortedFlowPaths.put(entry.getKey(), copyFlowPath);
1693 }
1694 }
1695 kryoFactory.deleteKryo(kryo);
1696
1697 return sortedFlowPaths;
1698 }
Pavlin Radoslavov6b79f2b2013-10-26 21:31:10 -07001699}