blob: f5929d1f1e269e711630f4a944362c21319e0ca5 [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 //
Yuta HIGUCHI703696c2014-06-25 20:36:45 -070091
92 private List<SwitchEvent> apiAddedSwitchEvents = new LinkedList<>();
93 private List<SwitchEvent> apiRemovedSwitchEvents = new LinkedList<>();
94 private List<PortEvent> apiAddedPortEvents = new LinkedList<>();
95 private List<PortEvent> apiRemovedPortEvents = new LinkedList<>();
96 private List<LinkEvent> apiAddedLinkEvents = new LinkedList<>();
97 private List<LinkEvent> apiRemovedLinkEvents = new LinkedList<>();
98 private List<DeviceEvent> apiAddedDeviceEvents = new LinkedList<>();
99 private List<DeviceEvent> apiRemovedDeviceEvents = new LinkedList<>();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800100
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800101 /**
102 * Constructor.
103 *
Jonathan Harte37e4e22014-05-13 19:12:02 -0700104 * @param registryService the Registry Service to use.
105 * @param topologyListeners the collection of topology listeners to use.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800106 */
107 public TopologyManager(IControllerRegistryService registryService,
Jonathan Harte37e4e22014-05-13 19:12:02 -0700108 CopyOnWriteArrayList<ITopologyListener> topologyListeners) {
109 datastore = new TopologyDatastore();
Ray Milkey269ffb92014-04-03 14:43:30 -0700110 this.registryService = registryService;
Jonathan Harte37e4e22014-05-13 19:12:02 -0700111 this.topologyListeners = topologyListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800112 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800113
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800114 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700115 * Get the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800116 *
Jonathan Harte37e4e22014-05-13 19:12:02 -0700117 * @return the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800118 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700119 Topology getTopology() {
120 return topology;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -0800121 }
122
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800123 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800124 * Event handler class.
125 */
126 private class EventHandler extends Thread implements
Ray Milkey269ffb92014-04-03 14:43:30 -0700127 IEventChannelListener<byte[], TopologyEvent> {
128 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
129 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800130
Ray Milkey269ffb92014-04-03 14:43:30 -0700131 /**
132 * Startup processing.
133 */
134 private void startup() {
135 //
136 // TODO: Read all state from the database:
137 //
138 // Collection<EventEntry<TopologyEvent>> collection =
139 // readWholeTopologyFromDB();
140 //
141 // For now, as a shortcut we read it from the datagrid
142 //
Ray Milkey5df613b2014-04-15 10:50:56 -0700143 Collection<TopologyEvent> allTopologyEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700144 eventChannel.getAllEntries();
145 Collection<EventEntry<TopologyEvent>> collection =
146 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800147
Ray Milkey5df613b2014-04-15 10:50:56 -0700148 for (TopologyEvent topologyEvent : allTopologyEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700149 EventEntry<TopologyEvent> eventEntry =
150 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
151 topologyEvent);
152 collection.add(eventEntry);
153 }
154 processEvents(collection);
155 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800156
Ray Milkey269ffb92014-04-03 14:43:30 -0700157 /**
158 * Run the thread.
159 */
160 @Override
161 public void run() {
162 Collection<EventEntry<TopologyEvent>> collection =
163 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800164
Ray Milkey269ffb92014-04-03 14:43:30 -0700165 this.setName("TopologyManager.EventHandler " + this.getId());
166 startup();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800167
Ray Milkey269ffb92014-04-03 14:43:30 -0700168 //
169 // The main loop
170 //
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700171 while (true) {
172 try {
173 EventEntry<TopologyEvent> eventEntry =
174 topologyEvents.take();
Ray Milkey269ffb92014-04-03 14:43:30 -0700175 collection.add(eventEntry);
176 topologyEvents.drainTo(collection);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800177
Ray Milkey269ffb92014-04-03 14:43:30 -0700178 processEvents(collection);
179 collection.clear();
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700180 } catch (Exception exception) {
181 log.debug("Exception processing Topology Events: ",
182 exception);
Ray Milkey269ffb92014-04-03 14:43:30 -0700183 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700184 }
185 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800186
Ray Milkey269ffb92014-04-03 14:43:30 -0700187 /**
188 * Process all topology events.
189 *
190 * @param events the events to process.
191 */
192 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
193 // Local state for computing the final set of events
194 Map<ByteBuffer, SwitchEvent> addedSwitchEvents = new HashMap<>();
195 Map<ByteBuffer, SwitchEvent> removedSwitchEvents = new HashMap<>();
196 Map<ByteBuffer, PortEvent> addedPortEvents = new HashMap<>();
197 Map<ByteBuffer, PortEvent> removedPortEvents = new HashMap<>();
198 Map<ByteBuffer, LinkEvent> addedLinkEvents = new HashMap<>();
199 Map<ByteBuffer, LinkEvent> removedLinkEvents = new HashMap<>();
200 Map<ByteBuffer, DeviceEvent> addedDeviceEvents = new HashMap<>();
201 Map<ByteBuffer, DeviceEvent> removedDeviceEvents = new HashMap<>();
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800202
Ray Milkey269ffb92014-04-03 14:43:30 -0700203 //
204 // Classify and suppress matching events
205 //
206 for (EventEntry<TopologyEvent> event : events) {
207 TopologyEvent topologyEvent = event.eventData();
208 SwitchEvent switchEvent = topologyEvent.switchEvent;
209 PortEvent portEvent = topologyEvent.portEvent;
210 LinkEvent linkEvent = topologyEvent.linkEvent;
211 DeviceEvent deviceEvent = topologyEvent.deviceEvent;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800212
Ray Milkey269ffb92014-04-03 14:43:30 -0700213 //
214 // Extract the events
215 //
216 switch (event.eventType()) {
217 case ENTRY_ADD:
218 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
219 if (switchEvent != null) {
220 ByteBuffer id = switchEvent.getIDasByteBuffer();
221 addedSwitchEvents.put(id, switchEvent);
222 removedSwitchEvents.remove(id);
223 // Switch Events are not affected by event reordering
224 }
225 if (portEvent != null) {
226 ByteBuffer id = portEvent.getIDasByteBuffer();
227 addedPortEvents.put(id, portEvent);
228 removedPortEvents.remove(id);
229 reorderedAddedPortEvents.remove(id);
230 }
231 if (linkEvent != null) {
232 ByteBuffer id = linkEvent.getIDasByteBuffer();
233 addedLinkEvents.put(id, linkEvent);
234 removedLinkEvents.remove(id);
235 reorderedAddedLinkEvents.remove(id);
236 }
237 if (deviceEvent != null) {
238 ByteBuffer id = deviceEvent.getIDasByteBuffer();
239 addedDeviceEvents.put(id, deviceEvent);
240 removedDeviceEvents.remove(id);
241 reorderedAddedDeviceEvents.remove(id);
242 }
243 break;
244 case ENTRY_REMOVE:
245 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
246 if (switchEvent != null) {
247 ByteBuffer id = switchEvent.getIDasByteBuffer();
248 addedSwitchEvents.remove(id);
249 removedSwitchEvents.put(id, switchEvent);
250 // Switch Events are not affected by event reordering
251 }
252 if (portEvent != null) {
253 ByteBuffer id = portEvent.getIDasByteBuffer();
254 addedPortEvents.remove(id);
255 removedPortEvents.put(id, portEvent);
256 reorderedAddedPortEvents.remove(id);
257 }
258 if (linkEvent != null) {
259 ByteBuffer id = linkEvent.getIDasByteBuffer();
260 addedLinkEvents.remove(id);
261 removedLinkEvents.put(id, linkEvent);
262 reorderedAddedLinkEvents.remove(id);
263 }
264 if (deviceEvent != null) {
265 ByteBuffer id = deviceEvent.getIDasByteBuffer();
266 addedDeviceEvents.remove(id);
267 removedDeviceEvents.put(id, deviceEvent);
268 reorderedAddedDeviceEvents.remove(id);
269 }
270 break;
Ray Milkey0b122ed2014-04-14 10:06:03 -0700271 default:
272 log.error("Unknown topology event {}",
273 event.eventType());
Ray Milkey269ffb92014-04-03 14:43:30 -0700274 }
275 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800276
Ray Milkey269ffb92014-04-03 14:43:30 -0700277 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700278 // Lock the topology while it is modified
Ray Milkey269ffb92014-04-03 14:43:30 -0700279 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700280 topology.acquireWriteLock();
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800281
Ray Milkey269ffb92014-04-03 14:43:30 -0700282 try {
283 //
284 // Apply the classified events.
285 //
286 // Apply the "add" events in the proper order:
287 // switch, port, link, device
288 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700289 for (SwitchEvent switchEvent : addedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700290 addSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700291 }
292 for (PortEvent portEvent : addedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700293 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700294 }
295 for (LinkEvent linkEvent : addedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700296 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700297 }
298 for (DeviceEvent deviceEvent : addedDeviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700299 addDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700300 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700301 //
302 // Apply the "remove" events in the reverse order:
303 // device, link, port, switch
304 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700305 for (DeviceEvent deviceEvent : removedDeviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700306 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700307 }
308 for (LinkEvent linkEvent : removedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700309 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700310 }
311 for (PortEvent portEvent : removedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700312 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700313 }
314 for (SwitchEvent switchEvent : removedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700315 removeSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700316 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800317
Ray Milkey269ffb92014-04-03 14:43:30 -0700318 //
319 // Apply reordered events
320 //
321 applyReorderedEvents(!addedSwitchEvents.isEmpty(),
322 !addedPortEvents.isEmpty());
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800323
Ray Milkey269ffb92014-04-03 14:43:30 -0700324 } finally {
325 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700326 // Topology modifications completed: Release the lock
Ray Milkey269ffb92014-04-03 14:43:30 -0700327 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700328 topology.releaseWriteLock();
Ray Milkey269ffb92014-04-03 14:43:30 -0700329 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800330
Ray Milkey269ffb92014-04-03 14:43:30 -0700331 //
332 // Dispatch the Topology Notification Events to the applications
333 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700334 dispatchTopologyEvents();
Ray Milkey269ffb92014-04-03 14:43:30 -0700335 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800336
Ray Milkey269ffb92014-04-03 14:43:30 -0700337 /**
338 * Receive a notification that an entry is added.
339 *
340 * @param value the value for the entry.
341 */
342 @Override
343 public void entryAdded(TopologyEvent value) {
344 EventEntry<TopologyEvent> eventEntry =
345 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
346 value);
347 topologyEvents.add(eventEntry);
348 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800349
Ray Milkey269ffb92014-04-03 14:43:30 -0700350 /**
351 * Receive a notification that an entry is removed.
352 *
353 * @param value the value for the entry.
354 */
355 @Override
356 public void entryRemoved(TopologyEvent value) {
357 EventEntry<TopologyEvent> eventEntry =
358 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
359 value);
360 topologyEvents.add(eventEntry);
361 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800362
Ray Milkey269ffb92014-04-03 14:43:30 -0700363 /**
364 * Receive a notification that an entry is updated.
365 *
366 * @param value the value for the entry.
367 */
368 @Override
369 public void entryUpdated(TopologyEvent value) {
370 // NOTE: The ADD and UPDATE events are processed in same way
371 entryAdded(value);
372 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800373 }
374
375 /**
376 * Startup processing.
377 *
378 * @param datagridService the datagrid service to use.
379 */
380 void startup(IDatagridService datagridService) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700381 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
382 eventHandler,
383 byte[].class,
384 TopologyEvent.class);
385 eventHandler.start();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800386 }
387
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800388 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700389 * Dispatch Topology Events to the listeners.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800390 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700391 private void dispatchTopologyEvents() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700392 if (apiAddedSwitchEvents.isEmpty() &&
393 apiRemovedSwitchEvents.isEmpty() &&
394 apiAddedPortEvents.isEmpty() &&
395 apiRemovedPortEvents.isEmpty() &&
396 apiAddedLinkEvents.isEmpty() &&
397 apiRemovedLinkEvents.isEmpty() &&
398 apiAddedDeviceEvents.isEmpty() &&
399 apiRemovedDeviceEvents.isEmpty()) {
400 return; // No events to dispatch
401 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800402
Ray Milkey269ffb92014-04-03 14:43:30 -0700403 if (log.isDebugEnabled()) {
404 //
405 // Debug statements
406 // TODO: Those statements should be removed in the future
407 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700408 for (SwitchEvent switchEvent : apiAddedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700409 log.debug("Dispatch Topology Event: ADDED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700410 }
411 for (SwitchEvent switchEvent : apiRemovedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700412 log.debug("Dispatch Topology Event: REMOVED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700413 }
414 for (PortEvent portEvent : apiAddedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700415 log.debug("Dispatch Topology Event: ADDED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700416 }
417 for (PortEvent portEvent : apiRemovedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700418 log.debug("Dispatch Topology Event: REMOVED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700419 }
420 for (LinkEvent linkEvent : apiAddedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700421 log.debug("Dispatch Topology Event: ADDED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700422 }
423 for (LinkEvent linkEvent : apiRemovedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700424 log.debug("Dispatch Topology Event: REMOVED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700425 }
426 for (DeviceEvent deviceEvent : apiAddedDeviceEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700427 log.debug("Dispatch Topology Event: ADDED {}", deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700428 }
429 for (DeviceEvent deviceEvent : apiRemovedDeviceEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700430 log.debug("Dispatch Topology Event: REMOVED {}", deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700431 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700432 }
adminbc181552014-02-21 18:36:42 -0800433
Ray Milkey269ffb92014-04-03 14:43:30 -0700434 // Deliver the events
Jonathan Harte37e4e22014-05-13 19:12:02 -0700435 for (ITopologyListener listener : this.topologyListeners) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700436 // TODO: Should copy before handing them over to listener?
Jonathan Harte37e4e22014-05-13 19:12:02 -0700437 listener.topologyEvents(apiAddedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700438 apiRemovedSwitchEvents,
439 apiAddedPortEvents,
440 apiRemovedPortEvents,
441 apiAddedLinkEvents,
442 apiRemovedLinkEvents,
443 apiAddedDeviceEvents,
444 apiRemovedDeviceEvents);
445 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800446
Ray Milkey269ffb92014-04-03 14:43:30 -0700447 //
448 // Cleanup
449 //
450 apiAddedSwitchEvents.clear();
451 apiRemovedSwitchEvents.clear();
452 apiAddedPortEvents.clear();
453 apiRemovedPortEvents.clear();
454 apiAddedLinkEvents.clear();
455 apiRemovedLinkEvents.clear();
456 apiAddedDeviceEvents.clear();
457 apiRemovedDeviceEvents.clear();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800458 }
459
460 /**
461 * Apply reordered events.
462 *
463 * @param hasAddedSwitchEvents true if there were Added Switch Events.
Ray Milkey269ffb92014-04-03 14:43:30 -0700464 * @param hasAddedPortEvents true if there were Added Port Events.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800465 */
466 private void applyReorderedEvents(boolean hasAddedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700467 boolean hasAddedPortEvents) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700468 if (!(hasAddedSwitchEvents || hasAddedPortEvents)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700469 return; // Nothing to do
Ray Milkeyb29e6262014-04-09 16:02:14 -0700470 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800471
Ray Milkey269ffb92014-04-03 14:43:30 -0700472 //
473 // Try to apply the reordered events.
474 //
475 // NOTE: For simplicity we try to apply all events of a particular
476 // type if any "parent" type event was processed:
477 // - Apply reordered Port Events if Switches were added
478 // - Apply reordered Link and Device Events if Switches or Ports
479 // were added
480 //
adminbc181552014-02-21 18:36:42 -0800481
Ray Milkey269ffb92014-04-03 14:43:30 -0700482 //
483 // Apply reordered Port Events if Switches were added
484 //
485 if (hasAddedSwitchEvents) {
486 Map<ByteBuffer, PortEvent> portEvents = reorderedAddedPortEvents;
487 reorderedAddedPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700488 for (PortEvent portEvent : portEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700489 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700490 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700491 }
492 //
493 // Apply reordered Link and Device Events if Switches or Ports
494 // were added.
495 //
496 Map<ByteBuffer, LinkEvent> linkEvents = reorderedAddedLinkEvents;
497 reorderedAddedLinkEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700498 for (LinkEvent linkEvent : linkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700499 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700500 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700501 //
502 Map<ByteBuffer, DeviceEvent> deviceEvents = reorderedAddedDeviceEvents;
503 reorderedAddedDeviceEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700504 for (DeviceEvent deviceEvent : deviceEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700505 addDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700506 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800507 }
508
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800509 /**
510 * Switch discovered event.
511 *
512 * @param switchEvent the switch event.
Ray Milkey269ffb92014-04-03 14:43:30 -0700513 * @param portEvents the corresponding port events for the switch.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800514 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800515 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800516 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
Ray Milkey269ffb92014-04-03 14:43:30 -0700517 Collection<PortEvent> portEvents) {
518 if (datastore.addSwitch(switchEvent, portEvents)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700519 log.debug("Sending add switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700520 // Send out notification
521 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
522 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800523
Ray Milkey269ffb92014-04-03 14:43:30 -0700524 // Send out notification for each port
525 for (PortEvent portEvent : portEvents) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700526 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700527 topologyEvent = new TopologyEvent(portEvent);
528 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
529 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800530
Ray Milkey269ffb92014-04-03 14:43:30 -0700531 //
532 // Keep track of the added ports
533 //
534 // Get the old Port Events
535 Map<ByteBuffer, PortEvent> oldPortEvents =
536 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700537 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700538 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700539 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800540
Ray Milkey269ffb92014-04-03 14:43:30 -0700541 // Store the new Port Events in the local cache
542 Map<ByteBuffer, PortEvent> newPortEvents = new HashMap<>();
543 for (PortEvent portEvent : portEvents) {
544 ByteBuffer id = portEvent.getIDasByteBuffer();
545 newPortEvents.put(id, portEvent);
546 }
547 discoveredAddedPortEvents.put(switchEvent.getDpid(),
548 newPortEvents);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800549
Ray Milkey269ffb92014-04-03 14:43:30 -0700550 //
551 // Extract the removed ports
552 //
553 List<PortEvent> removedPortEvents = new LinkedList<>();
554 for (Map.Entry<ByteBuffer, PortEvent> entry : oldPortEvents.entrySet()) {
555 ByteBuffer key = entry.getKey();
556 PortEvent portEvent = entry.getValue();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700557 if (!newPortEvents.containsKey(key)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700558 removedPortEvents.add(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700559 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700560 }
561
562 // Cleanup old removed ports
Ray Milkeyb29e6262014-04-09 16:02:14 -0700563 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700564 removePortDiscoveryEvent(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700565 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700566 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800567 }
568
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800569 /**
570 * Switch removed event.
571 *
572 * @param switchEvent the switch event.
573 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800574 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800575 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700576 // Get the old Port Events
577 Map<ByteBuffer, PortEvent> oldPortEvents =
578 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700579 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700580 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700581 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800582
Ray Milkey269ffb92014-04-03 14:43:30 -0700583 if (datastore.deactivateSwitch(switchEvent, oldPortEvents.values())) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700584 log.debug("Sending remove switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700585 // Send out notification
586 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800587
Ray Milkey269ffb92014-04-03 14:43:30 -0700588 //
589 // Send out notification for each port.
590 //
591 // NOTE: We don't use removePortDiscoveryEvent() for the cleanup,
592 // because it will attempt to remove the port from the database,
593 // and the deactiveSwitch() call above already removed all ports.
594 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700595 for (PortEvent portEvent : oldPortEvents.values()) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700596 log.debug("Sending remove port:", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700597 eventChannel.removeEntry(portEvent.getID());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700598 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700599 discoveredAddedPortEvents.remove(switchEvent.getDpid());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800600
Ray Milkey269ffb92014-04-03 14:43:30 -0700601 // Cleanup for each link
602 Map<ByteBuffer, LinkEvent> oldLinkEvents =
603 discoveredAddedLinkEvents.get(switchEvent.getDpid());
604 if (oldLinkEvents != null) {
605 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
606 removeLinkDiscoveryEvent(linkEvent);
607 }
608 discoveredAddedLinkEvents.remove(switchEvent.getDpid());
609 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800610
Ray Milkey269ffb92014-04-03 14:43:30 -0700611 // Cleanup for each device
612 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
613 discoveredAddedDeviceEvents.get(switchEvent.getDpid());
614 if (oldDeviceEvents != null) {
615 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
616 removeDeviceDiscoveryEvent(deviceEvent);
617 }
618 discoveredAddedDeviceEvents.remove(switchEvent.getDpid());
619 }
620 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800621 }
622
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800623 /**
624 * Port discovered event.
625 *
626 * @param portEvent the port event.
627 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800628 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800629 public void putPortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700630 if (datastore.addPort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700631 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700632 // Send out notification
633 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
634 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800635
Ray Milkey269ffb92014-04-03 14:43:30 -0700636 // Store the new Port Event in the local cache
637 Map<ByteBuffer, PortEvent> oldPortEvents =
638 discoveredAddedPortEvents.get(portEvent.getDpid());
639 if (oldPortEvents == null) {
640 oldPortEvents = new HashMap<>();
641 discoveredAddedPortEvents.put(portEvent.getDpid(),
642 oldPortEvents);
643 }
644 ByteBuffer id = portEvent.getIDasByteBuffer();
645 oldPortEvents.put(id, portEvent);
646 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800647 }
648
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800649 /**
650 * Port removed event.
651 *
652 * @param portEvent the port event.
653 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800654 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800655 public void removePortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700656 if (datastore.deactivatePort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700657 log.debug("Sending remove port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700658 // Send out notification
659 eventChannel.removeEntry(portEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800660
Ray Milkey269ffb92014-04-03 14:43:30 -0700661 // Cleanup the Port Event from the local cache
662 Map<ByteBuffer, PortEvent> oldPortEvents =
663 discoveredAddedPortEvents.get(portEvent.getDpid());
664 if (oldPortEvents != null) {
665 ByteBuffer id = portEvent.getIDasByteBuffer();
666 oldPortEvents.remove(id);
667 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800668
Ray Milkey269ffb92014-04-03 14:43:30 -0700669 // Cleanup for the incoming link
670 Map<ByteBuffer, LinkEvent> oldLinkEvents =
671 discoveredAddedLinkEvents.get(portEvent.getDpid());
672 if (oldLinkEvents != null) {
673 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
674 if (linkEvent.getDst().equals(portEvent.id)) {
675 removeLinkDiscoveryEvent(linkEvent);
676 // XXX If we change our model to allow multiple Link on
677 // a Port, this loop must be fixed to allow continuing.
678 break;
679 }
680 }
681 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800682
Ray Milkey269ffb92014-04-03 14:43:30 -0700683 // Cleanup for the connected devices
684 // TODO: The implementation below is probably wrong
685 List<DeviceEvent> removedDeviceEvents = new LinkedList<>();
686 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
687 discoveredAddedDeviceEvents.get(portEvent.getDpid());
688 if (oldDeviceEvents != null) {
689 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
690 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
691 if (swp.equals(portEvent.id)) {
692 removedDeviceEvents.add(deviceEvent);
693 }
694 }
695 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700696 for (DeviceEvent deviceEvent : removedDeviceEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700697 removeDeviceDiscoveryEvent(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700698 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700699 }
700 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800701 }
702
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800703 /**
704 * Link discovered event.
705 *
706 * @param linkEvent the link event.
707 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800708 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800709 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700710 if (datastore.addLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700711 log.debug("Sending add link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700712 // Send out notification
713 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
714 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800715
Ray Milkey269ffb92014-04-03 14:43:30 -0700716 // Store the new Link Event in the local cache
717 Map<ByteBuffer, LinkEvent> oldLinkEvents =
718 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
719 if (oldLinkEvents == null) {
720 oldLinkEvents = new HashMap<>();
721 discoveredAddedLinkEvents.put(linkEvent.getDst().getDpid(),
722 oldLinkEvents);
723 }
724 ByteBuffer id = linkEvent.getIDasByteBuffer();
725 oldLinkEvents.put(id, linkEvent);
726 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800727 }
728
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800729 /**
730 * Link removed event.
731 *
732 * @param linkEvent the link event.
733 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800734 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800735 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700736 if (datastore.removeLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700737 log.debug("Sending remove link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700738 // Send out notification
739 eventChannel.removeEntry(linkEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800740
Ray Milkey269ffb92014-04-03 14:43:30 -0700741 // Cleanup the Link Event from the local cache
742 Map<ByteBuffer, LinkEvent> oldLinkEvents =
743 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
744 if (oldLinkEvents != null) {
745 ByteBuffer id = linkEvent.getIDasByteBuffer();
746 oldLinkEvents.remove(id);
747 }
748 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800749 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800750
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800751 /**
752 * Device discovered event.
753 *
754 * @param deviceEvent the device event.
755 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800756 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800757 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700758 if (datastore.addDevice(deviceEvent)) {
759 // Send out notification
760 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
761 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700762 log.debug("Put the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -0700763
764 // Store the new Device Event in the local cache
765 // TODO: The implementation below is probably wrong
766 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
767 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
768 discoveredAddedDeviceEvents.get(swp.getDpid());
769 if (oldDeviceEvents == null) {
770 oldDeviceEvents = new HashMap<>();
771 discoveredAddedDeviceEvents.put(swp.getDpid(),
772 oldDeviceEvents);
773 }
774 ByteBuffer id = deviceEvent.getIDasByteBuffer();
775 oldDeviceEvents.put(id, deviceEvent);
776 }
777 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800778 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800779
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800780 /**
781 * Device removed event.
782 *
783 * @param deviceEvent the device event.
784 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800785 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800786 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700787 if (datastore.removeDevice(deviceEvent)) {
788 // Send out notification
789 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Harte37e4e22014-05-13 19:12:02 -0700790 log.debug("Remove the device info into the cache of the topology. mac {}", deviceEvent.getMac());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800791
Ray Milkey269ffb92014-04-03 14:43:30 -0700792 // Cleanup the Device Event from the local cache
793 // TODO: The implementation below is probably wrong
794 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
795 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
796 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
797 discoveredAddedDeviceEvents.get(swp.getDpid());
798 if (oldDeviceEvents != null) {
799 oldDeviceEvents.remove(id);
800 }
801 }
802 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800803 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800804
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800805 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700806 * Add a switch to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800807 *
808 * @param switchEvent the Switch Event with the switch to add.
809 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800810 private void addSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700811 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700812 if (sw == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700813 sw = new SwitchImpl(topology, switchEvent.getDpid());
814 topology.putSwitch(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700815 } else {
816 // TODO: Update the switch attributes
817 // TODO: Nothing to do for now
Ray Milkey1aa71f82014-04-08 16:23:24 -0700818 log.debug("Update switch attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700819 }
820 apiAddedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800821 }
822
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800823 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700824 * Remove a switch from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800825 *
826 * @param switchEvent the Switch Event with the switch to remove.
827 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800828 private void removeSwitch(SwitchEvent switchEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700829 Switch sw = topology.getSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700830 if (sw == null) {
831 log.warn("Switch {} already removed, ignoring", switchEvent);
832 return;
833 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800834
Ray Milkey269ffb92014-04-03 14:43:30 -0700835 //
836 // Remove all Ports on the Switch
837 //
838 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
839 for (Port port : sw.getPorts()) {
840 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
841 port, switchEvent);
842 PortEvent portEvent = new PortEvent(port.getDpid(),
843 port.getNumber());
844 portsToRemove.add(portEvent);
845 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700846 for (PortEvent portEvent : portsToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700847 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700848 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800849
Jonathan Harte37e4e22014-05-13 19:12:02 -0700850 topology.removeSwitch(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700851 apiRemovedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800852 }
853
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800854 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700855 * Add a port to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800856 *
857 * @param portEvent the Port Event with the port to add.
858 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800859 private void addPort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700860 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700861 if (sw == null) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700862 log.debug("{} reordered because switch is null", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700863 // Reordered event: delay the event in local cache
864 ByteBuffer id = portEvent.getIDasByteBuffer();
865 reorderedAddedPortEvents.put(id, portEvent);
866 return;
867 }
868 SwitchImpl switchImpl = getSwitchImpl(sw);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800869
Ray Milkey269ffb92014-04-03 14:43:30 -0700870 Port port = sw.getPort(portEvent.getNumber());
871 if (port == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700872 port = new PortImpl(topology, sw, portEvent.getNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -0700873 switchImpl.addPort(port);
874 } else {
875 // TODO: Update the port attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700876 log.debug("Update port attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700877 }
878 apiAddedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800879 }
880
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800881 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700882 * Remove a port from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800883 *
884 * @param portEvent the Port Event with the port to remove.
885 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800886 private void removePort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700887 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700888 if (sw == null) {
889 log.warn("Parent Switch for Port {} already removed, ignoring",
890 portEvent);
891 return;
892 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800893
Ray Milkey269ffb92014-04-03 14:43:30 -0700894 Port port = sw.getPort(portEvent.getNumber());
895 if (port == null) {
896 log.warn("Port {} already removed, ignoring", portEvent);
897 return;
898 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800899
Ray Milkey269ffb92014-04-03 14:43:30 -0700900 //
901 // Remove all Devices attached to the Port
902 //
903 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
904 for (Device device : port.getDevices()) {
905 log.debug("Removing Device {} on Port {}", device, portEvent);
906 DeviceEvent deviceEvent = new DeviceEvent(device.getMacAddress());
907 SwitchPort switchPort = new SwitchPort(port.getSwitch().getDpid(),
908 port.getNumber());
909 deviceEvent.addAttachmentPoint(switchPort);
910 devicesToRemove.add(deviceEvent);
911 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700912 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700913 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700914 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800915
Ray Milkey269ffb92014-04-03 14:43:30 -0700916 //
917 // Remove all Links connected to the Port
918 //
919 Set<Link> links = new HashSet<>();
920 links.add(port.getOutgoingLink());
921 links.add(port.getIncomingLink());
922 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
923 for (Link link : links) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700924 if (link == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700925 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -0700926 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700927 log.debug("Removing Link {} on Port {}", link, portEvent);
928 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
929 link.getSrcPort().getNumber(),
930 link.getDstSwitch().getDpid(),
931 link.getDstPort().getNumber());
932 linksToRemove.add(linkEvent);
933 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700934 for (LinkEvent linkEvent : linksToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700935 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700936 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800937
Ray Milkey269ffb92014-04-03 14:43:30 -0700938 // Remove the Port from the Switch
939 SwitchImpl switchImpl = getSwitchImpl(sw);
940 switchImpl.removePort(port);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800941
Ray Milkey269ffb92014-04-03 14:43:30 -0700942 apiRemovedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800943 }
944
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800945 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700946 * Add a link to the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800947 *
948 * @param linkEvent the Link Event with the link to add.
949 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800950 private void addLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700951 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700952 linkEvent.getSrc().number);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700953 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700954 linkEvent.getDst().number);
955 if ((srcPort == null) || (dstPort == null)) {
Jonathan Hartf1675202014-05-23 14:59:07 -0700956 log.debug("{} reordered because {} port is null", linkEvent,
957 (srcPort == null) ? "src" : "dst");
958
Ray Milkey269ffb92014-04-03 14:43:30 -0700959 // Reordered event: delay the event in local cache
960 ByteBuffer id = linkEvent.getIDasByteBuffer();
961 reorderedAddedLinkEvents.put(id, linkEvent);
962 return;
963 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800964
Ray Milkey269ffb92014-04-03 14:43:30 -0700965 // Get the Link instance from the Destination Port Incoming Link
966 Link link = dstPort.getIncomingLink();
967 assert (link == srcPort.getOutgoingLink());
968 if (link == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700969 link = new LinkImpl(topology, srcPort, dstPort);
970 topology.putLink(link);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800971
Ray Milkey269ffb92014-04-03 14:43:30 -0700972 // Remove all Devices attached to the Ports
973 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
974 ArrayList<Port> ports = new ArrayList<>();
975 ports.add(srcPort);
976 ports.add(dstPort);
977 for (Port port : ports) {
978 for (Device device : port.getDevices()) {
979 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
980 device, port, linkEvent);
981 DeviceEvent deviceEvent =
982 new DeviceEvent(device.getMacAddress());
983 SwitchPort switchPort =
984 new SwitchPort(port.getSwitch().getDpid(),
985 port.getNumber());
986 deviceEvent.addAttachmentPoint(switchPort);
987 devicesToRemove.add(deviceEvent);
988 }
989 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700990 for (DeviceEvent deviceEvent : devicesToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700991 removeDevice(deviceEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700992 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700993 } else {
994 // TODO: Update the link attributes
Ray Milkey1aa71f82014-04-08 16:23:24 -0700995 log.debug("Update link attributes");
Ray Milkey269ffb92014-04-03 14:43:30 -0700996 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800997
Ray Milkey269ffb92014-04-03 14:43:30 -0700998 apiAddedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800999 }
1000
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001001 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001002 * Remove a link from the topology.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001003 *
1004 * @param linkEvent the Link Event with the link to remove.
1005 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001006 private void removeLink(LinkEvent linkEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001007 Port srcPort = topology.getPort(linkEvent.getSrc().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -07001008 linkEvent.getSrc().number);
1009 if (srcPort == null) {
1010 log.warn("Src Port for Link {} already removed, ignoring",
1011 linkEvent);
1012 return;
1013 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001014
Jonathan Harte37e4e22014-05-13 19:12:02 -07001015 Port dstPort = topology.getPort(linkEvent.getDst().dpid,
Ray Milkey269ffb92014-04-03 14:43:30 -07001016 linkEvent.getDst().number);
1017 if (dstPort == null) {
1018 log.warn("Dst Port for Link {} already removed, ignoring",
1019 linkEvent);
1020 return;
1021 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001022
Ray Milkey269ffb92014-04-03 14:43:30 -07001023 //
1024 // Remove the Link instance from the Destination Port Incoming Link
1025 // and the Source Port Outgoing Link.
1026 //
1027 Link link = dstPort.getIncomingLink();
1028 if (link == null) {
1029 log.warn("Link {} already removed on destination Port", linkEvent);
1030 }
1031 link = srcPort.getOutgoingLink();
1032 if (link == null) {
1033 log.warn("Link {} already removed on src Port", linkEvent);
1034 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001035
1036 // TODO should we check that we get the same link from each port?
1037 if (link != null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001038 topology.removeLink(link);
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001039 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001040
Ray Milkey269ffb92014-04-03 14:43:30 -07001041 apiRemovedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001042 }
1043
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001044 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001045 * Add a device to the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001046 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001047 * TODO: Device-related work is incomplete.
1048 * TODO: Eventually, we might need to consider reordering
1049 * or addLink() and addDevice() events on the same port.
1050 *
1051 * @param deviceEvent the Device Event with the device to add.
1052 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001053 private void addDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001054 log.debug("Adding a device to the topology with mac {}", deviceEvent.getMac());
1055 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001056
Ray Milkey269ffb92014-04-03 14:43:30 -07001057 if (device == null) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001058 log.debug("Existing device was not found in the Topology: Adding new device: mac {}", deviceEvent.getMac());
1059 device = new DeviceImpl(topology, deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001060 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001061
Ray Milkey269ffb92014-04-03 14:43:30 -07001062 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001063
Ray Milkey269ffb92014-04-03 14:43:30 -07001064 // Process each attachment point
1065 boolean attachmentFound = false;
1066 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1067 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001068 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001069 if (port == null) {
1070 // Reordered event: delay the event in local cache
1071 ByteBuffer id = deviceEvent.getIDasByteBuffer();
1072 reorderedAddedDeviceEvents.put(id, deviceEvent);
1073 continue;
1074 }
1075 // Attached Ports must not have Link
1076 if (port.getOutgoingLink() != null ||
1077 port.getIncomingLink() != null) {
1078 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
1079 port.getOutgoingLink(),
1080 port.getIncomingLink());
1081 continue;
1082 }
1083
1084 // Add Device <-> Port attachment
1085 PortImpl portImpl = getPortImpl(port);
1086 portImpl.addDevice(device);
1087 deviceImpl.addAttachmentPoint(port);
1088 attachmentFound = true;
1089 }
1090
TeruU5d2c9392014-06-09 20:02:02 -07001091 deviceImpl.setLastSeenTime(deviceEvent.getLastSeenTime());
1092
Jonathan Harte37e4e22014-05-13 19:12:02 -07001093 // Update the device in the topology
Ray Milkey269ffb92014-04-03 14:43:30 -07001094 if (attachmentFound) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001095 log.debug("Storing the device info into the Topology: mac {}", deviceEvent.getMac());
1096 topology.putDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001097 apiAddedDeviceEvents.add(deviceEvent);
1098 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001099 }
1100
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001101 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -07001102 * Remove a device from the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -07001103 * <p/>
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001104 * TODO: Device-related work is incomplete.
1105 *
1106 * @param deviceEvent the Device Event with the device to remove.
1107 */
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001108 private void removeDevice(DeviceEvent deviceEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001109 log.debug("Removing a device to the topology: mac {}", deviceEvent.getMac());
1110 Device device = topology.getDeviceByMac(deviceEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -07001111 if (device == null) {
1112 log.warn("Device {} already removed, ignoring", deviceEvent);
1113 return;
1114 }
1115 DeviceImpl deviceImpl = getDeviceImpl(device);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001116
Ray Milkey269ffb92014-04-03 14:43:30 -07001117 // Process each attachment point
1118 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
1119 // Attached Ports must exist
Jonathan Harte37e4e22014-05-13 19:12:02 -07001120 Port port = topology.getPort(swp.dpid, swp.number);
Ray Milkey269ffb92014-04-03 14:43:30 -07001121 if (port == null) {
1122 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
1123 continue;
1124 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001125
Ray Milkey269ffb92014-04-03 14:43:30 -07001126 // Remove Device <-> Port attachment
1127 PortImpl portImpl = getPortImpl(port);
1128 portImpl.removeDevice(device);
1129 deviceImpl.removeAttachmentPoint(port);
1130 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001131
Jonathan Harte37e4e22014-05-13 19:12:02 -07001132 log.debug("Removing the device info into the Topology: mac {}", deviceEvent.getMac());
1133 topology.removeDevice(device);
Ray Milkey269ffb92014-04-03 14:43:30 -07001134 apiRemovedDeviceEvents.add(deviceEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001135 }
Jonathan Hart22eb9882014-02-11 15:52:59 -08001136
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001137 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001138 * Get the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001139 *
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001140 * @param sw the Switch to cast.
1141 * @return the SwitchImpl-casted switch implementation.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001142 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001143 private SwitchImpl getSwitchImpl(Switch sw) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001144 if (sw instanceof SwitchImpl) {
1145 return (SwitchImpl) sw;
1146 }
1147 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001148 }
1149
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001150 /**
1151 * Get the PortImpl-casted port implementation.
1152 *
1153 * @param port the Port to cast.
1154 * @return the PortImpl-casted port implementation.
1155 */
1156 private PortImpl getPortImpl(Port port) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001157 if (port instanceof PortImpl) {
1158 return (PortImpl) port;
1159 }
1160 throw new ClassCastException("PortImpl expected, but found: " + port);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001161 }
1162
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001163 /**
1164 * Get the LinkImpl-casted link implementation.
1165 *
1166 * @param link the Link to cast.
1167 * @return the LinkImpl-casted link implementation.
1168 */
1169 private LinkImpl getLinkImpl(Link link) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001170 if (link instanceof LinkImpl) {
1171 return (LinkImpl) link;
1172 }
1173 throw new ClassCastException("LinkImpl expected, but found: " + link);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001174 }
1175
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001176 /**
1177 * Get the DeviceImpl-casted device implementation.
1178 *
1179 * @param device the Device to cast.
1180 * @return the DeviceImpl-casted device implementation.
1181 */
1182 private DeviceImpl getDeviceImpl(Device device) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001183 if (device instanceof DeviceImpl) {
1184 return (DeviceImpl) device;
1185 }
1186 throw new ClassCastException("DeviceImpl expected, but found: " + device);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001187 }
1188
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001189 /**
1190 * Read the whole topology from the database.
1191 *
1192 * @return a collection of EventEntry-encapsulated Topology Events for
1193 * the whole topology.
1194 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001195 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
Ray Milkey269ffb92014-04-03 14:43:30 -07001196 Collection<EventEntry<TopologyEvent>> collection =
1197 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001198
Ray Milkey269ffb92014-04-03 14:43:30 -07001199 // XXX May need to clear whole topology first, depending on
1200 // how we initially subscribe to replication events
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001201
Ray Milkey269ffb92014-04-03 14:43:30 -07001202 // Add all active switches
1203 for (KVSwitch sw : KVSwitch.getAllSwitches()) {
1204 if (sw.getStatus() != KVSwitch.STATUS.ACTIVE) {
1205 continue;
1206 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001207
Ray Milkey269ffb92014-04-03 14:43:30 -07001208 SwitchEvent switchEvent = new SwitchEvent(sw.getDpid());
1209 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
1210 EventEntry<TopologyEvent> eventEntry =
1211 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1212 topologyEvent);
1213 collection.add(eventEntry);
1214 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001215
Ray Milkey269ffb92014-04-03 14:43:30 -07001216 // Add all active ports
1217 for (KVPort p : KVPort.getAllPorts()) {
1218 if (p.getStatus() != KVPort.STATUS.ACTIVE) {
1219 continue;
1220 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001221
Ray Milkey269ffb92014-04-03 14:43:30 -07001222 PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
1223 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
1224 EventEntry<TopologyEvent> eventEntry =
1225 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1226 topologyEvent);
1227 collection.add(eventEntry);
1228 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001229
TeruU28adcc32014-04-15 17:57:35 -07001230 for (KVDevice d : KVDevice.getAllDevices()) {
1231 DeviceEvent devEvent = new DeviceEvent(MACAddress.valueOf(d.getMac()));
1232 for (byte[] portId : d.getAllPortIds()) {
Jonathan Hartc00f5c22014-06-10 15:14:40 -07001233 devEvent.addAttachmentPoint(
1234 new SwitchPort(KVPort.getDpidFromKey(portId),
1235 KVPort.getNumberFromKey(portId)));
TeruU28adcc32014-04-15 17:57:35 -07001236 }
1237 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001238
Ray Milkey269ffb92014-04-03 14:43:30 -07001239 for (KVLink l : KVLink.getAllLinks()) {
1240 LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
1241 l.getSrc().number,
1242 l.getDst().dpid,
1243 l.getDst().number);
1244 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
1245 EventEntry<TopologyEvent> eventEntry =
1246 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1247 topologyEvent);
1248 collection.add(eventEntry);
1249 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001250
Ray Milkey269ffb92014-04-03 14:43:30 -07001251 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001252 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001253}