blob: 0dac65fc9cdedd6d1f29e2cb04961d3f2dec209e [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)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700516 log.debug("Sending add switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700517 // Send out notification
518 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
519 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800520
Ray Milkey269ffb92014-04-03 14:43:30 -0700521 // Send out notification for each port
522 for (PortEvent portEvent : portEvents) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700523 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700524 topologyEvent = new TopologyEvent(portEvent);
525 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
526 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800527
Ray Milkey269ffb92014-04-03 14:43:30 -0700528 //
529 // Keep track of the added ports
530 //
531 // Get the old Port Events
532 Map<ByteBuffer, PortEvent> oldPortEvents =
533 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700534 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700535 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700536 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800537
Ray Milkey269ffb92014-04-03 14:43:30 -0700538 // Store the new Port Events in the local cache
539 Map<ByteBuffer, PortEvent> newPortEvents = new HashMap<>();
540 for (PortEvent portEvent : portEvents) {
541 ByteBuffer id = portEvent.getIDasByteBuffer();
542 newPortEvents.put(id, portEvent);
543 }
544 discoveredAddedPortEvents.put(switchEvent.getDpid(),
545 newPortEvents);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800546
Ray Milkey269ffb92014-04-03 14:43:30 -0700547 //
548 // Extract the removed ports
549 //
550 List<PortEvent> removedPortEvents = new LinkedList<>();
551 for (Map.Entry<ByteBuffer, PortEvent> entry : oldPortEvents.entrySet()) {
552 ByteBuffer key = entry.getKey();
553 PortEvent portEvent = entry.getValue();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700554 if (!newPortEvents.containsKey(key)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700555 removedPortEvents.add(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700556 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700557 }
558
559 // Cleanup old removed ports
Ray Milkeyb29e6262014-04-09 16:02:14 -0700560 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700561 removePortDiscoveryEvent(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700562 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700563 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800564 }
565
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800566 /**
567 * Switch removed event.
568 *
569 * @param switchEvent the switch event.
570 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800571 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800572 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700573 // Get the old Port Events
574 Map<ByteBuffer, PortEvent> oldPortEvents =
575 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700576 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700577 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700578 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800579
Ray Milkey269ffb92014-04-03 14:43:30 -0700580 if (datastore.deactivateSwitch(switchEvent, oldPortEvents.values())) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700581 log.debug("Sending remove switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700582 // Send out notification
583 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800584
Ray Milkey269ffb92014-04-03 14:43:30 -0700585 //
586 // Send out notification for each port.
587 //
588 // NOTE: We don't use removePortDiscoveryEvent() for the cleanup,
589 // because it will attempt to remove the port from the database,
590 // and the deactiveSwitch() call above already removed all ports.
591 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700592 for (PortEvent portEvent : oldPortEvents.values()) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700593 log.debug("Sending remove port:", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700594 eventChannel.removeEntry(portEvent.getID());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700595 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700596 discoveredAddedPortEvents.remove(switchEvent.getDpid());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800597
Ray Milkey269ffb92014-04-03 14:43:30 -0700598 // Cleanup for each link
599 Map<ByteBuffer, LinkEvent> oldLinkEvents =
600 discoveredAddedLinkEvents.get(switchEvent.getDpid());
601 if (oldLinkEvents != null) {
602 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
603 removeLinkDiscoveryEvent(linkEvent);
604 }
605 discoveredAddedLinkEvents.remove(switchEvent.getDpid());
606 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800607
Ray Milkey269ffb92014-04-03 14:43:30 -0700608 // Cleanup for each device
609 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
610 discoveredAddedDeviceEvents.get(switchEvent.getDpid());
611 if (oldDeviceEvents != null) {
612 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
613 removeDeviceDiscoveryEvent(deviceEvent);
614 }
615 discoveredAddedDeviceEvents.remove(switchEvent.getDpid());
616 }
617 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800618 }
619
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800620 /**
621 * Port discovered event.
622 *
623 * @param portEvent the port event.
624 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800625 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800626 public void putPortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700627 if (datastore.addPort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700628 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700629 // Send out notification
630 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
631 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800632
Ray Milkey269ffb92014-04-03 14:43:30 -0700633 // Store the new Port Event in the local cache
634 Map<ByteBuffer, PortEvent> oldPortEvents =
635 discoveredAddedPortEvents.get(portEvent.getDpid());
636 if (oldPortEvents == null) {
637 oldPortEvents = new HashMap<>();
638 discoveredAddedPortEvents.put(portEvent.getDpid(),
639 oldPortEvents);
640 }
641 ByteBuffer id = portEvent.getIDasByteBuffer();
642 oldPortEvents.put(id, portEvent);
643 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800644 }
645
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800646 /**
647 * Port removed event.
648 *
649 * @param portEvent the port event.
650 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800651 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800652 public void removePortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700653 if (datastore.deactivatePort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700654 log.debug("Sending remove port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700655 // Send out notification
656 eventChannel.removeEntry(portEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800657
Ray Milkey269ffb92014-04-03 14:43:30 -0700658 // Cleanup the Port Event from the local cache
659 Map<ByteBuffer, PortEvent> oldPortEvents =
660 discoveredAddedPortEvents.get(portEvent.getDpid());
661 if (oldPortEvents != null) {
662 ByteBuffer id = portEvent.getIDasByteBuffer();
663 oldPortEvents.remove(id);
664 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800665
Ray Milkey269ffb92014-04-03 14:43:30 -0700666 // Cleanup for the incoming link
667 Map<ByteBuffer, LinkEvent> oldLinkEvents =
668 discoveredAddedLinkEvents.get(portEvent.getDpid());
669 if (oldLinkEvents != null) {
670 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
671 if (linkEvent.getDst().equals(portEvent.id)) {
672 removeLinkDiscoveryEvent(linkEvent);
673 // XXX If we change our model to allow multiple Link on
674 // a Port, this loop must be fixed to allow continuing.
675 break;
676 }
677 }
678 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800679
Ray Milkey269ffb92014-04-03 14:43:30 -0700680 // Cleanup for the connected devices
681 // TODO: The implementation below is probably wrong
682 List<DeviceEvent> removedDeviceEvents = new LinkedList<>();
683 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
684 discoveredAddedDeviceEvents.get(portEvent.getDpid());
685 if (oldDeviceEvents != null) {
686 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
687 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
688 if (swp.equals(portEvent.id)) {
689 removedDeviceEvents.add(deviceEvent);
690 }
691 }
692 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700693 for (DeviceEvent deviceEvent : removedDeviceEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700694 removeDeviceDiscoveryEvent(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700695 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700696 }
697 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800698 }
699
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800700 /**
701 * Link discovered event.
702 *
703 * @param linkEvent the link event.
704 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800705 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800706 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700707 if (datastore.addLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700708 log.debug("Sending add link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700709 // Send out notification
710 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
711 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800712
Ray Milkey269ffb92014-04-03 14:43:30 -0700713 // Store the new Link Event in the local cache
714 Map<ByteBuffer, LinkEvent> oldLinkEvents =
715 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
716 if (oldLinkEvents == null) {
717 oldLinkEvents = new HashMap<>();
718 discoveredAddedLinkEvents.put(linkEvent.getDst().getDpid(),
719 oldLinkEvents);
720 }
721 ByteBuffer id = linkEvent.getIDasByteBuffer();
722 oldLinkEvents.put(id, linkEvent);
723 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800724 }
725
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800726 /**
727 * Link removed event.
728 *
729 * @param linkEvent the link event.
730 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800731 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800732 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700733 if (datastore.removeLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700734 log.debug("Sending remove link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700735 // Send out notification
736 eventChannel.removeEntry(linkEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800737
Ray Milkey269ffb92014-04-03 14:43:30 -0700738 // Cleanup the Link Event from the local cache
739 Map<ByteBuffer, LinkEvent> oldLinkEvents =
740 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
741 if (oldLinkEvents != null) {
742 ByteBuffer id = linkEvent.getIDasByteBuffer();
743 oldLinkEvents.remove(id);
744 }
745 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800746 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800747
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800748 /**
749 * Device discovered event.
750 *
751 * @param deviceEvent the device event.
752 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800753 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800754 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700755 if (datastore.addDevice(deviceEvent)) {
756 // Send out notification
757 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
758 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700759 log.debug("Put the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -0700760
761 // Store the new Device Event in the local cache
762 // TODO: The implementation below is probably wrong
763 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
764 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
765 discoveredAddedDeviceEvents.get(swp.getDpid());
766 if (oldDeviceEvents == null) {
767 oldDeviceEvents = new HashMap<>();
768 discoveredAddedDeviceEvents.put(swp.getDpid(),
769 oldDeviceEvents);
770 }
771 ByteBuffer id = deviceEvent.getIDasByteBuffer();
772 oldDeviceEvents.put(id, deviceEvent);
773 }
774 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800775 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800776
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800777 /**
778 * Device removed event.
779 *
780 * @param deviceEvent the device event.
781 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800782 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800783 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700784 if (datastore.removeDevice(deviceEvent)) {
785 // Send out notification
786 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Harte37e4e22014-05-13 19:12:02 -0700787 log.debug("Remove the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800788
Ray Milkey269ffb92014-04-03 14:43:30 -0700789 // Cleanup the Device Event from the local cache
790 // TODO: The implementation below is probably wrong
791 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
792 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
793 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
794 discoveredAddedDeviceEvents.get(swp.getDpid());
795 if (oldDeviceEvents != null) {
796 oldDeviceEvents.remove(id);
797 }
798 }
799 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800800 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800801
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800802 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700803 * Add a switch to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800804 *
805 * @param switchEvent the Switch Event with the switch to add.
806 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800807 private void addSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700808 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700809 if (sw == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700810 sw = new SwitchImpl(topology, switchEvent.getDpid());
811 topology.putSwitch(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700812 } else {
813 // TODO: Update the switch attributes
814 // TODO: Nothing to do for now
Ray Milkey1aa71f82014-04-08 16:23:24 -0700815 log.debug("Update switch attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700816 }
817 apiAddedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800818 }
819
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800820 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700821 * Remove a switch from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800822 *
823 * @param switchEvent the Switch Event with the switch to remove.
824 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800825 private void removeSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700826 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700827 if (sw == null) {
828 log.warn("Switch {} already removed, ignoring", switchEvent);
829 return;
830 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800831
Ray Milkey269ffb92014-04-03 14:43:30 -0700832 //
833 // Remove all Ports on the Switch
834 //
835 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
836 for (Port port : sw.getPorts()) {
837 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
838 port, switchEvent);
839 PortEvent portEvent = new PortEvent(port.getDpid(),
840 port.getNumber());
841 portsToRemove.add(portEvent);
842 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700843 for (PortEvent portEvent : portsToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700844 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700845 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800846
Jonathan Harte37e4e22014-05-13 19:12:02 -0700847 topology.removeSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700848 apiRemovedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800849 }
850
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800851 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700852 * Add a port to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800853 *
854 * @param portEvent the Port Event with the port to add.
855 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800856 private void addPort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700857 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700858 if (sw == null) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700859 log.debug("{} reordered because switch is null", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700860 // Reordered event: delay the event in local cache
861 ByteBuffer id = portEvent.getIDasByteBuffer();
862 reorderedAddedPortEvents.put(id, portEvent);
863 return;
864 }
865 SwitchImpl switchImpl = getSwitchImpl(sw);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800866
Ray Milkey269ffb92014-04-03 14:43:30 -0700867 Port port = sw.getPort(portEvent.getNumber());
868 if (port == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700869 port = new PortImpl(topology, sw, portEvent.getNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -0700870 switchImpl.addPort(port);
871 } else {
872 // TODO: Update the port attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700873 log.debug("Update port attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700874 }
875 apiAddedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800876 }
877
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800878 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700879 * Remove a port from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800880 *
881 * @param portEvent the Port Event with the port to remove.
882 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800883 private void removePort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700884 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700885 if (sw == null) {
886 log.warn("Parent Switch for Port {} already removed, ignoring",
887 portEvent);
888 return;
889 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800890
Ray Milkey269ffb92014-04-03 14:43:30 -0700891 Port port = sw.getPort(portEvent.getNumber());
892 if (port == null) {
893 log.warn("Port {} already removed, ignoring", portEvent);
894 return;
895 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800896
Ray Milkey269ffb92014-04-03 14:43:30 -0700897 //
898 // Remove all Devices attached to the Port
899 //
900 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
901 for (Device device : port.getDevices()) {
902 log.debug("Removing Device {} on Port {}", device, portEvent);
903 DeviceEvent deviceEvent = new DeviceEvent(device.getMacAddress());
904 SwitchPort switchPort = new SwitchPort(port.getSwitch().getDpid(),
905 port.getNumber());
906 deviceEvent.addAttachmentPoint(switchPort);
907 devicesToRemove.add(deviceEvent);
908 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700909 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700910 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700911 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800912
Ray Milkey269ffb92014-04-03 14:43:30 -0700913 //
914 // Remove all Links connected to the Port
915 //
916 Set<Link> links = new HashSet<>();
917 links.add(port.getOutgoingLink());
918 links.add(port.getIncomingLink());
919 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
920 for (Link link : links) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700921 if (link == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700922 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700923 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700924 log.debug("Removing Link {} on Port {}", link, portEvent);
925 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
926 link.getSrcPort().getNumber(),
927 link.getDstSwitch().getDpid(),
928 link.getDstPort().getNumber());
929 linksToRemove.add(linkEvent);
930 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700931 for (LinkEvent linkEvent : linksToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700932 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700933 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800934
Ray Milkey269ffb92014-04-03 14:43:30 -0700935 // Remove the Port from the Switch
936 SwitchImpl switchImpl = getSwitchImpl(sw);
937 switchImpl.removePort(port);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800938
Ray Milkey269ffb92014-04-03 14:43:30 -0700939 apiRemovedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800940 }
941
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800942 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700943 * Add a link to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800944 *
945 * @param linkEvent the Link Event with the link to add.
946 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800947 private void addLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700948 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700949 linkEvent.getSrc().number);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700950 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700951 linkEvent.getDst().number);
952 if ((srcPort == null) || (dstPort == null)) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700953 log.debug("{} reordered because {} port is null", linkEvent,
954 (srcPort == null) ? "src" : "dst");
955
Ray Milkey269ffb92014-04-03 14:43:30 -0700956 // Reordered event: delay the event in local cache
957 ByteBuffer id = linkEvent.getIDasByteBuffer();
958 reorderedAddedLinkEvents.put(id, linkEvent);
959 return;
960 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800961
Ray Milkey269ffb92014-04-03 14:43:30 -0700962 // Get the Link instance from the Destination Port Incoming Link
963 Link link = dstPort.getIncomingLink();
964 assert (link == srcPort.getOutgoingLink());
965 if (link == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700966 link = new LinkImpl(topology, srcPort, dstPort);
967 topology.putLink(link);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800968
Ray Milkey269ffb92014-04-03 14:43:30 -0700969 // Remove all Devices attached to the Ports
970 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
971 ArrayList<Port> ports = new ArrayList<>();
972 ports.add(srcPort);
973 ports.add(dstPort);
974 for (Port port : ports) {
975 for (Device device : port.getDevices()) {
976 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
977 device, port, linkEvent);
978 DeviceEvent deviceEvent =
979 new DeviceEvent(device.getMacAddress());
980 SwitchPort switchPort =
981 new SwitchPort(port.getSwitch().getDpid(),
982 port.getNumber());
983 deviceEvent.addAttachmentPoint(switchPort);
984 devicesToRemove.add(deviceEvent);
985 }
986 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700987 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700988 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700989 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700990 } else {
991 // TODO: Update the link attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700992 log.debug("Update link attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700993 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800994
Ray Milkey269ffb92014-04-03 14:43:30 -0700995 apiAddedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800996 }
997
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800998 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700999 * Remove a link from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001000 *
1001 * @param linkEvent the Link Event with the link to remove.
1002 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001003 private void removeLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001004 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -07001005 linkEvent.getSrc().number);
1006 if (srcPort == null) {
1007 log.warn("Src Port for Link {} already removed, ignoring",
1008 linkEvent);
1009 return;
1010 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001011
Jonathan Harte37e4e22014-05-13 19:12:02 -07001012 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -07001013 linkEvent.getDst().number);
1014 if (dstPort == null) {
1015 log.warn("Dst Port for Link {} already removed, ignoring",
1016 linkEvent);
1017 return;
1018 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001019
Ray Milkey269ffb92014-04-03 14:43:30 -07001020 //
1021 // Remove the Link instance from the Destination Port Incoming Link
1022 // and the Source Port Outgoing Link.
1023 //
1024 Link link = dstPort.getIncomingLink();
1025 if (link == null) {
1026 log.warn("Link {} already removed on destination Port", linkEvent);
1027 }
1028 link = srcPort.getOutgoingLink();
1029 if (link == null) {
1030 log.warn("Link {} already removed on src Port", linkEvent);
1031 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001032
1033 // TODO should we check that we get the same link from each port?
1034 if (link != null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001035 topology.removeLink(link);
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001036 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001037
Ray Milkey269ffb92014-04-03 14:43:30 -07001038 apiRemovedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001039 }
1040
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001041 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001042 * Add a device to the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001043 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001044 * TODO: Device-related work is incomplete.
1045 * TODO: Eventually, we might need to consider reordering
1046 * or addLink() and addDevice() events on the same port.
1047 *
1048 * @param deviceEvent the Device Event with the device to add.
1049 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001050 private void addDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001051 log.debug("Adding a device to the topology with mac {}", deviceEvent.getMac());
1052 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001053
Ray Milkey269ffb92014-04-03 14:43:30 -07001054 if (device == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001055 log.debug("Existing device was not found in the Topology: Adding new device: mac {}", deviceEvent.getMac());
1056 device = new DeviceImpl(topology, deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001057 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001058
Ray Milkey269ffb92014-04-03 14:43:30 -07001059 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001060
Ray Milkey269ffb92014-04-03 14:43:30 -07001061 // Process each attachment point
1062 boolean attachmentFound = false;
1063 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1064 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001065 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001066 if (port == null) {
1067 // Reordered event: delay the event in local cache
1068 ByteBuffer id = deviceEvent.getIDasByteBuffer();
1069 reorderedAddedDeviceEvents.put(id, deviceEvent);
1070 continue;
1071 }
1072 // Attached Ports must not have Link
1073 if (port.getOutgoingLink() != null ||
1074 port.getIncomingLink() != null) {
1075 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
1076 port.getOutgoingLink(),
1077 port.getIncomingLink());
1078 continue;
1079 }
1080
1081 // Add Device <-> Port attachment
1082 PortImpl portImpl = getPortImpl(port);
1083 portImpl.addDevice(device);
1084 deviceImpl.addAttachmentPoint(port);
1085 attachmentFound = true;
1086 }
1087
Jonathan Harte37e4e22014-05-13 19:12:02 -07001088 // Update the device in the topology
Ray Milkey269ffb92014-04-03 14:43:30 -07001089 if (attachmentFound) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001090 log.debug("Storing the device info into the Topology: mac {}", deviceEvent.getMac());
1091 topology.putDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001092 apiAddedDeviceEvents.add(deviceEvent);
1093 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001094 }
1095
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001096 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001097 * Remove a device from the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001098 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001099 * TODO: Device-related work is incomplete.
1100 *
1101 * @param deviceEvent the Device Event with the device to remove.
1102 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001103 private void removeDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001104 log.debug("Removing a device to the topology: mac {}", deviceEvent.getMac());
1105 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001106 if (device == null) {
1107 log.warn("Device {} already removed, ignoring", deviceEvent);
1108 return;
1109 }
1110 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001111
Ray Milkey269ffb92014-04-03 14:43:30 -07001112 // Process each attachment point
1113 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1114 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001115 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001116 if (port == null) {
1117 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
1118 continue;
1119 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001120
Ray Milkey269ffb92014-04-03 14:43:30 -07001121 // Remove Device <-> Port attachment
1122 PortImpl portImpl = getPortImpl(port);
1123 portImpl.removeDevice(device);
1124 deviceImpl.removeAttachmentPoint(port);
1125 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001126
Jonathan Harte37e4e22014-05-13 19:12:02 -07001127 log.debug("Removing the device info into the Topology: mac {}", deviceEvent.getMac());
1128 topology.removeDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001129 apiRemovedDeviceEvents.add(deviceEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001130 }
Jonathan Hart22eb9882014-02-11 15:52:59 -08001131
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001132 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001133 * Get the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001134 *
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001135 * @param sw the Switch to cast.
1136 * @return the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001137 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001138 private SwitchImpl getSwitchImpl(Switch sw) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001139 if (sw instanceof SwitchImpl) {
1140 return (SwitchImpl) sw;
1141 }
1142 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001143 }
1144
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001145 /**
1146 * Get the PortImpl-casted port implementation.
1147 *
1148 * @param port the Port to cast.
1149 * @return the PortImpl-casted port implementation.
1150 */
1151 private PortImpl getPortImpl(Port port) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001152 if (port instanceof PortImpl) {
1153 return (PortImpl) port;
1154 }
1155 throw new ClassCastException("PortImpl expected, but found: " + port);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001156 }
1157
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001158 /**
1159 * Get the LinkImpl-casted link implementation.
1160 *
1161 * @param link the Link to cast.
1162 * @return the LinkImpl-casted link implementation.
1163 */
1164 private LinkImpl getLinkImpl(Link link) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001165 if (link instanceof LinkImpl) {
1166 return (LinkImpl) link;
1167 }
1168 throw new ClassCastException("LinkImpl expected, but found: " + link);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001169 }
1170
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001171 /**
1172 * Get the DeviceImpl-casted device implementation.
1173 *
1174 * @param device the Device to cast.
1175 * @return the DeviceImpl-casted device implementation.
1176 */
1177 private DeviceImpl getDeviceImpl(Device device) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001178 if (device instanceof DeviceImpl) {
1179 return (DeviceImpl) device;
1180 }
1181 throw new ClassCastException("DeviceImpl expected, but found: " + device);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001182 }
1183
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001184 /**
1185 * Read the whole topology from the database.
1186 *
1187 * @return a collection of EventEntry-encapsulated Topology Events for
1188 * the whole topology.
1189 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001190 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
Ray Milkey269ffb92014-04-03 14:43:30 -07001191 Collection<EventEntry<TopologyEvent>> collection =
1192 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001193
Ray Milkey269ffb92014-04-03 14:43:30 -07001194 // XXX May need to clear whole topology first, depending on
1195 // how we initially subscribe to replication events
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001196
Ray Milkey269ffb92014-04-03 14:43:30 -07001197 // Add all active switches
1198 for (KVSwitch sw : KVSwitch.getAllSwitches()) {
1199 if (sw.getStatus() != KVSwitch.STATUS.ACTIVE) {
1200 continue;
1201 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001202
Ray Milkey269ffb92014-04-03 14:43:30 -07001203 SwitchEvent switchEvent = new SwitchEvent(sw.getDpid());
1204 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
1205 EventEntry<TopologyEvent> eventEntry =
1206 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1207 topologyEvent);
1208 collection.add(eventEntry);
1209 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001210
Ray Milkey269ffb92014-04-03 14:43:30 -07001211 // Add all active ports
1212 for (KVPort p : KVPort.getAllPorts()) {
1213 if (p.getStatus() != KVPort.STATUS.ACTIVE) {
1214 continue;
1215 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001216
Ray Milkey269ffb92014-04-03 14:43:30 -07001217 PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
1218 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
1219 EventEntry<TopologyEvent> eventEntry =
1220 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1221 topologyEvent);
1222 collection.add(eventEntry);
1223 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001224
TeruU28adcc32014-04-15 17:57:35 -07001225 for (KVDevice d : KVDevice.getAllDevices()) {
1226 DeviceEvent devEvent = new DeviceEvent(MACAddress.valueOf(d.getMac()));
1227 for (byte[] portId : d.getAllPortIds()) {
1228 devEvent.addAttachmentPoint(new SwitchPort(KVPort.getDpidFromKey(portId), KVPort.getNumberFromKey(portId)));
1229 }
1230 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001231
Ray Milkey269ffb92014-04-03 14:43:30 -07001232 for (KVLink l : KVLink.getAllLinks()) {
1233 LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
1234 l.getSrc().number,
1235 l.getDst().dpid,
1236 l.getDst().number);
1237 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
1238 EventEntry<TopologyEvent> eventEntry =
1239 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1240 topologyEvent);
1241 collection.add(eventEntry);
1242 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001243
Ray Milkey269ffb92014-04-03 14:43:30 -07001244 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001245 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001246}