blob: 178bd00445a948123a78ad54c56a69116348d3e8 [file] [log] [blame]
Jonathan Hart472062d2014-04-03 10:56:48 -07001package net.onrc.onos.core.topology;
Jonathan Hart062a2e82014-02-03 09:41:57 -08002
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08003import java.nio.ByteBuffer;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08004import java.util.ArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08005import java.util.Collection;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08006import java.util.HashMap;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08007import java.util.HashSet;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08008import java.util.LinkedList;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08009import java.util.List;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080010import java.util.Map;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080011import java.util.Set;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080012import java.util.concurrent.BlockingQueue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080013import java.util.concurrent.CopyOnWriteArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080014import java.util.concurrent.LinkedBlockingQueue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080015
TeruU28adcc32014-04-15 17:57:35 -070016import net.floodlightcontroller.util.MACAddress;
Jonathan Hart6df90172014-04-03 10:13:11 -070017import net.onrc.onos.core.datagrid.IDatagridService;
18import net.onrc.onos.core.datagrid.IEventChannel;
19import net.onrc.onos.core.datagrid.IEventChannelListener;
TeruU28adcc32014-04-15 17:57:35 -070020import net.onrc.onos.core.datastore.topology.KVDevice;
Jonathan Hart6df90172014-04-03 10:13:11 -070021import net.onrc.onos.core.datastore.topology.KVLink;
22import net.onrc.onos.core.datastore.topology.KVPort;
23import net.onrc.onos.core.datastore.topology.KVSwitch;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070024import net.onrc.onos.core.registry.IControllerRegistryService;
Jonathan Hart472062d2014-04-03 10:56:48 -070025import net.onrc.onos.core.topology.PortEvent.SwitchPort;
Jonathan Hart23701d12014-04-03 10:45:48 -070026import net.onrc.onos.core.util.EventEntry;
Jonathan Hart062a2e82014-02-03 09:41:57 -080027
28import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
30
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080031/**
Jonathan Harte37e4e22014-05-13 19:12:02 -070032 * The TopologyManager receives topology updates from the southbound discovery
33 * modules and from other ONOS instances. These updates are processed and
34 * applied to the in-memory topology instance.
Ray Milkey269ffb92014-04-03 14:43:30 -070035 * <p/>
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080036 * - Maintain Invariant/Relationships between Topology Objects.
Ray Milkey269ffb92014-04-03 14:43:30 -070037 * <p/>
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080038 * TODO To be synchronized based on TopologyEvent Notification.
Ray Milkey269ffb92014-04-03 14:43:30 -070039 * <p/>
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080040 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
Yuta HIGUCHI1c700102014-02-12 16:30:52 -080041 * Object must exist before adding sub component(Add Switch -> Port).
Ray Milkey269ffb92014-04-03 14:43:30 -070042 * <p/>
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080043 * TODO TBD: This class may delay the requested change to handle event
44 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080045 */
Jonathan Harte37e4e22014-05-13 19:12:02 -070046public class TopologyManager implements TopologyDiscoveryInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080047
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080048 private static final Logger log = LoggerFactory
Ray Milkey269ffb92014-04-03 14:43:30 -070049 .getLogger(TopologyManager.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080050
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080051 private IEventChannel<byte[], TopologyEvent> eventChannel;
Jonathan Hart10a7e2b2014-02-21 18:30:08 -080052 public static final String EVENT_CHANNEL_NAME = "onos.topology";
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080053 private EventHandler eventHandler = new EventHandler();
54
Jonathan Harte37e4e22014-05-13 19:12:02 -070055 private final TopologyDatastore datastore;
56 private final TopologyImpl topology = new TopologyImpl();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080057 private final IControllerRegistryService registryService;
Jonathan Harte37e4e22014-05-13 19:12:02 -070058 private CopyOnWriteArrayList<ITopologyListener> topologyListeners;
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080059
Pavlin Radoslavov706add22014-02-20 12:15:59 -080060 //
61 // Local state for keeping track of reordered events.
62 // NOTE: Switch Events are not affected by the event reordering.
63 //
64 private Map<ByteBuffer, PortEvent> reorderedAddedPortEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -070065 new HashMap<ByteBuffer, PortEvent>();
Pavlin Radoslavov706add22014-02-20 12:15:59 -080066 private Map<ByteBuffer, LinkEvent> reorderedAddedLinkEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -070067 new HashMap<ByteBuffer, LinkEvent>();
Pavlin Radoslavov706add22014-02-20 12:15:59 -080068 private Map<ByteBuffer, DeviceEvent> reorderedAddedDeviceEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -070069 new HashMap<ByteBuffer, DeviceEvent>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080070
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -080071 //
Pavlin Radoslavov26d83402014-02-20 15:24:30 -080072 // Local state for keeping track of locally discovered events so we can
73 // cleanup properly when a Switch or Port is removed.
74 //
75 // We keep all Port, Link and Device events per Switch DPID:
76 // - If a switch goes down, we remove all corresponding Port, Link and
77 // Device events.
78 // - If a port on a switch goes down, we remove all corresponding Link
79 // and Device events.
80 //
81 private Map<Long, Map<ByteBuffer, PortEvent>> discoveredAddedPortEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -070082 new HashMap<>();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -080083 private Map<Long, Map<ByteBuffer, LinkEvent>> discoveredAddedLinkEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -070084 new HashMap<>();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -080085 private Map<Long, Map<ByteBuffer, DeviceEvent>> discoveredAddedDeviceEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -070086 new HashMap<>();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -080087
88 //
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -080089 // Local state for keeping track of the application event notifications
90 //
91 List<SwitchEvent> apiAddedSwitchEvents = new LinkedList<SwitchEvent>();
92 List<SwitchEvent> apiRemovedSwitchEvents = new LinkedList<SwitchEvent>();
93 List<PortEvent> apiAddedPortEvents = new LinkedList<PortEvent>();
94 List<PortEvent> apiRemovedPortEvents = new LinkedList<PortEvent>();
95 List<LinkEvent> apiAddedLinkEvents = new LinkedList<LinkEvent>();
96 List<LinkEvent> apiRemovedLinkEvents = new LinkedList<LinkEvent>();
97 List<DeviceEvent> apiAddedDeviceEvents = new LinkedList<DeviceEvent>();
98 List<DeviceEvent> apiRemovedDeviceEvents = new LinkedList<DeviceEvent>();
99
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800100 /**
101 * Constructor.
102 *
Jonathan Harte37e4e22014-05-13 19:12:02 -0700103 * @param registryService the Registry Service to use.
104 * @param topologyListeners the collection of topology listeners to use.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800105 */
106 public TopologyManager(IControllerRegistryService registryService,
Jonathan Harte37e4e22014-05-13 19:12:02 -0700107 CopyOnWriteArrayList<ITopologyListener> topologyListeners) {
108 datastore = new TopologyDatastore();
Ray Milkey269ffb92014-04-03 14:43:30 -0700109 this.registryService = registryService;
Jonathan Harte37e4e22014-05-13 19:12:02 -0700110 this.topologyListeners = topologyListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800111 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800112
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800113 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700114 * Get the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800115 *
Jonathan Harte37e4e22014-05-13 19:12:02 -0700116 * @return the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800117 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700118 Topology getTopology() {
119 return topology;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -0800120 }
121
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800122 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800123 * Event handler class.
124 */
125 private class EventHandler extends Thread implements
Ray Milkey269ffb92014-04-03 14:43:30 -0700126 IEventChannelListener<byte[], TopologyEvent> {
127 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
128 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800129
Ray Milkey269ffb92014-04-03 14:43:30 -0700130 /**
131 * Startup processing.
132 */
133 private void startup() {
134 //
135 // TODO: Read all state from the database:
136 //
137 // Collection<EventEntry<TopologyEvent>> collection =
138 // readWholeTopologyFromDB();
139 //
140 // For now, as a shortcut we read it from the datagrid
141 //
Ray Milkey5df613b2014-04-15 10:50:56 -0700142 Collection<TopologyEvent> allTopologyEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700143 eventChannel.getAllEntries();
144 Collection<EventEntry<TopologyEvent>> collection =
145 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800146
Ray Milkey5df613b2014-04-15 10:50:56 -0700147 for (TopologyEvent topologyEvent : allTopologyEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700148 EventEntry<TopologyEvent> eventEntry =
149 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
150 topologyEvent);
151 collection.add(eventEntry);
152 }
153 processEvents(collection);
154 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800155
Ray Milkey269ffb92014-04-03 14:43:30 -0700156 /**
157 * Run the thread.
158 */
159 @Override
160 public void run() {
161 Collection<EventEntry<TopologyEvent>> collection =
162 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800163
Ray Milkey269ffb92014-04-03 14:43:30 -0700164 this.setName("TopologyManager.EventHandler " + this.getId());
165 startup();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800166
Ray Milkey269ffb92014-04-03 14:43:30 -0700167 //
168 // The main loop
169 //
170 try {
171 while (true) {
172 EventEntry<TopologyEvent> eventEntry = topologyEvents.take();
173 collection.add(eventEntry);
174 topologyEvents.drainTo(collection);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800175
Ray Milkey269ffb92014-04-03 14:43:30 -0700176 processEvents(collection);
177 collection.clear();
178 }
179 } catch (Exception exception) {
180 log.debug("Exception processing Topology Events: ", exception);
181 }
182 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800183
Ray Milkey269ffb92014-04-03 14:43:30 -0700184 /**
185 * Process all topology events.
186 *
187 * @param events the events to process.
188 */
189 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
190 // Local state for computing the final set of events
191 Map<ByteBuffer, SwitchEvent> addedSwitchEvents = new HashMap<>();
192 Map<ByteBuffer, SwitchEvent> removedSwitchEvents = new HashMap<>();
193 Map<ByteBuffer, PortEvent> addedPortEvents = new HashMap<>();
194 Map<ByteBuffer, PortEvent> removedPortEvents = new HashMap<>();
195 Map<ByteBuffer, LinkEvent> addedLinkEvents = new HashMap<>();
196 Map<ByteBuffer, LinkEvent> removedLinkEvents = new HashMap<>();
197 Map<ByteBuffer, DeviceEvent> addedDeviceEvents = new HashMap<>();
198 Map<ByteBuffer, DeviceEvent> removedDeviceEvents = new HashMap<>();
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800199
Ray Milkey269ffb92014-04-03 14:43:30 -0700200 //
201 // Classify and suppress matching events
202 //
203 for (EventEntry<TopologyEvent> event : events) {
204 TopologyEvent topologyEvent = event.eventData();
205 SwitchEvent switchEvent = topologyEvent.switchEvent;
206 PortEvent portEvent = topologyEvent.portEvent;
207 LinkEvent linkEvent = topologyEvent.linkEvent;
208 DeviceEvent deviceEvent = topologyEvent.deviceEvent;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800209
Ray Milkey269ffb92014-04-03 14:43:30 -0700210 //
211 // Extract the events
212 //
213 switch (event.eventType()) {
214 case ENTRY_ADD:
215 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
216 if (switchEvent != null) {
217 ByteBuffer id = switchEvent.getIDasByteBuffer();
218 addedSwitchEvents.put(id, switchEvent);
219 removedSwitchEvents.remove(id);
220 // Switch Events are not affected by event reordering
221 }
222 if (portEvent != null) {
223 ByteBuffer id = portEvent.getIDasByteBuffer();
224 addedPortEvents.put(id, portEvent);
225 removedPortEvents.remove(id);
226 reorderedAddedPortEvents.remove(id);
227 }
228 if (linkEvent != null) {
229 ByteBuffer id = linkEvent.getIDasByteBuffer();
230 addedLinkEvents.put(id, linkEvent);
231 removedLinkEvents.remove(id);
232 reorderedAddedLinkEvents.remove(id);
233 }
234 if (deviceEvent != null) {
235 ByteBuffer id = deviceEvent.getIDasByteBuffer();
236 addedDeviceEvents.put(id, deviceEvent);
237 removedDeviceEvents.remove(id);
238 reorderedAddedDeviceEvents.remove(id);
239 }
240 break;
241 case ENTRY_REMOVE:
242 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
243 if (switchEvent != null) {
244 ByteBuffer id = switchEvent.getIDasByteBuffer();
245 addedSwitchEvents.remove(id);
246 removedSwitchEvents.put(id, switchEvent);
247 // Switch Events are not affected by event reordering
248 }
249 if (portEvent != null) {
250 ByteBuffer id = portEvent.getIDasByteBuffer();
251 addedPortEvents.remove(id);
252 removedPortEvents.put(id, portEvent);
253 reorderedAddedPortEvents.remove(id);
254 }
255 if (linkEvent != null) {
256 ByteBuffer id = linkEvent.getIDasByteBuffer();
257 addedLinkEvents.remove(id);
258 removedLinkEvents.put(id, linkEvent);
259 reorderedAddedLinkEvents.remove(id);
260 }
261 if (deviceEvent != null) {
262 ByteBuffer id = deviceEvent.getIDasByteBuffer();
263 addedDeviceEvents.remove(id);
264 removedDeviceEvents.put(id, deviceEvent);
265 reorderedAddedDeviceEvents.remove(id);
266 }
267 break;
Ray Milkey0b122ed2014-04-14 10:06:03 -0700268 default:
269 log.error("Unknown topology event {}",
270 event.eventType());
Ray Milkey269ffb92014-04-03 14:43:30 -0700271 }
272 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800273
Ray Milkey269ffb92014-04-03 14:43:30 -0700274 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700275 // Lock the topology while it is modified
Ray Milkey269ffb92014-04-03 14:43:30 -0700276 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700277 topology.acquireWriteLock();
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800278
Ray Milkey269ffb92014-04-03 14:43:30 -0700279 try {
280 //
281 // Apply the classified events.
282 //
283 // Apply the "add" events in the proper order:
284 // switch, port, link, device
285 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700286 for (SwitchEvent switchEvent : addedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700287 addSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700288 }
289 for (PortEvent portEvent : addedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700290 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700291 }
292 for (LinkEvent linkEvent : addedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700293 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700294 }
295 for (DeviceEvent deviceEvent : addedDeviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700296 addDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700297 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700298 //
299 // Apply the "remove" events in the reverse order:
300 // device, link, port, switch
301 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700302 for (DeviceEvent deviceEvent : removedDeviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700303 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700304 }
305 for (LinkEvent linkEvent : removedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700306 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700307 }
308 for (PortEvent portEvent : removedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700309 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700310 }
311 for (SwitchEvent switchEvent : removedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700312 removeSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700313 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800314
Ray Milkey269ffb92014-04-03 14:43:30 -0700315 //
316 // Apply reordered events
317 //
318 applyReorderedEvents(!addedSwitchEvents.isEmpty(),
319 !addedPortEvents.isEmpty());
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800320
Ray Milkey269ffb92014-04-03 14:43:30 -0700321 } finally {
322 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700323 // Topology modifications completed: Release the lock
Ray Milkey269ffb92014-04-03 14:43:30 -0700324 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700325 topology.releaseWriteLock();
Ray Milkey269ffb92014-04-03 14:43:30 -0700326 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800327
Ray Milkey269ffb92014-04-03 14:43:30 -0700328 //
329 // Dispatch the Topology Notification Events to the applications
330 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700331 dispatchTopologyEvents();
Ray Milkey269ffb92014-04-03 14:43:30 -0700332 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800333
Ray Milkey269ffb92014-04-03 14:43:30 -0700334 /**
335 * Receive a notification that an entry is added.
336 *
337 * @param value the value for the entry.
338 */
339 @Override
340 public void entryAdded(TopologyEvent value) {
341 EventEntry<TopologyEvent> eventEntry =
342 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
343 value);
344 topologyEvents.add(eventEntry);
345 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800346
Ray Milkey269ffb92014-04-03 14:43:30 -0700347 /**
348 * Receive a notification that an entry is removed.
349 *
350 * @param value the value for the entry.
351 */
352 @Override
353 public void entryRemoved(TopologyEvent value) {
354 EventEntry<TopologyEvent> eventEntry =
355 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
356 value);
357 topologyEvents.add(eventEntry);
358 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800359
Ray Milkey269ffb92014-04-03 14:43:30 -0700360 /**
361 * Receive a notification that an entry is updated.
362 *
363 * @param value the value for the entry.
364 */
365 @Override
366 public void entryUpdated(TopologyEvent value) {
367 // NOTE: The ADD and UPDATE events are processed in same way
368 entryAdded(value);
369 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800370 }
371
372 /**
373 * Startup processing.
374 *
375 * @param datagridService the datagrid service to use.
376 */
377 void startup(IDatagridService datagridService) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700378 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
379 eventHandler,
380 byte[].class,
381 TopologyEvent.class);
382 eventHandler.start();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800383 }
384
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800385 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700386 * Dispatch Topology Events to the listeners.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800387 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700388 private void dispatchTopologyEvents() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700389 if (apiAddedSwitchEvents.isEmpty() &&
390 apiRemovedSwitchEvents.isEmpty() &&
391 apiAddedPortEvents.isEmpty() &&
392 apiRemovedPortEvents.isEmpty() &&
393 apiAddedLinkEvents.isEmpty() &&
394 apiRemovedLinkEvents.isEmpty() &&
395 apiAddedDeviceEvents.isEmpty() &&
396 apiRemovedDeviceEvents.isEmpty()) {
397 return; // No events to dispatch
398 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800399
Ray Milkey269ffb92014-04-03 14:43:30 -0700400 if (log.isDebugEnabled()) {
401 //
402 // Debug statements
403 // TODO: Those statements should be removed in the future
404 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700405 for (SwitchEvent switchEvent : apiAddedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700406 log.debug("Dispatch Topology Event: ADDED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700407 }
408 for (SwitchEvent switchEvent : apiRemovedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700409 log.debug("Dispatch Topology Event: REMOVED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700410 }
411 for (PortEvent portEvent : apiAddedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700412 log.debug("Dispatch Topology Event: ADDED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700413 }
414 for (PortEvent portEvent : apiRemovedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700415 log.debug("Dispatch Topology Event: REMOVED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700416 }
417 for (LinkEvent linkEvent : apiAddedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700418 log.debug("Dispatch Topology Event: ADDED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700419 }
420 for (LinkEvent linkEvent : apiRemovedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700421 log.debug("Dispatch Topology Event: REMOVED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700422 }
423 for (DeviceEvent deviceEvent : apiAddedDeviceEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700424 log.debug("Dispatch Topology Event: ADDED {}", deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700425 }
426 for (DeviceEvent deviceEvent : apiRemovedDeviceEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700427 log.debug("Dispatch Topology Event: REMOVED {}", deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700428 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700429 }
adminbc181552014-02-21 18:36:42 -0800430
Ray Milkey269ffb92014-04-03 14:43:30 -0700431 // Deliver the events
Jonathan Harte37e4e22014-05-13 19:12:02 -0700432 for (ITopologyListener listener : this.topologyListeners) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700433 // TODO: Should copy before handing them over to listener?
Jonathan Harte37e4e22014-05-13 19:12:02 -0700434 listener.topologyEvents(apiAddedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700435 apiRemovedSwitchEvents,
436 apiAddedPortEvents,
437 apiRemovedPortEvents,
438 apiAddedLinkEvents,
439 apiRemovedLinkEvents,
440 apiAddedDeviceEvents,
441 apiRemovedDeviceEvents);
442 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800443
Ray Milkey269ffb92014-04-03 14:43:30 -0700444 //
445 // Cleanup
446 //
447 apiAddedSwitchEvents.clear();
448 apiRemovedSwitchEvents.clear();
449 apiAddedPortEvents.clear();
450 apiRemovedPortEvents.clear();
451 apiAddedLinkEvents.clear();
452 apiRemovedLinkEvents.clear();
453 apiAddedDeviceEvents.clear();
454 apiRemovedDeviceEvents.clear();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800455 }
456
457 /**
458 * Apply reordered events.
459 *
460 * @param hasAddedSwitchEvents true if there were Added Switch Events.
Ray Milkey269ffb92014-04-03 14:43:30 -0700461 * @param hasAddedPortEvents true if there were Added Port Events.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800462 */
463 private void applyReorderedEvents(boolean hasAddedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700464 boolean hasAddedPortEvents) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700465 if (!(hasAddedSwitchEvents || hasAddedPortEvents)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700466 return; // Nothing to do
Ray Milkeyb29e6262014-04-09 16:02:14 -0700467 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800468
Ray Milkey269ffb92014-04-03 14:43:30 -0700469 //
470 // Try to apply the reordered events.
471 //
472 // NOTE: For simplicity we try to apply all events of a particular
473 // type if any "parent" type event was processed:
474 // - Apply reordered Port Events if Switches were added
475 // - Apply reordered Link and Device Events if Switches or Ports
476 // were added
477 //
adminbc181552014-02-21 18:36:42 -0800478
Ray Milkey269ffb92014-04-03 14:43:30 -0700479 //
480 // Apply reordered Port Events if Switches were added
481 //
482 if (hasAddedSwitchEvents) {
483 Map<ByteBuffer, PortEvent> portEvents = reorderedAddedPortEvents;
484 reorderedAddedPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700485 for (PortEvent portEvent : portEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700486 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700487 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700488 }
489 //
490 // Apply reordered Link and Device Events if Switches or Ports
491 // were added.
492 //
493 Map<ByteBuffer, LinkEvent> linkEvents = reorderedAddedLinkEvents;
494 reorderedAddedLinkEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700495 for (LinkEvent linkEvent : linkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700496 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700497 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700498 //
499 Map<ByteBuffer, DeviceEvent> deviceEvents = reorderedAddedDeviceEvents;
500 reorderedAddedDeviceEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700501 for (DeviceEvent deviceEvent : deviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700502 addDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700503 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800504 }
505
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800506 /**
507 * Switch discovered event.
508 *
509 * @param switchEvent the switch event.
Ray Milkey269ffb92014-04-03 14:43:30 -0700510 * @param portEvents the corresponding port events for the switch.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800511 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800512 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800513 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
Ray Milkey269ffb92014-04-03 14:43:30 -0700514 Collection<PortEvent> portEvents) {
515 if (datastore.addSwitch(switchEvent, portEvents)) {
516 // Send out notification
517 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
518 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800519
Ray Milkey269ffb92014-04-03 14:43:30 -0700520 // Send out notification for each port
521 for (PortEvent portEvent : portEvents) {
522 topologyEvent = new TopologyEvent(portEvent);
523 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
524 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800525
Ray Milkey269ffb92014-04-03 14:43:30 -0700526 //
527 // Keep track of the added ports
528 //
529 // Get the old Port Events
530 Map<ByteBuffer, PortEvent> oldPortEvents =
531 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700532 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700533 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700534 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800535
Ray Milkey269ffb92014-04-03 14:43:30 -0700536 // Store the new Port Events in the local cache
537 Map<ByteBuffer, PortEvent> newPortEvents = new HashMap<>();
538 for (PortEvent portEvent : portEvents) {
539 ByteBuffer id = portEvent.getIDasByteBuffer();
540 newPortEvents.put(id, portEvent);
541 }
542 discoveredAddedPortEvents.put(switchEvent.getDpid(),
543 newPortEvents);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800544
Ray Milkey269ffb92014-04-03 14:43:30 -0700545 //
546 // Extract the removed ports
547 //
548 List<PortEvent> removedPortEvents = new LinkedList<>();
549 for (Map.Entry<ByteBuffer, PortEvent> entry : oldPortEvents.entrySet()) {
550 ByteBuffer key = entry.getKey();
551 PortEvent portEvent = entry.getValue();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700552 if (!newPortEvents.containsKey(key)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700553 removedPortEvents.add(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700554 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700555 }
556
557 // Cleanup old removed ports
Ray Milkeyb29e6262014-04-09 16:02:14 -0700558 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700559 removePortDiscoveryEvent(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700560 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700561 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800562 }
563
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800564 /**
565 * Switch removed event.
566 *
567 * @param switchEvent the switch event.
568 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800569 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800570 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700571 // Get the old Port Events
572 Map<ByteBuffer, PortEvent> oldPortEvents =
573 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700574 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700575 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700576 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800577
Ray Milkey269ffb92014-04-03 14:43:30 -0700578 if (datastore.deactivateSwitch(switchEvent, oldPortEvents.values())) {
579 // Send out notification
580 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800581
Ray Milkey269ffb92014-04-03 14:43:30 -0700582 //
583 // Send out notification for each port.
584 //
585 // NOTE: We don't use removePortDiscoveryEvent() for the cleanup,
586 // because it will attempt to remove the port from the database,
587 // and the deactiveSwitch() call above already removed all ports.
588 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700589 for (PortEvent portEvent : oldPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700590 eventChannel.removeEntry(portEvent.getID());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700591 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700592 discoveredAddedPortEvents.remove(switchEvent.getDpid());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800593
Ray Milkey269ffb92014-04-03 14:43:30 -0700594 // Cleanup for each link
595 Map<ByteBuffer, LinkEvent> oldLinkEvents =
596 discoveredAddedLinkEvents.get(switchEvent.getDpid());
597 if (oldLinkEvents != null) {
598 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
599 removeLinkDiscoveryEvent(linkEvent);
600 }
601 discoveredAddedLinkEvents.remove(switchEvent.getDpid());
602 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800603
Ray Milkey269ffb92014-04-03 14:43:30 -0700604 // Cleanup for each device
605 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
606 discoveredAddedDeviceEvents.get(switchEvent.getDpid());
607 if (oldDeviceEvents != null) {
608 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
609 removeDeviceDiscoveryEvent(deviceEvent);
610 }
611 discoveredAddedDeviceEvents.remove(switchEvent.getDpid());
612 }
613 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800614 }
615
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800616 /**
617 * Port discovered event.
618 *
619 * @param portEvent the port event.
620 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800621 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800622 public void putPortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700623 if (datastore.addPort(portEvent)) {
624 // Send out notification
625 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
626 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800627
Ray Milkey269ffb92014-04-03 14:43:30 -0700628 // Store the new Port Event in the local cache
629 Map<ByteBuffer, PortEvent> oldPortEvents =
630 discoveredAddedPortEvents.get(portEvent.getDpid());
631 if (oldPortEvents == null) {
632 oldPortEvents = new HashMap<>();
633 discoveredAddedPortEvents.put(portEvent.getDpid(),
634 oldPortEvents);
635 }
636 ByteBuffer id = portEvent.getIDasByteBuffer();
637 oldPortEvents.put(id, portEvent);
638 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800639 }
640
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800641 /**
642 * Port removed event.
643 *
644 * @param portEvent the port event.
645 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800646 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800647 public void removePortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700648 if (datastore.deactivatePort(portEvent)) {
649 // Send out notification
650 eventChannel.removeEntry(portEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800651
Ray Milkey269ffb92014-04-03 14:43:30 -0700652 // Cleanup the Port Event from the local cache
653 Map<ByteBuffer, PortEvent> oldPortEvents =
654 discoveredAddedPortEvents.get(portEvent.getDpid());
655 if (oldPortEvents != null) {
656 ByteBuffer id = portEvent.getIDasByteBuffer();
657 oldPortEvents.remove(id);
658 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800659
Ray Milkey269ffb92014-04-03 14:43:30 -0700660 // Cleanup for the incoming link
661 Map<ByteBuffer, LinkEvent> oldLinkEvents =
662 discoveredAddedLinkEvents.get(portEvent.getDpid());
663 if (oldLinkEvents != null) {
664 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
665 if (linkEvent.getDst().equals(portEvent.id)) {
666 removeLinkDiscoveryEvent(linkEvent);
667 // XXX If we change our model to allow multiple Link on
668 // a Port, this loop must be fixed to allow continuing.
669 break;
670 }
671 }
672 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800673
Ray Milkey269ffb92014-04-03 14:43:30 -0700674 // Cleanup for the connected devices
675 // TODO: The implementation below is probably wrong
676 List<DeviceEvent> removedDeviceEvents = new LinkedList<>();
677 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
678 discoveredAddedDeviceEvents.get(portEvent.getDpid());
679 if (oldDeviceEvents != null) {
680 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
681 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
682 if (swp.equals(portEvent.id)) {
683 removedDeviceEvents.add(deviceEvent);
684 }
685 }
686 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700687 for (DeviceEvent deviceEvent : removedDeviceEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700688 removeDeviceDiscoveryEvent(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700689 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700690 }
691 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800692 }
693
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800694 /**
695 * Link discovered event.
696 *
697 * @param linkEvent the link event.
698 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800699 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800700 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700701 if (datastore.addLink(linkEvent)) {
702 // Send out notification
703 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
704 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800705
Ray Milkey269ffb92014-04-03 14:43:30 -0700706 // Store the new Link Event in the local cache
707 Map<ByteBuffer, LinkEvent> oldLinkEvents =
708 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
709 if (oldLinkEvents == null) {
710 oldLinkEvents = new HashMap<>();
711 discoveredAddedLinkEvents.put(linkEvent.getDst().getDpid(),
712 oldLinkEvents);
713 }
714 ByteBuffer id = linkEvent.getIDasByteBuffer();
715 oldLinkEvents.put(id, linkEvent);
716 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800717 }
718
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800719 /**
720 * Link removed event.
721 *
722 * @param linkEvent the link event.
723 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800724 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800725 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700726 if (datastore.removeLink(linkEvent)) {
727 // Send out notification
728 eventChannel.removeEntry(linkEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800729
Ray Milkey269ffb92014-04-03 14:43:30 -0700730 // Cleanup the Link Event from the local cache
731 Map<ByteBuffer, LinkEvent> oldLinkEvents =
732 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
733 if (oldLinkEvents != null) {
734 ByteBuffer id = linkEvent.getIDasByteBuffer();
735 oldLinkEvents.remove(id);
736 }
737 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800738 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800739
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800740 /**
741 * Device discovered event.
742 *
743 * @param deviceEvent the device event.
744 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800745 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800746 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700747 if (datastore.addDevice(deviceEvent)) {
748 // Send out notification
749 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
750 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700751 log.debug("Put the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -0700752
753 // Store the new Device Event in the local cache
754 // TODO: The implementation below is probably wrong
755 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
756 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
757 discoveredAddedDeviceEvents.get(swp.getDpid());
758 if (oldDeviceEvents == null) {
759 oldDeviceEvents = new HashMap<>();
760 discoveredAddedDeviceEvents.put(swp.getDpid(),
761 oldDeviceEvents);
762 }
763 ByteBuffer id = deviceEvent.getIDasByteBuffer();
764 oldDeviceEvents.put(id, deviceEvent);
765 }
766 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800767 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800768
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800769 /**
770 * Device removed event.
771 *
772 * @param deviceEvent the device event.
773 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800774 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800775 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700776 if (datastore.removeDevice(deviceEvent)) {
777 // Send out notification
778 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Harte37e4e22014-05-13 19:12:02 -0700779 log.debug("Remove the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800780
Ray Milkey269ffb92014-04-03 14:43:30 -0700781 // Cleanup the Device Event from the local cache
782 // TODO: The implementation below is probably wrong
783 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
784 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
785 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
786 discoveredAddedDeviceEvents.get(swp.getDpid());
787 if (oldDeviceEvents != null) {
788 oldDeviceEvents.remove(id);
789 }
790 }
791 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800792 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800793
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800794 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700795 * Add a switch to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800796 *
797 * @param switchEvent the Switch Event with the switch to add.
798 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800799 private void addSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700800 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700801 if (sw == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700802 sw = new SwitchImpl(topology, switchEvent.getDpid());
803 topology.putSwitch(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700804 } else {
805 // TODO: Update the switch attributes
806 // TODO: Nothing to do for now
Ray Milkey1aa71f82014-04-08 16:23:24 -0700807 log.debug("Update switch attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700808 }
809 apiAddedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800810 }
811
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800812 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700813 * Remove a switch from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800814 *
815 * @param switchEvent the Switch Event with the switch to remove.
816 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800817 private void removeSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700818 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700819 if (sw == null) {
820 log.warn("Switch {} already removed, ignoring", switchEvent);
821 return;
822 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800823
Ray Milkey269ffb92014-04-03 14:43:30 -0700824 //
825 // Remove all Ports on the Switch
826 //
827 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
828 for (Port port : sw.getPorts()) {
829 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
830 port, switchEvent);
831 PortEvent portEvent = new PortEvent(port.getDpid(),
832 port.getNumber());
833 portsToRemove.add(portEvent);
834 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700835 for (PortEvent portEvent : portsToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700836 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700837 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800838
Jonathan Harte37e4e22014-05-13 19:12:02 -0700839 topology.removeSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700840 apiRemovedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800841 }
842
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800843 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700844 * Add a port to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800845 *
846 * @param portEvent the Port Event with the port to add.
847 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800848 private void addPort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700849 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700850 if (sw == null) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700851 log.debug("{} reordered because switch is null", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700852 // Reordered event: delay the event in local cache
853 ByteBuffer id = portEvent.getIDasByteBuffer();
854 reorderedAddedPortEvents.put(id, portEvent);
855 return;
856 }
857 SwitchImpl switchImpl = getSwitchImpl(sw);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800858
Ray Milkey269ffb92014-04-03 14:43:30 -0700859 Port port = sw.getPort(portEvent.getNumber());
860 if (port == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700861 port = new PortImpl(topology, sw, portEvent.getNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -0700862 switchImpl.addPort(port);
863 } else {
864 // TODO: Update the port attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700865 log.debug("Update port attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700866 }
867 apiAddedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800868 }
869
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800870 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700871 * Remove a port from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800872 *
873 * @param portEvent the Port Event with the port to remove.
874 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800875 private void removePort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700876 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700877 if (sw == null) {
878 log.warn("Parent Switch for Port {} already removed, ignoring",
879 portEvent);
880 return;
881 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800882
Ray Milkey269ffb92014-04-03 14:43:30 -0700883 Port port = sw.getPort(portEvent.getNumber());
884 if (port == null) {
885 log.warn("Port {} already removed, ignoring", portEvent);
886 return;
887 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800888
Ray Milkey269ffb92014-04-03 14:43:30 -0700889 //
890 // Remove all Devices attached to the Port
891 //
892 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
893 for (Device device : port.getDevices()) {
894 log.debug("Removing Device {} on Port {}", device, portEvent);
895 DeviceEvent deviceEvent = new DeviceEvent(device.getMacAddress());
896 SwitchPort switchPort = new SwitchPort(port.getSwitch().getDpid(),
897 port.getNumber());
898 deviceEvent.addAttachmentPoint(switchPort);
899 devicesToRemove.add(deviceEvent);
900 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700901 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700902 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700903 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800904
Ray Milkey269ffb92014-04-03 14:43:30 -0700905 //
906 // Remove all Links connected to the Port
907 //
908 Set<Link> links = new HashSet<>();
909 links.add(port.getOutgoingLink());
910 links.add(port.getIncomingLink());
911 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
912 for (Link link : links) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700913 if (link == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700914 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700915 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700916 log.debug("Removing Link {} on Port {}", link, portEvent);
917 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
918 link.getSrcPort().getNumber(),
919 link.getDstSwitch().getDpid(),
920 link.getDstPort().getNumber());
921 linksToRemove.add(linkEvent);
922 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700923 for (LinkEvent linkEvent : linksToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700924 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700925 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800926
Ray Milkey269ffb92014-04-03 14:43:30 -0700927 // Remove the Port from the Switch
928 SwitchImpl switchImpl = getSwitchImpl(sw);
929 switchImpl.removePort(port);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800930
Ray Milkey269ffb92014-04-03 14:43:30 -0700931 apiRemovedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800932 }
933
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800934 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700935 * Add a link to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800936 *
937 * @param linkEvent the Link Event with the link to add.
938 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800939 private void addLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700940 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700941 linkEvent.getSrc().number);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700942 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700943 linkEvent.getDst().number);
944 if ((srcPort == null) || (dstPort == null)) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700945 log.debug("{} reordered because {} port is null", linkEvent,
946 (srcPort == null) ? "src" : "dst");
947
Ray Milkey269ffb92014-04-03 14:43:30 -0700948 // Reordered event: delay the event in local cache
949 ByteBuffer id = linkEvent.getIDasByteBuffer();
950 reorderedAddedLinkEvents.put(id, linkEvent);
951 return;
952 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800953
Ray Milkey269ffb92014-04-03 14:43:30 -0700954 // Get the Link instance from the Destination Port Incoming Link
955 Link link = dstPort.getIncomingLink();
956 assert (link == srcPort.getOutgoingLink());
957 if (link == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700958 link = new LinkImpl(topology, srcPort, dstPort);
959 topology.putLink(link);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800960
Ray Milkey269ffb92014-04-03 14:43:30 -0700961 // Remove all Devices attached to the Ports
962 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
963 ArrayList<Port> ports = new ArrayList<>();
964 ports.add(srcPort);
965 ports.add(dstPort);
966 for (Port port : ports) {
967 for (Device device : port.getDevices()) {
968 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
969 device, port, linkEvent);
970 DeviceEvent deviceEvent =
971 new DeviceEvent(device.getMacAddress());
972 SwitchPort switchPort =
973 new SwitchPort(port.getSwitch().getDpid(),
974 port.getNumber());
975 deviceEvent.addAttachmentPoint(switchPort);
976 devicesToRemove.add(deviceEvent);
977 }
978 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700979 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700980 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700981 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700982 } else {
983 // TODO: Update the link attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700984 log.debug("Update link attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700985 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800986
Ray Milkey269ffb92014-04-03 14:43:30 -0700987 apiAddedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800988 }
989
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800990 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700991 * Remove a link from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800992 *
993 * @param linkEvent the Link Event with the link to remove.
994 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800995 private void removeLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700996 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700997 linkEvent.getSrc().number);
998 if (srcPort == null) {
999 log.warn("Src Port for Link {} already removed, ignoring",
1000 linkEvent);
1001 return;
1002 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001003
Jonathan Harte37e4e22014-05-13 19:12:02 -07001004 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -07001005 linkEvent.getDst().number);
1006 if (dstPort == null) {
1007 log.warn("Dst Port for Link {} already removed, ignoring",
1008 linkEvent);
1009 return;
1010 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001011
Ray Milkey269ffb92014-04-03 14:43:30 -07001012 //
1013 // Remove the Link instance from the Destination Port Incoming Link
1014 // and the Source Port Outgoing Link.
1015 //
1016 Link link = dstPort.getIncomingLink();
1017 if (link == null) {
1018 log.warn("Link {} already removed on destination Port", linkEvent);
1019 }
1020 link = srcPort.getOutgoingLink();
1021 if (link == null) {
1022 log.warn("Link {} already removed on src Port", linkEvent);
1023 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001024
1025 // TODO should we check that we get the same link from each port?
1026 if (link != null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001027 topology.removeLink(link);
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001028 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001029
Ray Milkey269ffb92014-04-03 14:43:30 -07001030 apiRemovedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001031 }
1032
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001033 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001034 * Add a device to the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001035 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001036 * TODO: Device-related work is incomplete.
1037 * TODO: Eventually, we might need to consider reordering
1038 * or addLink() and addDevice() events on the same port.
1039 *
1040 * @param deviceEvent the Device Event with the device to add.
1041 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001042 private void addDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001043 log.debug("Adding a device to the topology with mac {}", deviceEvent.getMac());
1044 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001045
Ray Milkey269ffb92014-04-03 14:43:30 -07001046 if (device == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001047 log.debug("Existing device was not found in the Topology: Adding new device: mac {}", deviceEvent.getMac());
1048 device = new DeviceImpl(topology, deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001049 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001050
Ray Milkey269ffb92014-04-03 14:43:30 -07001051 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001052
Ray Milkey269ffb92014-04-03 14:43:30 -07001053 // Process each attachment point
1054 boolean attachmentFound = false;
1055 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1056 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001057 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001058 if (port == null) {
1059 // Reordered event: delay the event in local cache
1060 ByteBuffer id = deviceEvent.getIDasByteBuffer();
1061 reorderedAddedDeviceEvents.put(id, deviceEvent);
1062 continue;
1063 }
1064 // Attached Ports must not have Link
1065 if (port.getOutgoingLink() != null ||
1066 port.getIncomingLink() != null) {
1067 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
1068 port.getOutgoingLink(),
1069 port.getIncomingLink());
1070 continue;
1071 }
1072
1073 // Add Device <-> Port attachment
1074 PortImpl portImpl = getPortImpl(port);
1075 portImpl.addDevice(device);
1076 deviceImpl.addAttachmentPoint(port);
1077 attachmentFound = true;
1078 }
1079
Jonathan Harte37e4e22014-05-13 19:12:02 -07001080 // Update the device in the topology
Ray Milkey269ffb92014-04-03 14:43:30 -07001081 if (attachmentFound) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001082 log.debug("Storing the device info into the Topology: mac {}", deviceEvent.getMac());
1083 topology.putDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001084 apiAddedDeviceEvents.add(deviceEvent);
1085 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001086 }
1087
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001088 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001089 * Remove a device from the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001090 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001091 * TODO: Device-related work is incomplete.
1092 *
1093 * @param deviceEvent the Device Event with the device to remove.
1094 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001095 private void removeDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001096 log.debug("Removing a device to the topology: mac {}", deviceEvent.getMac());
1097 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001098 if (device == null) {
1099 log.warn("Device {} already removed, ignoring", deviceEvent);
1100 return;
1101 }
1102 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001103
Ray Milkey269ffb92014-04-03 14:43:30 -07001104 // Process each attachment point
1105 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1106 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001107 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001108 if (port == null) {
1109 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
1110 continue;
1111 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001112
Ray Milkey269ffb92014-04-03 14:43:30 -07001113 // Remove Device <-> Port attachment
1114 PortImpl portImpl = getPortImpl(port);
1115 portImpl.removeDevice(device);
1116 deviceImpl.removeAttachmentPoint(port);
1117 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001118
Jonathan Harte37e4e22014-05-13 19:12:02 -07001119 log.debug("Removing the device info into the Topology: mac {}", deviceEvent.getMac());
1120 topology.removeDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001121 apiRemovedDeviceEvents.add(deviceEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001122 }
Jonathan Hart22eb9882014-02-11 15:52:59 -08001123
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001124 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001125 * Get the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001126 *
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001127 * @param sw the Switch to cast.
1128 * @return the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001129 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001130 private SwitchImpl getSwitchImpl(Switch sw) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001131 if (sw instanceof SwitchImpl) {
1132 return (SwitchImpl) sw;
1133 }
1134 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001135 }
1136
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001137 /**
1138 * Get the PortImpl-casted port implementation.
1139 *
1140 * @param port the Port to cast.
1141 * @return the PortImpl-casted port implementation.
1142 */
1143 private PortImpl getPortImpl(Port port) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001144 if (port instanceof PortImpl) {
1145 return (PortImpl) port;
1146 }
1147 throw new ClassCastException("PortImpl expected, but found: " + port);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001148 }
1149
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001150 /**
1151 * Get the LinkImpl-casted link implementation.
1152 *
1153 * @param link the Link to cast.
1154 * @return the LinkImpl-casted link implementation.
1155 */
1156 private LinkImpl getLinkImpl(Link link) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001157 if (link instanceof LinkImpl) {
1158 return (LinkImpl) link;
1159 }
1160 throw new ClassCastException("LinkImpl expected, but found: " + link);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001161 }
1162
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001163 /**
1164 * Get the DeviceImpl-casted device implementation.
1165 *
1166 * @param device the Device to cast.
1167 * @return the DeviceImpl-casted device implementation.
1168 */
1169 private DeviceImpl getDeviceImpl(Device device) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001170 if (device instanceof DeviceImpl) {
1171 return (DeviceImpl) device;
1172 }
1173 throw new ClassCastException("DeviceImpl expected, but found: " + device);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001174 }
1175
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001176 /**
1177 * Read the whole topology from the database.
1178 *
1179 * @return a collection of EventEntry-encapsulated Topology Events for
1180 * the whole topology.
1181 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001182 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
Ray Milkey269ffb92014-04-03 14:43:30 -07001183 Collection<EventEntry<TopologyEvent>> collection =
1184 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001185
Ray Milkey269ffb92014-04-03 14:43:30 -07001186 // XXX May need to clear whole topology first, depending on
1187 // how we initially subscribe to replication events
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001188
Ray Milkey269ffb92014-04-03 14:43:30 -07001189 // Add all active switches
1190 for (KVSwitch sw : KVSwitch.getAllSwitches()) {
1191 if (sw.getStatus() != KVSwitch.STATUS.ACTIVE) {
1192 continue;
1193 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001194
Ray Milkey269ffb92014-04-03 14:43:30 -07001195 SwitchEvent switchEvent = new SwitchEvent(sw.getDpid());
1196 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
1197 EventEntry<TopologyEvent> eventEntry =
1198 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1199 topologyEvent);
1200 collection.add(eventEntry);
1201 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001202
Ray Milkey269ffb92014-04-03 14:43:30 -07001203 // Add all active ports
1204 for (KVPort p : KVPort.getAllPorts()) {
1205 if (p.getStatus() != KVPort.STATUS.ACTIVE) {
1206 continue;
1207 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001208
Ray Milkey269ffb92014-04-03 14:43:30 -07001209 PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
1210 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
1211 EventEntry<TopologyEvent> eventEntry =
1212 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1213 topologyEvent);
1214 collection.add(eventEntry);
1215 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001216
TeruU28adcc32014-04-15 17:57:35 -07001217 for (KVDevice d : KVDevice.getAllDevices()) {
1218 DeviceEvent devEvent = new DeviceEvent(MACAddress.valueOf(d.getMac()));
1219 for (byte[] portId : d.getAllPortIds()) {
1220 devEvent.addAttachmentPoint(new SwitchPort(KVPort.getDpidFromKey(portId), KVPort.getNumberFromKey(portId)));
1221 }
1222 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001223
Ray Milkey269ffb92014-04-03 14:43:30 -07001224 for (KVLink l : KVLink.getAllLinks()) {
1225 LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
1226 l.getSrc().number,
1227 l.getDst().dpid,
1228 l.getDst().number);
1229 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
1230 EventEntry<TopologyEvent> eventEntry =
1231 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1232 topologyEvent);
1233 collection.add(eventEntry);
1234 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001235
Ray Milkey269ffb92014-04-03 14:43:30 -07001236 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001237 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001238}