blob: 78b6b9f85e68a3290ace4eedc14703fbaf3ffed2 [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 //
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700170 while (true) {
171 try {
172 EventEntry<TopologyEvent> eventEntry =
173 topologyEvents.take();
Ray Milkey269ffb92014-04-03 14:43:30 -0700174 collection.add(eventEntry);
175 topologyEvents.drainTo(collection);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800176
Ray Milkey269ffb92014-04-03 14:43:30 -0700177 processEvents(collection);
178 collection.clear();
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700179 } catch (Exception exception) {
180 log.debug("Exception processing Topology Events: ",
181 exception);
Ray Milkey269ffb92014-04-03 14:43:30 -0700182 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700183 }
184 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800185
Ray Milkey269ffb92014-04-03 14:43:30 -0700186 /**
187 * Process all topology events.
188 *
189 * @param events the events to process.
190 */
191 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
192 // Local state for computing the final set of events
193 Map<ByteBuffer, SwitchEvent> addedSwitchEvents = new HashMap<>();
194 Map<ByteBuffer, SwitchEvent> removedSwitchEvents = new HashMap<>();
195 Map<ByteBuffer, PortEvent> addedPortEvents = new HashMap<>();
196 Map<ByteBuffer, PortEvent> removedPortEvents = new HashMap<>();
197 Map<ByteBuffer, LinkEvent> addedLinkEvents = new HashMap<>();
198 Map<ByteBuffer, LinkEvent> removedLinkEvents = new HashMap<>();
199 Map<ByteBuffer, DeviceEvent> addedDeviceEvents = new HashMap<>();
200 Map<ByteBuffer, DeviceEvent> removedDeviceEvents = new HashMap<>();
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800201
Ray Milkey269ffb92014-04-03 14:43:30 -0700202 //
203 // Classify and suppress matching events
204 //
205 for (EventEntry<TopologyEvent> event : events) {
206 TopologyEvent topologyEvent = event.eventData();
207 SwitchEvent switchEvent = topologyEvent.switchEvent;
208 PortEvent portEvent = topologyEvent.portEvent;
209 LinkEvent linkEvent = topologyEvent.linkEvent;
210 DeviceEvent deviceEvent = topologyEvent.deviceEvent;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800211
Ray Milkey269ffb92014-04-03 14:43:30 -0700212 //
213 // Extract the events
214 //
215 switch (event.eventType()) {
216 case ENTRY_ADD:
217 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
218 if (switchEvent != null) {
219 ByteBuffer id = switchEvent.getIDasByteBuffer();
220 addedSwitchEvents.put(id, switchEvent);
221 removedSwitchEvents.remove(id);
222 // Switch Events are not affected by event reordering
223 }
224 if (portEvent != null) {
225 ByteBuffer id = portEvent.getIDasByteBuffer();
226 addedPortEvents.put(id, portEvent);
227 removedPortEvents.remove(id);
228 reorderedAddedPortEvents.remove(id);
229 }
230 if (linkEvent != null) {
231 ByteBuffer id = linkEvent.getIDasByteBuffer();
232 addedLinkEvents.put(id, linkEvent);
233 removedLinkEvents.remove(id);
234 reorderedAddedLinkEvents.remove(id);
235 }
236 if (deviceEvent != null) {
237 ByteBuffer id = deviceEvent.getIDasByteBuffer();
238 addedDeviceEvents.put(id, deviceEvent);
239 removedDeviceEvents.remove(id);
240 reorderedAddedDeviceEvents.remove(id);
241 }
242 break;
243 case ENTRY_REMOVE:
244 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
245 if (switchEvent != null) {
246 ByteBuffer id = switchEvent.getIDasByteBuffer();
247 addedSwitchEvents.remove(id);
248 removedSwitchEvents.put(id, switchEvent);
249 // Switch Events are not affected by event reordering
250 }
251 if (portEvent != null) {
252 ByteBuffer id = portEvent.getIDasByteBuffer();
253 addedPortEvents.remove(id);
254 removedPortEvents.put(id, portEvent);
255 reorderedAddedPortEvents.remove(id);
256 }
257 if (linkEvent != null) {
258 ByteBuffer id = linkEvent.getIDasByteBuffer();
259 addedLinkEvents.remove(id);
260 removedLinkEvents.put(id, linkEvent);
261 reorderedAddedLinkEvents.remove(id);
262 }
263 if (deviceEvent != null) {
264 ByteBuffer id = deviceEvent.getIDasByteBuffer();
265 addedDeviceEvents.remove(id);
266 removedDeviceEvents.put(id, deviceEvent);
267 reorderedAddedDeviceEvents.remove(id);
268 }
269 break;
Ray Milkey0b122ed2014-04-14 10:06:03 -0700270 default:
271 log.error("Unknown topology event {}",
272 event.eventType());
Ray Milkey269ffb92014-04-03 14:43:30 -0700273 }
274 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800275
Ray Milkey269ffb92014-04-03 14:43:30 -0700276 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700277 // Lock the topology while it is modified
Ray Milkey269ffb92014-04-03 14:43:30 -0700278 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700279 topology.acquireWriteLock();
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800280
Ray Milkey269ffb92014-04-03 14:43:30 -0700281 try {
282 //
283 // Apply the classified events.
284 //
285 // Apply the "add" events in the proper order:
286 // switch, port, link, device
287 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700288 for (SwitchEvent switchEvent : addedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700289 addSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700290 }
291 for (PortEvent portEvent : addedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700292 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700293 }
294 for (LinkEvent linkEvent : addedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700295 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700296 }
297 for (DeviceEvent deviceEvent : addedDeviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700298 addDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700299 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700300 //
301 // Apply the "remove" events in the reverse order:
302 // device, link, port, switch
303 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700304 for (DeviceEvent deviceEvent : removedDeviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700305 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700306 }
307 for (LinkEvent linkEvent : removedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700308 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700309 }
310 for (PortEvent portEvent : removedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700311 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700312 }
313 for (SwitchEvent switchEvent : removedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700314 removeSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700315 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800316
Ray Milkey269ffb92014-04-03 14:43:30 -0700317 //
318 // Apply reordered events
319 //
320 applyReorderedEvents(!addedSwitchEvents.isEmpty(),
321 !addedPortEvents.isEmpty());
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800322
Ray Milkey269ffb92014-04-03 14:43:30 -0700323 } finally {
324 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700325 // Topology modifications completed: Release the lock
Ray Milkey269ffb92014-04-03 14:43:30 -0700326 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700327 topology.releaseWriteLock();
Ray Milkey269ffb92014-04-03 14:43:30 -0700328 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800329
Ray Milkey269ffb92014-04-03 14:43:30 -0700330 //
331 // Dispatch the Topology Notification Events to the applications
332 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700333 dispatchTopologyEvents();
Ray Milkey269ffb92014-04-03 14:43:30 -0700334 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800335
Ray Milkey269ffb92014-04-03 14:43:30 -0700336 /**
337 * Receive a notification that an entry is added.
338 *
339 * @param value the value for the entry.
340 */
341 @Override
342 public void entryAdded(TopologyEvent value) {
343 EventEntry<TopologyEvent> eventEntry =
344 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
345 value);
346 topologyEvents.add(eventEntry);
347 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800348
Ray Milkey269ffb92014-04-03 14:43:30 -0700349 /**
350 * Receive a notification that an entry is removed.
351 *
352 * @param value the value for the entry.
353 */
354 @Override
355 public void entryRemoved(TopologyEvent value) {
356 EventEntry<TopologyEvent> eventEntry =
357 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
358 value);
359 topologyEvents.add(eventEntry);
360 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800361
Ray Milkey269ffb92014-04-03 14:43:30 -0700362 /**
363 * Receive a notification that an entry is updated.
364 *
365 * @param value the value for the entry.
366 */
367 @Override
368 public void entryUpdated(TopologyEvent value) {
369 // NOTE: The ADD and UPDATE events are processed in same way
370 entryAdded(value);
371 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800372 }
373
374 /**
375 * Startup processing.
376 *
377 * @param datagridService the datagrid service to use.
378 */
379 void startup(IDatagridService datagridService) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700380 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
381 eventHandler,
382 byte[].class,
383 TopologyEvent.class);
384 eventHandler.start();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800385 }
386
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800387 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700388 * Dispatch Topology Events to the listeners.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800389 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700390 private void dispatchTopologyEvents() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700391 if (apiAddedSwitchEvents.isEmpty() &&
392 apiRemovedSwitchEvents.isEmpty() &&
393 apiAddedPortEvents.isEmpty() &&
394 apiRemovedPortEvents.isEmpty() &&
395 apiAddedLinkEvents.isEmpty() &&
396 apiRemovedLinkEvents.isEmpty() &&
397 apiAddedDeviceEvents.isEmpty() &&
398 apiRemovedDeviceEvents.isEmpty()) {
399 return; // No events to dispatch
400 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800401
Ray Milkey269ffb92014-04-03 14:43:30 -0700402 if (log.isDebugEnabled()) {
403 //
404 // Debug statements
405 // TODO: Those statements should be removed in the future
406 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700407 for (SwitchEvent switchEvent : apiAddedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700408 log.debug("Dispatch Topology Event: ADDED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700409 }
410 for (SwitchEvent switchEvent : apiRemovedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700411 log.debug("Dispatch Topology Event: REMOVED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700412 }
413 for (PortEvent portEvent : apiAddedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700414 log.debug("Dispatch Topology Event: ADDED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700415 }
416 for (PortEvent portEvent : apiRemovedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700417 log.debug("Dispatch Topology Event: REMOVED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700418 }
419 for (LinkEvent linkEvent : apiAddedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700420 log.debug("Dispatch Topology Event: ADDED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700421 }
422 for (LinkEvent linkEvent : apiRemovedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700423 log.debug("Dispatch Topology Event: REMOVED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700424 }
425 for (DeviceEvent deviceEvent : apiAddedDeviceEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700426 log.debug("Dispatch Topology Event: ADDED {}", deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700427 }
428 for (DeviceEvent deviceEvent : apiRemovedDeviceEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700429 log.debug("Dispatch Topology Event: REMOVED {}", deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700430 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700431 }
adminbc181552014-02-21 18:36:42 -0800432
Ray Milkey269ffb92014-04-03 14:43:30 -0700433 // Deliver the events
Jonathan Harte37e4e22014-05-13 19:12:02 -0700434 for (ITopologyListener listener : this.topologyListeners) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700435 // TODO: Should copy before handing them over to listener?
Jonathan Harte37e4e22014-05-13 19:12:02 -0700436 listener.topologyEvents(apiAddedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700437 apiRemovedSwitchEvents,
438 apiAddedPortEvents,
439 apiRemovedPortEvents,
440 apiAddedLinkEvents,
441 apiRemovedLinkEvents,
442 apiAddedDeviceEvents,
443 apiRemovedDeviceEvents);
444 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800445
Ray Milkey269ffb92014-04-03 14:43:30 -0700446 //
447 // Cleanup
448 //
449 apiAddedSwitchEvents.clear();
450 apiRemovedSwitchEvents.clear();
451 apiAddedPortEvents.clear();
452 apiRemovedPortEvents.clear();
453 apiAddedLinkEvents.clear();
454 apiRemovedLinkEvents.clear();
455 apiAddedDeviceEvents.clear();
456 apiRemovedDeviceEvents.clear();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800457 }
458
459 /**
460 * Apply reordered events.
461 *
462 * @param hasAddedSwitchEvents true if there were Added Switch Events.
Ray Milkey269ffb92014-04-03 14:43:30 -0700463 * @param hasAddedPortEvents true if there were Added Port Events.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800464 */
465 private void applyReorderedEvents(boolean hasAddedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700466 boolean hasAddedPortEvents) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700467 if (!(hasAddedSwitchEvents || hasAddedPortEvents)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700468 return; // Nothing to do
Ray Milkeyb29e6262014-04-09 16:02:14 -0700469 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800470
Ray Milkey269ffb92014-04-03 14:43:30 -0700471 //
472 // Try to apply the reordered events.
473 //
474 // NOTE: For simplicity we try to apply all events of a particular
475 // type if any "parent" type event was processed:
476 // - Apply reordered Port Events if Switches were added
477 // - Apply reordered Link and Device Events if Switches or Ports
478 // were added
479 //
adminbc181552014-02-21 18:36:42 -0800480
Ray Milkey269ffb92014-04-03 14:43:30 -0700481 //
482 // Apply reordered Port Events if Switches were added
483 //
484 if (hasAddedSwitchEvents) {
485 Map<ByteBuffer, PortEvent> portEvents = reorderedAddedPortEvents;
486 reorderedAddedPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700487 for (PortEvent portEvent : portEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700488 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700489 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700490 }
491 //
492 // Apply reordered Link and Device Events if Switches or Ports
493 // were added.
494 //
495 Map<ByteBuffer, LinkEvent> linkEvents = reorderedAddedLinkEvents;
496 reorderedAddedLinkEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700497 for (LinkEvent linkEvent : linkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700498 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700499 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700500 //
501 Map<ByteBuffer, DeviceEvent> deviceEvents = reorderedAddedDeviceEvents;
502 reorderedAddedDeviceEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700503 for (DeviceEvent deviceEvent : deviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700504 addDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700505 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800506 }
507
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800508 /**
509 * Switch discovered event.
510 *
511 * @param switchEvent the switch event.
Ray Milkey269ffb92014-04-03 14:43:30 -0700512 * @param portEvents the corresponding port events for the switch.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800513 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800514 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800515 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
Ray Milkey269ffb92014-04-03 14:43:30 -0700516 Collection<PortEvent> portEvents) {
517 if (datastore.addSwitch(switchEvent, portEvents)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700518 log.debug("Sending add switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700519 // Send out notification
520 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
521 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800522
Ray Milkey269ffb92014-04-03 14:43:30 -0700523 // Send out notification for each port
524 for (PortEvent portEvent : portEvents) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700525 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700526 topologyEvent = new TopologyEvent(portEvent);
527 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
528 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800529
Ray Milkey269ffb92014-04-03 14:43:30 -0700530 //
531 // Keep track of the added ports
532 //
533 // Get the old Port Events
534 Map<ByteBuffer, PortEvent> oldPortEvents =
535 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700536 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700537 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700538 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800539
Ray Milkey269ffb92014-04-03 14:43:30 -0700540 // Store the new Port Events in the local cache
541 Map<ByteBuffer, PortEvent> newPortEvents = new HashMap<>();
542 for (PortEvent portEvent : portEvents) {
543 ByteBuffer id = portEvent.getIDasByteBuffer();
544 newPortEvents.put(id, portEvent);
545 }
546 discoveredAddedPortEvents.put(switchEvent.getDpid(),
547 newPortEvents);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800548
Ray Milkey269ffb92014-04-03 14:43:30 -0700549 //
550 // Extract the removed ports
551 //
552 List<PortEvent> removedPortEvents = new LinkedList<>();
553 for (Map.Entry<ByteBuffer, PortEvent> entry : oldPortEvents.entrySet()) {
554 ByteBuffer key = entry.getKey();
555 PortEvent portEvent = entry.getValue();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700556 if (!newPortEvents.containsKey(key)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700557 removedPortEvents.add(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700558 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700559 }
560
561 // Cleanup old removed ports
Ray Milkeyb29e6262014-04-09 16:02:14 -0700562 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700563 removePortDiscoveryEvent(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700564 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700565 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800566 }
567
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800568 /**
569 * Switch removed event.
570 *
571 * @param switchEvent the switch event.
572 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800573 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800574 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700575 // Get the old Port Events
576 Map<ByteBuffer, PortEvent> oldPortEvents =
577 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700578 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700579 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700580 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800581
Ray Milkey269ffb92014-04-03 14:43:30 -0700582 if (datastore.deactivateSwitch(switchEvent, oldPortEvents.values())) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700583 log.debug("Sending remove switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700584 // Send out notification
585 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800586
Ray Milkey269ffb92014-04-03 14:43:30 -0700587 //
588 // Send out notification for each port.
589 //
590 // NOTE: We don't use removePortDiscoveryEvent() for the cleanup,
591 // because it will attempt to remove the port from the database,
592 // and the deactiveSwitch() call above already removed all ports.
593 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700594 for (PortEvent portEvent : oldPortEvents.values()) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700595 log.debug("Sending remove port:", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700596 eventChannel.removeEntry(portEvent.getID());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700597 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700598 discoveredAddedPortEvents.remove(switchEvent.getDpid());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800599
Ray Milkey269ffb92014-04-03 14:43:30 -0700600 // Cleanup for each link
601 Map<ByteBuffer, LinkEvent> oldLinkEvents =
602 discoveredAddedLinkEvents.get(switchEvent.getDpid());
603 if (oldLinkEvents != null) {
604 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
605 removeLinkDiscoveryEvent(linkEvent);
606 }
607 discoveredAddedLinkEvents.remove(switchEvent.getDpid());
608 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800609
Ray Milkey269ffb92014-04-03 14:43:30 -0700610 // Cleanup for each device
611 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
612 discoveredAddedDeviceEvents.get(switchEvent.getDpid());
613 if (oldDeviceEvents != null) {
614 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
615 removeDeviceDiscoveryEvent(deviceEvent);
616 }
617 discoveredAddedDeviceEvents.remove(switchEvent.getDpid());
618 }
619 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800620 }
621
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800622 /**
623 * Port discovered event.
624 *
625 * @param portEvent the port event.
626 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800627 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800628 public void putPortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700629 if (datastore.addPort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700630 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700631 // Send out notification
632 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
633 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800634
Ray Milkey269ffb92014-04-03 14:43:30 -0700635 // Store the new Port Event in the local cache
636 Map<ByteBuffer, PortEvent> oldPortEvents =
637 discoveredAddedPortEvents.get(portEvent.getDpid());
638 if (oldPortEvents == null) {
639 oldPortEvents = new HashMap<>();
640 discoveredAddedPortEvents.put(portEvent.getDpid(),
641 oldPortEvents);
642 }
643 ByteBuffer id = portEvent.getIDasByteBuffer();
644 oldPortEvents.put(id, portEvent);
645 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800646 }
647
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800648 /**
649 * Port removed event.
650 *
651 * @param portEvent the port event.
652 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800653 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800654 public void removePortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700655 if (datastore.deactivatePort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700656 log.debug("Sending remove port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700657 // Send out notification
658 eventChannel.removeEntry(portEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800659
Ray Milkey269ffb92014-04-03 14:43:30 -0700660 // Cleanup the Port Event from the local cache
661 Map<ByteBuffer, PortEvent> oldPortEvents =
662 discoveredAddedPortEvents.get(portEvent.getDpid());
663 if (oldPortEvents != null) {
664 ByteBuffer id = portEvent.getIDasByteBuffer();
665 oldPortEvents.remove(id);
666 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800667
Ray Milkey269ffb92014-04-03 14:43:30 -0700668 // Cleanup for the incoming link
669 Map<ByteBuffer, LinkEvent> oldLinkEvents =
670 discoveredAddedLinkEvents.get(portEvent.getDpid());
671 if (oldLinkEvents != null) {
672 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
673 if (linkEvent.getDst().equals(portEvent.id)) {
674 removeLinkDiscoveryEvent(linkEvent);
675 // XXX If we change our model to allow multiple Link on
676 // a Port, this loop must be fixed to allow continuing.
677 break;
678 }
679 }
680 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800681
Ray Milkey269ffb92014-04-03 14:43:30 -0700682 // Cleanup for the connected devices
683 // TODO: The implementation below is probably wrong
684 List<DeviceEvent> removedDeviceEvents = new LinkedList<>();
685 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
686 discoveredAddedDeviceEvents.get(portEvent.getDpid());
687 if (oldDeviceEvents != null) {
688 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
689 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
690 if (swp.equals(portEvent.id)) {
691 removedDeviceEvents.add(deviceEvent);
692 }
693 }
694 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700695 for (DeviceEvent deviceEvent : removedDeviceEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700696 removeDeviceDiscoveryEvent(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700697 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700698 }
699 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800700 }
701
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800702 /**
703 * Link discovered event.
704 *
705 * @param linkEvent the link event.
706 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800707 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800708 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700709 if (datastore.addLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700710 log.debug("Sending add link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700711 // Send out notification
712 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
713 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800714
Ray Milkey269ffb92014-04-03 14:43:30 -0700715 // Store the new Link Event in the local cache
716 Map<ByteBuffer, LinkEvent> oldLinkEvents =
717 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
718 if (oldLinkEvents == null) {
719 oldLinkEvents = new HashMap<>();
720 discoveredAddedLinkEvents.put(linkEvent.getDst().getDpid(),
721 oldLinkEvents);
722 }
723 ByteBuffer id = linkEvent.getIDasByteBuffer();
724 oldLinkEvents.put(id, linkEvent);
725 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800726 }
727
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800728 /**
729 * Link removed event.
730 *
731 * @param linkEvent the link event.
732 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800733 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800734 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700735 if (datastore.removeLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700736 log.debug("Sending remove link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700737 // Send out notification
738 eventChannel.removeEntry(linkEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800739
Ray Milkey269ffb92014-04-03 14:43:30 -0700740 // Cleanup the Link Event from the local cache
741 Map<ByteBuffer, LinkEvent> oldLinkEvents =
742 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
743 if (oldLinkEvents != null) {
744 ByteBuffer id = linkEvent.getIDasByteBuffer();
745 oldLinkEvents.remove(id);
746 }
747 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800748 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800749
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800750 /**
751 * Device discovered event.
752 *
753 * @param deviceEvent the device event.
754 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800755 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800756 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700757 if (datastore.addDevice(deviceEvent)) {
758 // Send out notification
759 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
760 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700761 log.debug("Put the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -0700762
763 // Store the new Device Event in the local cache
764 // TODO: The implementation below is probably wrong
765 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
766 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
767 discoveredAddedDeviceEvents.get(swp.getDpid());
768 if (oldDeviceEvents == null) {
769 oldDeviceEvents = new HashMap<>();
770 discoveredAddedDeviceEvents.put(swp.getDpid(),
771 oldDeviceEvents);
772 }
773 ByteBuffer id = deviceEvent.getIDasByteBuffer();
774 oldDeviceEvents.put(id, deviceEvent);
775 }
776 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800777 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800778
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800779 /**
780 * Device removed event.
781 *
782 * @param deviceEvent the device event.
783 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800784 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800785 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700786 if (datastore.removeDevice(deviceEvent)) {
787 // Send out notification
788 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Harte37e4e22014-05-13 19:12:02 -0700789 log.debug("Remove the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800790
Ray Milkey269ffb92014-04-03 14:43:30 -0700791 // Cleanup the Device Event from the local cache
792 // TODO: The implementation below is probably wrong
793 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
794 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
795 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
796 discoveredAddedDeviceEvents.get(swp.getDpid());
797 if (oldDeviceEvents != null) {
798 oldDeviceEvents.remove(id);
799 }
800 }
801 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800802 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800803
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800804 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700805 * Add a switch to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800806 *
807 * @param switchEvent the Switch Event with the switch to add.
808 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800809 private void addSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700810 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700811 if (sw == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700812 sw = new SwitchImpl(topology, switchEvent.getDpid());
813 topology.putSwitch(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700814 } else {
815 // TODO: Update the switch attributes
816 // TODO: Nothing to do for now
Ray Milkey1aa71f82014-04-08 16:23:24 -0700817 log.debug("Update switch attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700818 }
819 apiAddedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800820 }
821
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800822 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700823 * Remove a switch from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800824 *
825 * @param switchEvent the Switch Event with the switch to remove.
826 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800827 private void removeSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700828 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700829 if (sw == null) {
830 log.warn("Switch {} already removed, ignoring", switchEvent);
831 return;
832 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800833
Ray Milkey269ffb92014-04-03 14:43:30 -0700834 //
835 // Remove all Ports on the Switch
836 //
837 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
838 for (Port port : sw.getPorts()) {
839 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
840 port, switchEvent);
841 PortEvent portEvent = new PortEvent(port.getDpid(),
842 port.getNumber());
843 portsToRemove.add(portEvent);
844 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700845 for (PortEvent portEvent : portsToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700846 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700847 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800848
Jonathan Harte37e4e22014-05-13 19:12:02 -0700849 topology.removeSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700850 apiRemovedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800851 }
852
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800853 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700854 * Add a port to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800855 *
856 * @param portEvent the Port Event with the port to add.
857 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800858 private void addPort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700859 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700860 if (sw == null) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700861 log.debug("{} reordered because switch is null", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700862 // Reordered event: delay the event in local cache
863 ByteBuffer id = portEvent.getIDasByteBuffer();
864 reorderedAddedPortEvents.put(id, portEvent);
865 return;
866 }
867 SwitchImpl switchImpl = getSwitchImpl(sw);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800868
Ray Milkey269ffb92014-04-03 14:43:30 -0700869 Port port = sw.getPort(portEvent.getNumber());
870 if (port == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700871 port = new PortImpl(topology, sw, portEvent.getNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -0700872 switchImpl.addPort(port);
873 } else {
874 // TODO: Update the port attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700875 log.debug("Update port attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700876 }
877 apiAddedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800878 }
879
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800880 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700881 * Remove a port from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800882 *
883 * @param portEvent the Port Event with the port to remove.
884 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800885 private void removePort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700886 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700887 if (sw == null) {
888 log.warn("Parent Switch for Port {} already removed, ignoring",
889 portEvent);
890 return;
891 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800892
Ray Milkey269ffb92014-04-03 14:43:30 -0700893 Port port = sw.getPort(portEvent.getNumber());
894 if (port == null) {
895 log.warn("Port {} already removed, ignoring", portEvent);
896 return;
897 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800898
Ray Milkey269ffb92014-04-03 14:43:30 -0700899 //
900 // Remove all Devices attached to the Port
901 //
902 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
903 for (Device device : port.getDevices()) {
904 log.debug("Removing Device {} on Port {}", device, portEvent);
905 DeviceEvent deviceEvent = new DeviceEvent(device.getMacAddress());
906 SwitchPort switchPort = new SwitchPort(port.getSwitch().getDpid(),
907 port.getNumber());
908 deviceEvent.addAttachmentPoint(switchPort);
909 devicesToRemove.add(deviceEvent);
910 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700911 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700912 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700913 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800914
Ray Milkey269ffb92014-04-03 14:43:30 -0700915 //
916 // Remove all Links connected to the Port
917 //
918 Set<Link> links = new HashSet<>();
919 links.add(port.getOutgoingLink());
920 links.add(port.getIncomingLink());
921 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
922 for (Link link : links) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700923 if (link == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700924 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700925 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700926 log.debug("Removing Link {} on Port {}", link, portEvent);
927 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
928 link.getSrcPort().getNumber(),
929 link.getDstSwitch().getDpid(),
930 link.getDstPort().getNumber());
931 linksToRemove.add(linkEvent);
932 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700933 for (LinkEvent linkEvent : linksToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700934 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700935 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800936
Ray Milkey269ffb92014-04-03 14:43:30 -0700937 // Remove the Port from the Switch
938 SwitchImpl switchImpl = getSwitchImpl(sw);
939 switchImpl.removePort(port);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800940
Ray Milkey269ffb92014-04-03 14:43:30 -0700941 apiRemovedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800942 }
943
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800944 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700945 * Add a link to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800946 *
947 * @param linkEvent the Link Event with the link to add.
948 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800949 private void addLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700950 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700951 linkEvent.getSrc().number);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700952 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700953 linkEvent.getDst().number);
954 if ((srcPort == null) || (dstPort == null)) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700955 log.debug("{} reordered because {} port is null", linkEvent,
956 (srcPort == null) ? "src" : "dst");
957
Ray Milkey269ffb92014-04-03 14:43:30 -0700958 // Reordered event: delay the event in local cache
959 ByteBuffer id = linkEvent.getIDasByteBuffer();
960 reorderedAddedLinkEvents.put(id, linkEvent);
961 return;
962 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800963
Ray Milkey269ffb92014-04-03 14:43:30 -0700964 // Get the Link instance from the Destination Port Incoming Link
965 Link link = dstPort.getIncomingLink();
966 assert (link == srcPort.getOutgoingLink());
967 if (link == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700968 link = new LinkImpl(topology, srcPort, dstPort);
969 topology.putLink(link);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800970
Ray Milkey269ffb92014-04-03 14:43:30 -0700971 // Remove all Devices attached to the Ports
972 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
973 ArrayList<Port> ports = new ArrayList<>();
974 ports.add(srcPort);
975 ports.add(dstPort);
976 for (Port port : ports) {
977 for (Device device : port.getDevices()) {
978 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
979 device, port, linkEvent);
980 DeviceEvent deviceEvent =
981 new DeviceEvent(device.getMacAddress());
982 SwitchPort switchPort =
983 new SwitchPort(port.getSwitch().getDpid(),
984 port.getNumber());
985 deviceEvent.addAttachmentPoint(switchPort);
986 devicesToRemove.add(deviceEvent);
987 }
988 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700989 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700990 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700991 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700992 } else {
993 // TODO: Update the link attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700994 log.debug("Update link attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700995 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800996
Ray Milkey269ffb92014-04-03 14:43:30 -0700997 apiAddedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800998 }
999
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001000 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001001 * Remove a link from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001002 *
1003 * @param linkEvent the Link Event with the link to remove.
1004 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001005 private void removeLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001006 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -07001007 linkEvent.getSrc().number);
1008 if (srcPort == null) {
1009 log.warn("Src Port for Link {} already removed, ignoring",
1010 linkEvent);
1011 return;
1012 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001013
Jonathan Harte37e4e22014-05-13 19:12:02 -07001014 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -07001015 linkEvent.getDst().number);
1016 if (dstPort == null) {
1017 log.warn("Dst Port for Link {} already removed, ignoring",
1018 linkEvent);
1019 return;
1020 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001021
Ray Milkey269ffb92014-04-03 14:43:30 -07001022 //
1023 // Remove the Link instance from the Destination Port Incoming Link
1024 // and the Source Port Outgoing Link.
1025 //
1026 Link link = dstPort.getIncomingLink();
1027 if (link == null) {
1028 log.warn("Link {} already removed on destination Port", linkEvent);
1029 }
1030 link = srcPort.getOutgoingLink();
1031 if (link == null) {
1032 log.warn("Link {} already removed on src Port", linkEvent);
1033 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001034
1035 // TODO should we check that we get the same link from each port?
1036 if (link != null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001037 topology.removeLink(link);
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001038 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001039
Ray Milkey269ffb92014-04-03 14:43:30 -07001040 apiRemovedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001041 }
1042
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001043 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001044 * Add a device to the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001045 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001046 * TODO: Device-related work is incomplete.
1047 * TODO: Eventually, we might need to consider reordering
1048 * or addLink() and addDevice() events on the same port.
1049 *
1050 * @param deviceEvent the Device Event with the device to add.
1051 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001052 private void addDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001053 log.debug("Adding a device to the topology with mac {}", deviceEvent.getMac());
1054 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001055
Ray Milkey269ffb92014-04-03 14:43:30 -07001056 if (device == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001057 log.debug("Existing device was not found in the Topology: Adding new device: mac {}", deviceEvent.getMac());
1058 device = new DeviceImpl(topology, deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001059 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001060
Ray Milkey269ffb92014-04-03 14:43:30 -07001061 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001062
Ray Milkey269ffb92014-04-03 14:43:30 -07001063 // Process each attachment point
1064 boolean attachmentFound = false;
1065 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1066 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001067 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001068 if (port == null) {
1069 // Reordered event: delay the event in local cache
1070 ByteBuffer id = deviceEvent.getIDasByteBuffer();
1071 reorderedAddedDeviceEvents.put(id, deviceEvent);
1072 continue;
1073 }
1074 // Attached Ports must not have Link
1075 if (port.getOutgoingLink() != null ||
1076 port.getIncomingLink() != null) {
1077 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
1078 port.getOutgoingLink(),
1079 port.getIncomingLink());
1080 continue;
1081 }
1082
1083 // Add Device <-> Port attachment
1084 PortImpl portImpl = getPortImpl(port);
1085 portImpl.addDevice(device);
1086 deviceImpl.addAttachmentPoint(port);
1087 attachmentFound = true;
1088 }
1089
TeruU5d2c9392014-06-09 20:02:02 -07001090 deviceImpl.setLastSeenTime(deviceEvent.getLastSeenTime());
1091
Jonathan Harte37e4e22014-05-13 19:12:02 -07001092 // Update the device in the topology
Ray Milkey269ffb92014-04-03 14:43:30 -07001093 if (attachmentFound) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001094 log.debug("Storing the device info into the Topology: mac {}", deviceEvent.getMac());
1095 topology.putDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001096 apiAddedDeviceEvents.add(deviceEvent);
1097 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001098 }
1099
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001100 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001101 * Remove a device from the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001102 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001103 * TODO: Device-related work is incomplete.
1104 *
1105 * @param deviceEvent the Device Event with the device to remove.
1106 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001107 private void removeDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001108 log.debug("Removing a device to the topology: mac {}", deviceEvent.getMac());
1109 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001110 if (device == null) {
1111 log.warn("Device {} already removed, ignoring", deviceEvent);
1112 return;
1113 }
1114 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001115
Ray Milkey269ffb92014-04-03 14:43:30 -07001116 // Process each attachment point
1117 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1118 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001119 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001120 if (port == null) {
1121 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
1122 continue;
1123 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001124
Ray Milkey269ffb92014-04-03 14:43:30 -07001125 // Remove Device <-> Port attachment
1126 PortImpl portImpl = getPortImpl(port);
1127 portImpl.removeDevice(device);
1128 deviceImpl.removeAttachmentPoint(port);
1129 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001130
Jonathan Harte37e4e22014-05-13 19:12:02 -07001131 log.debug("Removing the device info into the Topology: mac {}", deviceEvent.getMac());
1132 topology.removeDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001133 apiRemovedDeviceEvents.add(deviceEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001134 }
Jonathan Hart22eb9882014-02-11 15:52:59 -08001135
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001136 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001137 * Get the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001138 *
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001139 * @param sw the Switch to cast.
1140 * @return the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001141 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001142 private SwitchImpl getSwitchImpl(Switch sw) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001143 if (sw instanceof SwitchImpl) {
1144 return (SwitchImpl) sw;
1145 }
1146 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001147 }
1148
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001149 /**
1150 * Get the PortImpl-casted port implementation.
1151 *
1152 * @param port the Port to cast.
1153 * @return the PortImpl-casted port implementation.
1154 */
1155 private PortImpl getPortImpl(Port port) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001156 if (port instanceof PortImpl) {
1157 return (PortImpl) port;
1158 }
1159 throw new ClassCastException("PortImpl expected, but found: " + port);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001160 }
1161
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001162 /**
1163 * Get the LinkImpl-casted link implementation.
1164 *
1165 * @param link the Link to cast.
1166 * @return the LinkImpl-casted link implementation.
1167 */
1168 private LinkImpl getLinkImpl(Link link) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001169 if (link instanceof LinkImpl) {
1170 return (LinkImpl) link;
1171 }
1172 throw new ClassCastException("LinkImpl expected, but found: " + link);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001173 }
1174
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001175 /**
1176 * Get the DeviceImpl-casted device implementation.
1177 *
1178 * @param device the Device to cast.
1179 * @return the DeviceImpl-casted device implementation.
1180 */
1181 private DeviceImpl getDeviceImpl(Device device) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001182 if (device instanceof DeviceImpl) {
1183 return (DeviceImpl) device;
1184 }
1185 throw new ClassCastException("DeviceImpl expected, but found: " + device);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001186 }
1187
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001188 /**
1189 * Read the whole topology from the database.
1190 *
1191 * @return a collection of EventEntry-encapsulated Topology Events for
1192 * the whole topology.
1193 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001194 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
Ray Milkey269ffb92014-04-03 14:43:30 -07001195 Collection<EventEntry<TopologyEvent>> collection =
1196 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001197
Ray Milkey269ffb92014-04-03 14:43:30 -07001198 // XXX May need to clear whole topology first, depending on
1199 // how we initially subscribe to replication events
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001200
Ray Milkey269ffb92014-04-03 14:43:30 -07001201 // Add all active switches
1202 for (KVSwitch sw : KVSwitch.getAllSwitches()) {
1203 if (sw.getStatus() != KVSwitch.STATUS.ACTIVE) {
1204 continue;
1205 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001206
Ray Milkey269ffb92014-04-03 14:43:30 -07001207 SwitchEvent switchEvent = new SwitchEvent(sw.getDpid());
1208 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
1209 EventEntry<TopologyEvent> eventEntry =
1210 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1211 topologyEvent);
1212 collection.add(eventEntry);
1213 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001214
Ray Milkey269ffb92014-04-03 14:43:30 -07001215 // Add all active ports
1216 for (KVPort p : KVPort.getAllPorts()) {
1217 if (p.getStatus() != KVPort.STATUS.ACTIVE) {
1218 continue;
1219 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001220
Ray Milkey269ffb92014-04-03 14:43:30 -07001221 PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
1222 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
1223 EventEntry<TopologyEvent> eventEntry =
1224 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1225 topologyEvent);
1226 collection.add(eventEntry);
1227 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001228
TeruU28adcc32014-04-15 17:57:35 -07001229 for (KVDevice d : KVDevice.getAllDevices()) {
1230 DeviceEvent devEvent = new DeviceEvent(MACAddress.valueOf(d.getMac()));
1231 for (byte[] portId : d.getAllPortIds()) {
Jonathan Hartc00f5c22014-06-10 15:14:40 -07001232 devEvent.addAttachmentPoint(
1233 new SwitchPort(KVPort.getDpidFromKey(portId),
1234 KVPort.getNumberFromKey(portId)));
TeruU28adcc32014-04-15 17:57:35 -07001235 }
1236 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001237
Ray Milkey269ffb92014-04-03 14:43:30 -07001238 for (KVLink l : KVLink.getAllLinks()) {
1239 LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
1240 l.getSrc().number,
1241 l.getDst().dpid,
1242 l.getDst().number);
1243 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
1244 EventEntry<TopologyEvent> eventEntry =
1245 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1246 topologyEvent);
1247 collection.add(eventEntry);
1248 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001249
Ray Milkey269ffb92014-04-03 14:43:30 -07001250 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001251 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001252}