blob: d32df8df2796668add18c8aedea9a68dcb9b0793 [file] [log] [blame]
Jonathan Hart062a2e82014-02-03 09:41:57 -08001package net.onrc.onos.ofcontroller.networkgraph;
2
Yuta HIGUCHI1c700102014-02-12 16:30:52 -08003import java.net.InetAddress;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08004import java.nio.ByteBuffer;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08005import java.util.ArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08006import java.util.Collection;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08007import java.util.HashMap;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08008import java.util.HashSet;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08009import java.util.LinkedList;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080010import java.util.List;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080011import java.util.Map;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080012import java.util.Set;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080013import java.util.concurrent.BlockingQueue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080014import java.util.concurrent.CopyOnWriteArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080015import java.util.concurrent.LinkedBlockingQueue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080016
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080017import net.onrc.onos.datagrid.IDatagridService;
18import net.onrc.onos.datagrid.IEventChannel;
19import net.onrc.onos.datagrid.IEventChannelListener;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080020import net.onrc.onos.datastore.topology.RCLink;
Jonathan Hart062a2e82014-02-03 09:41:57 -080021import net.onrc.onos.datastore.topology.RCPort;
22import net.onrc.onos.datastore.topology.RCSwitch;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080023import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080024import net.onrc.onos.ofcontroller.util.EventEntry;
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080025import net.onrc.onos.registry.controller.IControllerRegistryService;
Jonathan Hart062a2e82014-02-03 09:41:57 -080026
27import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
29
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080030/**
31 * The "NB" read-only Network Map.
32 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080033 * - Maintain Invariant/Relationships between Topology Objects.
34 *
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080035 * TODO To be synchronized based on TopologyEvent Notification.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080036 *
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080037 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
Yuta HIGUCHI1c700102014-02-12 16:30:52 -080038 * Object must exist before adding sub component(Add Switch -> Port).
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080039 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080040 * TODO TBD: This class may delay the requested change to handle event
41 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080042 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080043 */
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -080044public class TopologyManager implements NetworkGraphDiscoveryInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080045
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080046 private static final Logger log = LoggerFactory
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -080047 .getLogger(TopologyManager.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080048
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080049 private IEventChannel<byte[], TopologyEvent> eventChannel;
Jonathan Hart10a7e2b2014-02-21 18:30:08 -080050 public static final String EVENT_CHANNEL_NAME = "onos.topology";
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080051 private EventHandler eventHandler = new EventHandler();
52
Jonathan Hart22eb9882014-02-11 15:52:59 -080053 private final NetworkGraphDatastore datastore;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080054 private final NetworkGraphImpl networkGraph = new NetworkGraphImpl();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080055 private final IControllerRegistryService registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080056 private CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners;
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080057
Pavlin Radoslavov706add22014-02-20 12:15:59 -080058 //
59 // Local state for keeping track of reordered events.
60 // NOTE: Switch Events are not affected by the event reordering.
61 //
62 private Map<ByteBuffer, PortEvent> reorderedAddedPortEvents =
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080063 new HashMap<ByteBuffer, PortEvent>();
Pavlin Radoslavov706add22014-02-20 12:15:59 -080064 private Map<ByteBuffer, LinkEvent> reorderedAddedLinkEvents =
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080065 new HashMap<ByteBuffer, LinkEvent>();
Pavlin Radoslavov706add22014-02-20 12:15:59 -080066 private Map<ByteBuffer, DeviceEvent> reorderedAddedDeviceEvents =
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080067 new HashMap<ByteBuffer, DeviceEvent>();
68
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -080069 //
Pavlin Radoslavov26d83402014-02-20 15:24:30 -080070 // Local state for keeping track of locally discovered events so we can
71 // cleanup properly when a Switch or Port is removed.
72 //
73 // We keep all Port, Link and Device events per Switch DPID:
74 // - If a switch goes down, we remove all corresponding Port, Link and
75 // Device events.
76 // - If a port on a switch goes down, we remove all corresponding Link
77 // and Device events.
78 //
79 private Map<Long, Map<ByteBuffer, PortEvent>> discoveredAddedPortEvents =
80 new HashMap<>();
81 private Map<Long, Map<ByteBuffer, LinkEvent>> discoveredAddedLinkEvents =
82 new HashMap<>();
83 private Map<Long, Map<ByteBuffer, DeviceEvent>> discoveredAddedDeviceEvents =
84 new HashMap<>();
85
86 //
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -080087 // Local state for keeping track of the application event notifications
88 //
89 List<SwitchEvent> apiAddedSwitchEvents = new LinkedList<SwitchEvent>();
90 List<SwitchEvent> apiRemovedSwitchEvents = new LinkedList<SwitchEvent>();
91 List<PortEvent> apiAddedPortEvents = new LinkedList<PortEvent>();
92 List<PortEvent> apiRemovedPortEvents = new LinkedList<PortEvent>();
93 List<LinkEvent> apiAddedLinkEvents = new LinkedList<LinkEvent>();
94 List<LinkEvent> apiRemovedLinkEvents = new LinkedList<LinkEvent>();
95 List<DeviceEvent> apiAddedDeviceEvents = new LinkedList<DeviceEvent>();
96 List<DeviceEvent> apiRemovedDeviceEvents = new LinkedList<DeviceEvent>();
97
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080098 /**
99 * Constructor.
100 *
101 * @param registryService the Registry Service to use.
102 * @param networkGraphListeners the collection of Network Graph Listeners
103 * to use.
104 */
105 public TopologyManager(IControllerRegistryService registryService,
106 CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners) {
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800107 datastore = new NetworkGraphDatastore();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -0800108 this.registryService = registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800109 this.networkGraphListeners = networkGraphListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800110 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800111
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800112 /**
113 * Get the Network Graph.
114 *
115 * @return the Network Graph.
116 */
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -0800117 NetworkGraph getNetworkGraph() {
118 return networkGraph;
119 }
120
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800121 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800122 * Event handler class.
123 */
124 private class EventHandler extends Thread implements
125 IEventChannelListener<byte[], TopologyEvent> {
126 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
127 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
128
129 /**
130 * Startup processing.
131 */
132 private void startup() {
133 //
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800134 // TODO: Read all state from the database:
135 //
136 // Collection<EventEntry<TopologyEvent>> collection =
137 // readWholeTopologyFromDB();
138 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800139 // For now, as a shortcut we read it from the datagrid
140 //
141 Collection<TopologyEvent> topologyEvents =
142 eventChannel.getAllEntries();
143 Collection<EventEntry<TopologyEvent>> collection =
144 new LinkedList<EventEntry<TopologyEvent>>();
145
146 for (TopologyEvent topologyEvent : topologyEvents) {
147 EventEntry<TopologyEvent> eventEntry =
148 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
149 topologyEvent);
150 collection.add(eventEntry);
151 }
152 processEvents(collection);
153 }
154
155 /**
156 * Run the thread.
157 */
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800158 @Override
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800159 public void run() {
160 Collection<EventEntry<TopologyEvent>> collection =
161 new LinkedList<EventEntry<TopologyEvent>>();
162
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -0800163 this.setName("TopologyManager.EventHandler " + this.getId());
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800164 startup();
165
166 //
167 // The main loop
168 //
169 try {
170 while (true) {
171 EventEntry<TopologyEvent> eventEntry = topologyEvents.take();
172 collection.add(eventEntry);
173 topologyEvents.drainTo(collection);
174
175 processEvents(collection);
176 collection.clear();
177 }
178 } catch (Exception exception) {
179 log.debug("Exception processing Topology Events: ", exception);
180 }
181 }
182
183 /**
184 * Process all topology events.
185 *
186 * @param events the events to process.
187 */
188 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800189 // Local state for computing the final set of events
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800190 Map<ByteBuffer, SwitchEvent> addedSwitchEvents = new HashMap<>();
191 Map<ByteBuffer, SwitchEvent> removedSwitchEvents = new HashMap<>();
192 Map<ByteBuffer, PortEvent> addedPortEvents = new HashMap<>();
193 Map<ByteBuffer, PortEvent> removedPortEvents = new HashMap<>();
194 Map<ByteBuffer, LinkEvent> addedLinkEvents = new HashMap<>();
195 Map<ByteBuffer, LinkEvent> removedLinkEvents = new HashMap<>();
196 Map<ByteBuffer, DeviceEvent> addedDeviceEvents = new HashMap<>();
197 Map<ByteBuffer, DeviceEvent> removedDeviceEvents = new HashMap<>();
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800198
199 //
200 // Classify and suppress matching events
201 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800202 for (EventEntry<TopologyEvent> event : events) {
203 TopologyEvent topologyEvent = event.eventData();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800204 SwitchEvent switchEvent = topologyEvent.switchEvent;
205 PortEvent portEvent = topologyEvent.portEvent;
206 LinkEvent linkEvent = topologyEvent.linkEvent;
207 DeviceEvent deviceEvent = topologyEvent.deviceEvent;
208
209 //
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800210 // Extract the events
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800211 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800212 switch (event.eventType()) {
213 case ENTRY_ADD:
214 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800215 if (switchEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800216 ByteBuffer id = switchEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800217 addedSwitchEvents.put(id, switchEvent);
218 removedSwitchEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800219 // Switch Events are not affected by event reordering
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800220 }
221 if (portEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800222 ByteBuffer id = portEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800223 addedPortEvents.put(id, portEvent);
224 removedPortEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800225 reorderedAddedPortEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800226 }
227 if (linkEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800228 ByteBuffer id = linkEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800229 addedLinkEvents.put(id, linkEvent);
230 removedLinkEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800231 reorderedAddedLinkEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800232 }
233 if (deviceEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800234 ByteBuffer id = deviceEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800235 addedDeviceEvents.put(id, deviceEvent);
236 removedDeviceEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800237 reorderedAddedDeviceEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800238 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800239 break;
240 case ENTRY_REMOVE:
241 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800242 if (switchEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800243 ByteBuffer id = switchEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800244 addedSwitchEvents.remove(id);
245 removedSwitchEvents.put(id, switchEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800246 // Switch Events are not affected by event reordering
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800247 }
248 if (portEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800249 ByteBuffer id = portEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800250 addedPortEvents.remove(id);
251 removedPortEvents.put(id, portEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800252 reorderedAddedPortEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800253 }
254 if (linkEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800255 ByteBuffer id = linkEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800256 addedLinkEvents.remove(id);
257 removedLinkEvents.put(id, linkEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800258 reorderedAddedLinkEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800259 }
260 if (deviceEvent != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800261 ByteBuffer id = deviceEvent.getIDasByteBuffer();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800262 addedDeviceEvents.remove(id);
263 removedDeviceEvents.put(id, deviceEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800264 reorderedAddedDeviceEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800265 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800266 break;
267 }
268 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800269
270 //
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800271 // Lock the Network Graph while it is modified
272 //
273 networkGraph.acquireWriteLock();
274
Jonathan Hart26241692014-02-20 16:31:11 -0800275 try {
276 //
277 // Apply the classified events.
278 //
279 // Apply the "add" events in the proper order:
280 // switch, port, link, device
281 //
282 for (SwitchEvent switchEvent : addedSwitchEvents.values())
283 addSwitch(switchEvent);
284 for (PortEvent portEvent : addedPortEvents.values())
285 addPort(portEvent);
286 for (LinkEvent linkEvent : addedLinkEvents.values())
287 addLink(linkEvent);
288 for (DeviceEvent deviceEvent : addedDeviceEvents.values())
289 addDevice(deviceEvent);
290 //
291 // Apply the "remove" events in the reverse order:
292 // device, link, port, switch
293 //
294 for (DeviceEvent deviceEvent : removedDeviceEvents.values())
295 removeDevice(deviceEvent);
296 for (LinkEvent linkEvent : removedLinkEvents.values())
297 removeLink(linkEvent);
298 for (PortEvent portEvent : removedPortEvents.values())
299 removePort(portEvent);
300 for (SwitchEvent switchEvent : removedSwitchEvents.values())
301 removeSwitch(switchEvent);
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800302
Jonathan Hart26241692014-02-20 16:31:11 -0800303 //
304 // Apply reordered events
305 //
306 applyReorderedEvents(! addedSwitchEvents.isEmpty(),
307 ! addedPortEvents.isEmpty());
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800308
Jonathan Hart26241692014-02-20 16:31:11 -0800309 }
310 finally {
311 //
312 // Network Graph modifications completed: Release the lock
313 //
314 networkGraph.releaseWriteLock();
315 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800316
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800317 //
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800318 // Dispatch the Topology Notification Events to the applications
319 //
320 dispatchNetworkGraphEvents();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800321 }
322
323 /**
324 * Receive a notification that an entry is added.
325 *
326 * @param value the value for the entry.
327 */
328 @Override
329 public void entryAdded(TopologyEvent value) {
330 EventEntry<TopologyEvent> eventEntry =
331 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
332 value);
333 topologyEvents.add(eventEntry);
334 }
335
336 /**
337 * Receive a notification that an entry is removed.
338 *
339 * @param value the value for the entry.
340 */
341 @Override
342 public void entryRemoved(TopologyEvent value) {
343 EventEntry<TopologyEvent> eventEntry =
344 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
345 value);
346 topologyEvents.add(eventEntry);
347 }
348
349 /**
350 * Receive a notification that an entry is updated.
351 *
352 * @param value the value for the entry.
353 */
354 @Override
355 public void entryUpdated(TopologyEvent value) {
356 // NOTE: The ADD and UPDATE events are processed in same way
357 entryAdded(value);
358 }
359 }
360
361 /**
362 * Startup processing.
363 *
364 * @param datagridService the datagrid service to use.
365 */
366 void startup(IDatagridService datagridService) {
367 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
368 eventHandler,
369 byte[].class,
370 TopologyEvent.class);
371 eventHandler.start();
372 }
373
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800374 /**
375 * Dispatch Network Graph Events to the listeners.
376 */
377 private void dispatchNetworkGraphEvents() {
378 if (apiAddedSwitchEvents.isEmpty() &&
379 apiRemovedSwitchEvents.isEmpty() &&
380 apiAddedPortEvents.isEmpty() &&
381 apiRemovedPortEvents.isEmpty() &&
382 apiAddedLinkEvents.isEmpty() &&
383 apiRemovedLinkEvents.isEmpty() &&
384 apiAddedDeviceEvents.isEmpty() &&
385 apiRemovedDeviceEvents.isEmpty()) {
386 return; // No events to dispatch
387 }
388
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800389 if (log.isDebugEnabled()) {
390 //
391 // Debug statements
392 // TODO: Those statements should be removed in the future
393 //
394 for (SwitchEvent switchEvent : apiAddedSwitchEvents)
395 log.debug("Dispatch Network Graph Event: ADDED {}", switchEvent);
396 for (SwitchEvent switchEvent : apiRemovedSwitchEvents)
397 log.debug("Dispatch Network Graph Event: REMOVED {}", switchEvent);
398 for (PortEvent portEvent : apiAddedPortEvents)
399 log.debug("Dispatch Network Graph Event: ADDED {}", portEvent);
400 for (PortEvent portEvent : apiRemovedPortEvents)
401 log.debug("Dispatch Network Graph Event: REMOVED {}", portEvent);
402 for (LinkEvent linkEvent : apiAddedLinkEvents)
403 log.debug("Dispatch Network Graph Event: ADDED {}", linkEvent);
404 for (LinkEvent linkEvent : apiRemovedLinkEvents)
405 log.debug("Dispatch Network Graph Event: REMOVED {}", linkEvent);
406 for (DeviceEvent deviceEvent : apiAddedDeviceEvents)
407 log.debug("Dispatch Network Graph Event: ADDED {}", deviceEvent);
408 for (DeviceEvent deviceEvent : apiRemovedDeviceEvents)
409 log.debug("Dispatch Network Graph Event: REMOVED {}", deviceEvent);
410 }
adminbc181552014-02-21 18:36:42 -0800411
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800412 // Deliver the events
413 for (INetworkGraphListener listener : this.networkGraphListeners) {
414 // TODO: Should copy before handing them over to listener?
415 listener.networkGraphEvents(apiAddedSwitchEvents,
416 apiRemovedSwitchEvents,
417 apiAddedPortEvents,
418 apiRemovedPortEvents,
419 apiAddedLinkEvents,
420 apiRemovedLinkEvents,
421 apiAddedDeviceEvents,
422 apiRemovedDeviceEvents);
423 }
424
425 //
426 // Cleanup
427 //
428 apiAddedSwitchEvents.clear();
429 apiRemovedSwitchEvents.clear();
430 apiAddedPortEvents.clear();
431 apiRemovedPortEvents.clear();
432 apiAddedLinkEvents.clear();
433 apiRemovedLinkEvents.clear();
434 apiAddedDeviceEvents.clear();
435 apiRemovedDeviceEvents.clear();
436 }
437
438 /**
439 * Apply reordered events.
440 *
441 * @param hasAddedSwitchEvents true if there were Added Switch Events.
442 * @param hasAddedPortEvents true if there were Added Port Events.
443 */
444 private void applyReorderedEvents(boolean hasAddedSwitchEvents,
445 boolean hasAddedPortEvents) {
446 if (! (hasAddedSwitchEvents || hasAddedPortEvents))
447 return; // Nothing to do
448
449 //
450 // Try to apply the reordered events.
451 //
452 // NOTE: For simplicity we try to apply all events of a particular
453 // type if any "parent" type event was processed:
454 // - Apply reordered Port Events if Switches were added
455 // - Apply reordered Link and Device Events if Switches or Ports
456 // were added
457 //
adminbc181552014-02-21 18:36:42 -0800458
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800459 //
460 // Apply reordered Port Events if Switches were added
461 //
462 if (hasAddedSwitchEvents) {
adminbc181552014-02-21 18:36:42 -0800463 Map<ByteBuffer, PortEvent> portEvents = reorderedAddedPortEvents;
464 reorderedAddedPortEvents = new HashMap<>();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800465 for (PortEvent portEvent : portEvents.values())
466 addPort(portEvent);
467 }
468 //
469 // Apply reordered Link and Device Events if Switches or Ports
470 // were added.
471 //
adminbc181552014-02-21 18:36:42 -0800472 Map<ByteBuffer, LinkEvent> linkEvents = reorderedAddedLinkEvents;
473 reorderedAddedLinkEvents = new HashMap<>();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800474 for (LinkEvent linkEvent : linkEvents.values())
475 addLink(linkEvent);
adminbc181552014-02-21 18:36:42 -0800476 //
477 Map<ByteBuffer, DeviceEvent> deviceEvents = reorderedAddedDeviceEvents;
478 reorderedAddedDeviceEvents = new HashMap<>();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800479 for (DeviceEvent deviceEvent : deviceEvents.values())
480 addDevice(deviceEvent);
481 }
482
Jonathan Hart22eb9882014-02-11 15:52:59 -0800483 /* ******************************
484 * NetworkGraphDiscoveryInterface methods
485 * ******************************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800486
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800487 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800488 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
489 Collection<PortEvent> portEvents) {
490 if (datastore.addSwitch(switchEvent, portEvents)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800491 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800492 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800493 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800494
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800495 // Send out notification for each port
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800496 for (PortEvent portEvent : portEvents) {
497 topologyEvent = new TopologyEvent(portEvent);
498 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
499 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800500
501 //
502 // Keep track of the added ports
503 //
504 // Get the old Port Events
505 Map<ByteBuffer, PortEvent> oldPortEvents =
506 discoveredAddedPortEvents.get(switchEvent.getDpid());
507 if (oldPortEvents == null)
508 oldPortEvents = new HashMap<>();
509
510 // Store the new Port Events in the local cache
511 Map<ByteBuffer, PortEvent> newPortEvents = new HashMap<>();
512 for (PortEvent portEvent : portEvents) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800513 ByteBuffer id = portEvent.getIDasByteBuffer();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800514 newPortEvents.put(id, portEvent);
515 }
516 discoveredAddedPortEvents.put(switchEvent.getDpid(),
517 newPortEvents);
518
519 //
520 // Extract the removed ports
521 //
522 List<PortEvent> removedPortEvents = new LinkedList<>();
523 for (Map.Entry<ByteBuffer, PortEvent> entry : oldPortEvents.entrySet()) {
524 ByteBuffer key = entry.getKey();
525 PortEvent portEvent = entry.getValue();
526 if (! newPortEvents.containsKey(key))
527 removedPortEvents.add(portEvent);
528 }
529
530 // Cleanup old removed ports
531 for (PortEvent portEvent : removedPortEvents)
532 removePortDiscoveryEvent(portEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800533 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800534 }
535
536 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800537 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800538 // Get the old Port Events
539 Map<ByteBuffer, PortEvent> oldPortEvents =
540 discoveredAddedPortEvents.get(switchEvent.getDpid());
541 if (oldPortEvents == null)
542 oldPortEvents = new HashMap<>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800543
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800544 if (datastore.deactivateSwitch(switchEvent, oldPortEvents.values())) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800545 // Send out notification
546 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800547
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800548 // Send out notification for each port
549 for (PortEvent portEvent : oldPortEvents.values())
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800550 eventChannel.removeEntry(portEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800551 discoveredAddedPortEvents.remove(switchEvent.getDpid());
552
553 // Cleanup for each link
554 Map<ByteBuffer, LinkEvent> oldLinkEvents =
555 discoveredAddedLinkEvents.get(switchEvent.getDpid());
556 if (oldLinkEvents != null) {
Yuta HIGUCHI95b20352014-02-24 12:06:27 -0800557 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800558 removeLinkDiscoveryEvent(linkEvent);
Yuta HIGUCHI95b20352014-02-24 12:06:27 -0800559 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800560 discoveredAddedLinkEvents.remove(switchEvent.getDpid());
561 }
562
563 // Cleanup for each device
564 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
565 discoveredAddedDeviceEvents.get(switchEvent.getDpid());
566 if (oldDeviceEvents != null) {
Yuta HIGUCHI95b20352014-02-24 12:06:27 -0800567 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800568 removeDeviceDiscoveryEvent(deviceEvent);
Yuta HIGUCHI95b20352014-02-24 12:06:27 -0800569 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800570 discoveredAddedDeviceEvents.remove(switchEvent.getDpid());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800571 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800572 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800573 }
574
575 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800576 public void putPortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800577 if (datastore.addPort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800578 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800579 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800580 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800581
582 // Store the new Port Event in the local cache
583 Map<ByteBuffer, PortEvent> oldPortEvents =
584 discoveredAddedPortEvents.get(portEvent.getDpid());
585 if (oldPortEvents == null) {
586 oldPortEvents = new HashMap<>();
587 discoveredAddedPortEvents.put(portEvent.getDpid(),
588 oldPortEvents);
589 }
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800590 ByteBuffer id = portEvent.getIDasByteBuffer();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800591 oldPortEvents.put(id, portEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800592 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800593 }
594
595 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800596 public void removePortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800597 if (datastore.deactivatePort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800598 // Send out notification
599 eventChannel.removeEntry(portEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800600
601 // Cleanup the Port Event from the local cache
602 Map<ByteBuffer, PortEvent> oldPortEvents =
603 discoveredAddedPortEvents.get(portEvent.getDpid());
604 if (oldPortEvents != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800605 ByteBuffer id = portEvent.getIDasByteBuffer();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800606 oldPortEvents.remove(id);
607 }
608
609 // Cleanup for the incoming link
610 Map<ByteBuffer, LinkEvent> oldLinkEvents =
611 discoveredAddedLinkEvents.get(portEvent.getDpid());
612 if (oldLinkEvents != null) {
613 for (LinkEvent linkEvent : oldLinkEvents.values()) {
614 if (linkEvent.getDst().equals(portEvent.id)) {
615 removeLinkDiscoveryEvent(linkEvent);
616 //
617 // NOTE: oldLinkEvents was modified by
618 // removeLinkDiscoveryEvent() and cannot be iterated
619 // anymore.
620 //
Yuta HIGUCHI95b20352014-02-24 12:06:27 -0800621 // XXX If we change our model to allow multiple Link on
622 // a Port, this loop must be fixed to allow continuing.
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800623 break;
624 }
625 }
626 }
627
628 // Cleanup for the connected devices
629 // TODO: The implementation below is probably wrong
630 List<DeviceEvent> removedDeviceEvents = new LinkedList<>();
631 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
632 discoveredAddedDeviceEvents.get(portEvent.getDpid());
633 if (oldDeviceEvents != null) {
Yuta HIGUCHI95b20352014-02-24 12:06:27 -0800634 for (DeviceEvent deviceEvent : new ArrayList<>(oldDeviceEvents.values())) {
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800635 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
636 if (swp.equals(portEvent.id)) {
637 removedDeviceEvents.add(deviceEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800638 }
639 }
640 }
641 for (DeviceEvent deviceEvent : removedDeviceEvents)
642 removeDeviceDiscoveryEvent(deviceEvent);
643 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800644 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800645 }
646
647 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800648 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800649 if (datastore.addLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800650 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800651 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800652 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800653
654 // Store the new Link Event in the local cache
655 Map<ByteBuffer, LinkEvent> oldLinkEvents =
656 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
657 if (oldLinkEvents == null) {
658 oldLinkEvents = new HashMap<>();
659 discoveredAddedLinkEvents.put(linkEvent.getDst().getDpid(),
660 oldLinkEvents);
661 }
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800662 ByteBuffer id = linkEvent.getIDasByteBuffer();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800663 oldLinkEvents.put(id, linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800664 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800665 }
666
667 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800668 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800669 if (datastore.removeLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800670 // Send out notification
671 eventChannel.removeEntry(linkEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800672
673 // Cleanup the Link Event from the local cache
674 Map<ByteBuffer, LinkEvent> oldLinkEvents =
675 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
676 if (oldLinkEvents != null) {
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800677 ByteBuffer id = linkEvent.getIDasByteBuffer();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800678 oldLinkEvents.remove(id);
679 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800680 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800681 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800682
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800683 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800684 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800685 if (datastore.addDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800686 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800687 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800688 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800689
690 // Store the new Device Event in the local cache
691 // TODO: The implementation below is probably wrong
692 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
693 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
694 discoveredAddedDeviceEvents.get(swp.getDpid());
695 if (oldDeviceEvents == null) {
696 oldDeviceEvents = new HashMap<>();
697 discoveredAddedDeviceEvents.put(swp.getDpid(),
698 oldDeviceEvents);
699 }
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800700 ByteBuffer id = deviceEvent.getIDasByteBuffer();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800701 oldDeviceEvents.put(id, deviceEvent);
702 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800703 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800704 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800705
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800706 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800707 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800708 if (datastore.removeDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800709 // Send out notification
710 eventChannel.removeEntry(deviceEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800711
712 // Cleanup the Device Event from the local cache
713 // TODO: The implementation below is probably wrong
714 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
715 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
716 Map<ByteBuffer, DeviceEvent> oldDeviceEvents =
717 discoveredAddedDeviceEvents.get(swp.getDpid());
718 if (oldDeviceEvents != null) {
719 oldDeviceEvents.remove(id);
720 }
721 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800722 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800723 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800724
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800725 /* ************************************************
726 * Internal methods to maintain the network graph
727 * ************************************************/
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800728 private void addSwitch(SwitchEvent switchEvent) {
729 Switch sw = networkGraph.getSwitch(switchEvent.getDpid());
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800730 if (sw == null) {
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800731 sw = new SwitchImpl(networkGraph, switchEvent.getDpid());
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800732 networkGraph.putSwitch(sw);
733 } else {
734 // TODO: Update the switch attributes
735 // TODO: Nothing to do for now
736 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800737 apiAddedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800738 }
739
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800740 private void removeSwitch(SwitchEvent switchEvent) {
741 Switch sw = networkGraph.getSwitch(switchEvent.getDpid());
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800742 if (sw == null) {
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800743 log.warn("Switch {} already removed, ignoring", switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800744 return;
745 }
746
747 //
748 // Remove all Ports on the Switch
749 //
750 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
751 for (Port port : sw.getPorts()) {
752 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800753 port, switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800754 PortEvent portEvent = new PortEvent(port.getDpid(),
755 port.getNumber());
756 portsToRemove.add(portEvent);
757 }
758 for (PortEvent portEvent : portsToRemove)
759 removePort(portEvent);
760
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800761 networkGraph.removeSwitch(switchEvent.getDpid());
762 apiRemovedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800763 }
764
765 private void addPort(PortEvent portEvent) {
766 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
767 if (sw == null) {
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800768 // Reordered event: delay the event in local cache
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800769 ByteBuffer id = portEvent.getIDasByteBuffer();
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800770 reorderedAddedPortEvents.put(id, portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800771 return;
772 }
773 SwitchImpl switchImpl = getSwitchImpl(sw);
774
775 Port port = sw.getPort(portEvent.getNumber());
776 if (port == null) {
777 port = new PortImpl(networkGraph, sw, portEvent.getNumber());
778 switchImpl.addPort(port);
779 } else {
780 // TODO: Update the port attributes
781 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800782 apiAddedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800783 }
784
785 private void removePort(PortEvent portEvent) {
786 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
787 if (sw == null) {
788 log.warn("Parent Switch for Port {} already removed, ignoring",
789 portEvent);
790 return;
791 }
792
793 Port port = sw.getPort(portEvent.getNumber());
794 if (port == null) {
795 log.warn("Port {} already removed, ignoring", portEvent);
796 return;
797 }
798
799 //
800 // Remove all Devices attached to the Port
801 //
802 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
803 for (Device device : port.getDevices()) {
804 log.debug("Removing Device {} on Port {}", device, portEvent);
805 DeviceEvent deviceEvent = new DeviceEvent(device.getMacAddress());
806 SwitchPort switchPort = new SwitchPort(port.getSwitch().getDpid(),
807 port.getNumber());
808 deviceEvent.addAttachmentPoint(switchPort);
809 devicesToRemove.add(deviceEvent);
810 }
811 for (DeviceEvent deviceEvent : devicesToRemove)
812 removeDevice(deviceEvent);
813
814 //
815 // Remove all Links connected to the Port
816 //
817 Set<Link> links = new HashSet<>();
818 links.add(port.getOutgoingLink());
819 links.add(port.getIncomingLink());
820 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
821 for (Link link : links) {
822 if (link == null)
823 continue;
824 log.debug("Removing Link {} on Port {}", link, portEvent);
825 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
826 link.getSrcPort().getNumber(),
827 link.getDstSwitch().getDpid(),
828 link.getDstPort().getNumber());
829 linksToRemove.add(linkEvent);
830 }
831 for (LinkEvent linkEvent : linksToRemove)
832 removeLink(linkEvent);
833
834 // Remove the Port from the Switch
835 SwitchImpl switchImpl = getSwitchImpl(sw);
836 switchImpl.removePort(port);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800837
838 apiRemovedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800839 }
840
841 private void addLink(LinkEvent linkEvent) {
842 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
843 linkEvent.getSrc().number);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800844 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
845 linkEvent.getDst().number);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800846 if ((srcPort == null) || (dstPort == null)) {
847 // Reordered event: delay the event in local cache
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800848 ByteBuffer id = linkEvent.getIDasByteBuffer();
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800849 reorderedAddedLinkEvents.put(id, linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800850 return;
851 }
852
853 // Get the Link instance from the Destination Port Incoming Link
854 Link link = dstPort.getIncomingLink();
855 assert(link == srcPort.getOutgoingLink());
856 if (link == null) {
857 link = new LinkImpl(networkGraph, srcPort, dstPort);
858 PortImpl srcPortImpl = getPortImpl(srcPort);
859 PortImpl dstPortImpl = getPortImpl(dstPort);
860 srcPortImpl.setOutgoingLink(link);
861 dstPortImpl.setIncomingLink(link);
862
863 // Remove all Devices attached to the Ports
864 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
865 ArrayList<Port> ports = new ArrayList<>();
866 ports.add(srcPort);
867 ports.add(dstPort);
868 for (Port port : ports) {
869 for (Device device : port.getDevices()) {
870 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
871 device, port, linkEvent);
872 DeviceEvent deviceEvent =
873 new DeviceEvent(device.getMacAddress());
874 SwitchPort switchPort =
875 new SwitchPort(port.getSwitch().getDpid(),
876 port.getNumber());
877 deviceEvent.addAttachmentPoint(switchPort);
878 devicesToRemove.add(deviceEvent);
879 }
880 }
881 for (DeviceEvent deviceEvent : devicesToRemove)
882 removeDevice(deviceEvent);
883 } else {
884 // TODO: Update the link attributes
885 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800886
887 apiAddedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800888 }
889
890 private void removeLink(LinkEvent linkEvent) {
891 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
892 linkEvent.getSrc().number);
893 if (srcPort == null) {
894 log.warn("Src Port for Link {} already removed, ignoring",
895 linkEvent);
896 return;
897 }
898
899 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
900 linkEvent.getDst().number);
901 if (dstPort == null) {
902 log.warn("Dst Port for Link {} already removed, ignoring",
903 linkEvent);
904 return;
905 }
906
907 //
908 // Remove the Link instance from the Destination Port Incoming Link
909 // and the Source Port Outgoing Link.
910 //
911 Link link = dstPort.getIncomingLink();
912 if (link == null) {
913 log.warn("Link {} already removed on destination Port", linkEvent);
914 }
915 link = srcPort.getOutgoingLink();
916 if (link == null) {
917 log.warn("Link {} already removed on src Port", linkEvent);
918 }
919 getPortImpl(dstPort).setIncomingLink(null);
920 getPortImpl(srcPort).setOutgoingLink(null);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800921
922 apiRemovedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800923 }
924
925 // TODO: Device-related work is incomplete
926 private void addDevice(DeviceEvent deviceEvent) {
927 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
928 if (device == null) {
929 device = new DeviceImpl(networkGraph, deviceEvent.getMac());
930 }
931 DeviceImpl deviceImpl = getDeviceImpl(device);
932
933 // Update the IP addresses
934 for (InetAddress ipAddr : deviceEvent.getIpAddresses())
935 deviceImpl.addIpAddress(ipAddr);
936
937 // Process each attachment point
938 boolean attachmentFound = false;
939 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
940 // Attached Ports must exist
941 Port port = networkGraph.getPort(swp.dpid, swp.number);
942 if (port == null) {
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800943 // Reordered event: delay the event in local cache
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800944 ByteBuffer id = deviceEvent.getIDasByteBuffer();
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800945 reorderedAddedDeviceEvents.put(id, deviceEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800946 continue;
947 }
948 // Attached Ports must not have Link
949 if (port.getOutgoingLink() != null ||
950 port.getIncomingLink() != null) {
951 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
952 port.getOutgoingLink(),
953 port.getIncomingLink());
954 continue;
955 }
956
957 // Add Device <-> Port attachment
958 PortImpl portImpl = getPortImpl(port);
959 portImpl.addDevice(device);
960 deviceImpl.addAttachmentPoint(port);
961 attachmentFound = true;
962 }
963
964 // Update the device in the Network Graph
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800965 if (attachmentFound) {
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800966 networkGraph.putDevice(device);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800967 apiAddedDeviceEvents.add(deviceEvent);
968 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800969 }
970
971 private void removeDevice(DeviceEvent deviceEvent) {
972 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
973 if (device == null) {
974 log.warn("Device {} already removed, ignoring", deviceEvent);
975 return;
976 }
977 DeviceImpl deviceImpl = getDeviceImpl(device);
978
979 // Process each attachment point
980 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
981 // Attached Ports must exist
982 Port port = networkGraph.getPort(swp.dpid, swp.number);
983 if (port == null) {
984 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
985 continue;
986 }
987
988 // Remove Device <-> Port attachment
989 PortImpl portImpl = getPortImpl(port);
990 portImpl.removeDevice(device);
991 deviceImpl.removeAttachmentPoint(port);
992 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800993
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800994 networkGraph.removeDevice(device);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800995 apiRemovedDeviceEvents.add(deviceEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800996 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800997
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800998 /**
999 *
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001000 * @param switchEvent
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001001 * @return true if ready to accept event.
1002 */
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001003 private boolean prepareForAddSwitchEvent(SwitchEvent switchEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001004 // No show stopping precondition
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001005 return true;
1006 }
Jonathan Hart22eb9882014-02-11 15:52:59 -08001007
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001008 private boolean prepareForRemoveSwitchEvent(SwitchEvent switchEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001009 // No show stopping precondition
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001010 return true;
1011 }
Yuta HIGUCHI71e7a052014-02-17 22:14:15 -08001012
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001013 private boolean prepareForAddPortEvent(PortEvent portEvent) {
1014 // Parent Switch must exist
1015 if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
1016 log.warn("Dropping add port event because switch doesn't exist: {}",
1017 portEvent);
1018 return false;
1019 }
1020 // Prep: None
1021 return true;
1022 }
1023
1024 private boolean prepareForRemovePortEvent(PortEvent portEvent) {
1025 Port port = networkGraph.getPort(portEvent.getDpid(),
1026 portEvent.getNumber());
1027 if (port == null) {
1028 log.debug("Port already removed? {}", portEvent);
1029 // let it pass
1030 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -08001031 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -08001032
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001033 // Prep: Remove Link and Device Attachment
1034 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
1035 for (Device device : port.getDevices()) {
1036 log.debug("Removing Device {} on Port {}", device, portEvent);
1037 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
1038 devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
1039 port.getNumber()));
1040 deviceEvents.add(devEvent);
1041 }
1042 for (DeviceEvent devEvent : deviceEvents) {
1043 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -08001044 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -08001045 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -08001046
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001047 Set<Link> links = new HashSet<>();
1048 links.add(port.getOutgoingLink());
1049 links.add(port.getIncomingLink());
1050 for (Link link : links) {
1051 if (link == null) {
1052 continue;
1053 }
1054 log.debug("Removing Link {} on Port {}", link, portEvent);
1055 LinkEvent linkEvent =
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -08001056 new LinkEvent(link.getSrcSwitch().getDpid(),
1057 link.getSrcPort().getNumber(),
1058 link.getDstSwitch().getDpid(),
1059 link.getDstPort().getNumber());
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001060 // calling Discovery API to wipe from DB, etc.
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08001061
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001062 // Call internal remove Link, which will check
1063 // ownership of DST dpid and modify DB only if it is the owner
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -08001064 removeLinkDiscoveryEvent(linkEvent, true);
Jonathan Hart22eb9882014-02-11 15:52:59 -08001065 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001066 return true;
1067 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -08001068
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001069 private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
1070 // Src/Dst Port must exist
1071 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
1072 linkEvent.getSrc().number);
1073 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
1074 linkEvent.getDst().number);
1075 if (srcPort == null || dstPort == null) {
Jonathan Hart0a4846e2014-02-18 11:03:40 -08001076 log.warn("Dropping add link event because port doesn't exist: {}",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001077 linkEvent);
1078 return false;
Jonathan Hart22eb9882014-02-11 15:52:59 -08001079 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -08001080
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001081 // Prep: remove Device attachment on both Ports
1082 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
1083 for (Device device : srcPort.getDevices()) {
1084 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
1085 devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
1086 deviceEvents.add(devEvent);
1087 }
1088 for (Device device : dstPort.getDevices()) {
1089 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
1090 devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
1091 dstPort.getNumber()));
1092 deviceEvents.add(devEvent);
1093 }
1094 for (DeviceEvent devEvent : deviceEvents) {
1095 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -08001096 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -08001097 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -08001098
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001099 return true;
1100 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -08001101
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001102 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
1103 // Src/Dst Port must exist
1104 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
1105 linkEvent.getSrc().number);
1106 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
1107 linkEvent.getDst().number);
1108 if (srcPort == null || dstPort == null) {
1109 log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
1110 return false;
1111 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08001112
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001113 Link link = srcPort.getOutgoingLink();
1114
1115 // Link is already gone, or different Link exist in memory
1116 // XXX Check if we should reject or just accept these cases.
1117 // it should be harmless to remove the Link on event from DB anyways
1118 if (link == null ||
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -08001119 !link.getDstPort().getNumber().equals(linkEvent.getDst().number)
1120 || !link.getDstSwitch().getDpid().equals(linkEvent.getDst().dpid)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001121 log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
1122 return false;
1123 }
1124 // Prep: None
1125 return true;
1126 }
1127
1128 /**
1129 *
1130 * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
1131 * @return false if this event should be dropped.
1132 */
1133 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
1134 boolean preconditionBroken = false;
1135 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
1136 for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
1137 // Attached Ports must exist
1138 Port port = networkGraph.getPort(swp.dpid, swp.number);
1139 if (port == null) {
1140 preconditionBroken = true;
1141 failedSwitchPort.add(swp);
1142 continue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08001143 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001144 // Attached Ports must not have Link
1145 if (port.getOutgoingLink() != null ||
1146 port.getIncomingLink() != null) {
1147 preconditionBroken = true;
1148 failedSwitchPort.add(swp);
1149 continue;
1150 }
1151 }
1152
1153 // Rewriting event to exclude failed attachmentPoint
1154 // XXX Assumption behind this is that inapplicable device event should
1155 // be dropped, not deferred. If we decide to defer Device event,
1156 // rewriting can become a problem
1157 List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
1158 attachmentPoints.removeAll(failedSwitchPort);
1159 deviceEvent.setAttachmentPoints(attachmentPoints);
1160
1161 if (deviceEvent.getAttachmentPoints().isEmpty() &&
1162 deviceEvent.getIpAddresses().isEmpty()) {
1163 // return false to represent: Nothing left to do for this event.
1164 // Caller should drop event
1165 return false;
1166 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08001167
1168 // Should we return false to tell caller that the event was trimmed?
1169 // if ( preconditionBroken ) {
1170 // return false;
1171 // }
1172
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001173 return true;
1174 }
1175
1176 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
1177 // No show stopping precondition?
1178 // Prep: none
1179 return true;
1180 }
1181
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001182 private SwitchImpl getSwitchImpl(Switch sw) {
1183 if (sw instanceof SwitchImpl) {
1184 return (SwitchImpl) sw;
1185 }
1186 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
1187 }
1188
1189 private PortImpl getPortImpl(Port p) {
1190 if (p instanceof PortImpl) {
1191 return (PortImpl) p;
1192 }
1193 throw new ClassCastException("PortImpl expected, but found: " + p);
1194 }
1195
1196 private LinkImpl getLinkImpl(Link l) {
1197 if (l instanceof LinkImpl) {
1198 return (LinkImpl) l;
1199 }
1200 throw new ClassCastException("LinkImpl expected, but found: " + l);
1201 }
1202
1203 private DeviceImpl getDeviceImpl(Device d) {
1204 if (d instanceof DeviceImpl) {
1205 return (DeviceImpl) d;
1206 }
1207 throw new ClassCastException("DeviceImpl expected, but found: " + d);
1208 }
1209
1210 @Deprecated
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001211 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
1212 Collection<EventEntry<TopologyEvent>> collection =
1213 new LinkedList<EventEntry<TopologyEvent>>();
1214
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001215 // XXX May need to clear whole topology first, depending on
1216 // how we initially subscribe to replication events
1217
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001218 // Add all active switches
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001219 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
1220 if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
1221 continue;
1222 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001223
1224 SwitchEvent switchEvent = new SwitchEvent(sw.getDpid());
1225 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
1226 EventEntry<TopologyEvent> eventEntry =
1227 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1228 topologyEvent);
1229 collection.add(eventEntry);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001230 }
1231
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001232 // Add all active ports
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001233 for (RCPort p : RCPort.getAllPorts()) {
1234 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1235 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001236 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001237
1238 PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
1239 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
1240 EventEntry<TopologyEvent> eventEntry =
1241 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1242 topologyEvent);
1243 collection.add(eventEntry);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001244 }
1245
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001246 // TODO Is Device going to be in DB? If so, read from DB.
1247 // for (RCDevice d : RCDevice.getAllDevices()) {
1248 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
1249 // for (byte[] portId : d.getAllPortIds() ) {
1250 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
1251 // }
1252 // }
1253
1254 for (RCLink l : RCLink.getAllLinks()) {
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001255 LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
1256 l.getSrc().number,
1257 l.getDst().dpid,
1258 l.getDst().number);
1259 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
1260 EventEntry<TopologyEvent> eventEntry =
1261 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1262 topologyEvent);
1263 collection.add(eventEntry);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001264 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001265
1266 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001267 }
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -08001268
1269 @Deprecated
1270 private void removeLinkDiscoveryEvent(LinkEvent linkEvent,
1271 boolean dstCheckBeforeDBmodify) {
1272 if (prepareForRemoveLinkEvent(linkEvent)) {
1273 if (dstCheckBeforeDBmodify) {
1274 // write to DB only if it is owner of the dst dpid
1275 // XXX this will cause link remove events to be dropped
1276 // if the dst switch just disconnected
1277 if (registryService.hasControl(linkEvent.getDst().dpid)) {
1278 datastore.removeLink(linkEvent);
1279 }
1280 } else {
1281 datastore.removeLink(linkEvent);
1282 }
1283 removeLink(linkEvent);
1284 // Send out notification
1285 eventChannel.removeEntry(linkEvent.getID());
1286 }
1287 // TODO handle invariant violation
1288 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001289}