blob: 25a322bdd69c8cb57673bcbc04306cfae7df1176 [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;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08004import java.util.ArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08005import java.util.Collection;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08006import java.util.HashSet;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08007import java.util.LinkedList;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08008import java.util.List;
9import java.util.Set;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080010import java.util.concurrent.BlockingQueue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080011import java.util.concurrent.CopyOnWriteArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080012import java.util.concurrent.LinkedBlockingQueue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080013
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080014import net.onrc.onos.datagrid.IDatagridService;
15import net.onrc.onos.datagrid.IEventChannel;
16import net.onrc.onos.datagrid.IEventChannelListener;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080017import net.onrc.onos.datastore.topology.RCLink;
Jonathan Hart062a2e82014-02-03 09:41:57 -080018import net.onrc.onos.datastore.topology.RCPort;
19import net.onrc.onos.datastore.topology.RCSwitch;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080020import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080021import net.onrc.onos.ofcontroller.util.EventEntry;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080022import net.onrc.onos.ofcontroller.util.Dpid;
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080023import net.onrc.onos.registry.controller.IControllerRegistryService;
Jonathan Hart062a2e82014-02-03 09:41:57 -080024
25import org.slf4j.Logger;
26import org.slf4j.LoggerFactory;
27
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080028/**
29 * The "NB" read-only Network Map.
30 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080031 * - Maintain Invariant/Relationships between Topology Objects.
32 *
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080033 * TODO To be synchronized based on TopologyEvent Notification.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080034 *
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080035 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
Yuta HIGUCHI1c700102014-02-12 16:30:52 -080036 * Object must exist before adding sub component(Add Switch -> Port).
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080037 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080038 * TODO TBD: This class may delay the requested change to handle event
39 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080040 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080041 */
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080042public class TopologyManager implements NetworkGraphDiscoveryInterface,
43 NetworkGraphReplicationInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080044
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080045 private static final Logger log = LoggerFactory
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -080046 .getLogger(TopologyManager.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080047
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080048 private IEventChannel<byte[], TopologyEvent> eventChannel;
49 private static final String EVENT_CHANNEL_NAME = "onos.topology";
50 private EventHandler eventHandler = new EventHandler();
51
Jonathan Hart22eb9882014-02-11 15:52:59 -080052 private final NetworkGraphDatastore datastore;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080053 private final NetworkGraphImpl networkGraph = new NetworkGraphImpl();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080054 private final IControllerRegistryService registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080055 private CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners;
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080056
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080057 /**
58 * Constructor.
59 *
60 * @param registryService the Registry Service to use.
61 * @param networkGraphListeners the collection of Network Graph Listeners
62 * to use.
63 */
64 public TopologyManager(IControllerRegistryService registryService,
65 CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners) {
Jonathan Hart22eb9882014-02-11 15:52:59 -080066 datastore = new NetworkGraphDatastore(this);
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080067 this.registryService = registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080068 this.networkGraphListeners = networkGraphListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080069 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080070
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080071 /**
72 * Get the Network Graph.
73 *
74 * @return the Network Graph.
75 */
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080076 NetworkGraph getNetworkGraph() {
77 return networkGraph;
78 }
79
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080080 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080081 * Event handler class.
82 */
83 private class EventHandler extends Thread implements
84 IEventChannelListener<byte[], TopologyEvent> {
85 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
86 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
87
88 /**
89 * Startup processing.
90 */
91 private void startup() {
92 //
93 // TODO: Read all state from the database
94 // For now, as a shortcut we read it from the datagrid
95 //
96 Collection<TopologyEvent> topologyEvents =
97 eventChannel.getAllEntries();
98 Collection<EventEntry<TopologyEvent>> collection =
99 new LinkedList<EventEntry<TopologyEvent>>();
100
101 for (TopologyEvent topologyEvent : topologyEvents) {
102 EventEntry<TopologyEvent> eventEntry =
103 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
104 topologyEvent);
105 collection.add(eventEntry);
106 }
107 processEvents(collection);
108 }
109
110 /**
111 * Run the thread.
112 */
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800113 @Override
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800114 public void run() {
115 Collection<EventEntry<TopologyEvent>> collection =
116 new LinkedList<EventEntry<TopologyEvent>>();
117
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -0800118 this.setName("TopologyManager.EventHandler " + this.getId());
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800119 startup();
120
121 //
122 // The main loop
123 //
124 try {
125 while (true) {
126 EventEntry<TopologyEvent> eventEntry = topologyEvents.take();
127 collection.add(eventEntry);
128 topologyEvents.drainTo(collection);
129
130 processEvents(collection);
131 collection.clear();
132 }
133 } catch (Exception exception) {
134 log.debug("Exception processing Topology Events: ", exception);
135 }
136 }
137
138 /**
139 * Process all topology events.
140 *
141 * @param events the events to process.
142 */
143 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
144 for (EventEntry<TopologyEvent> event : events) {
Yuta HIGUCHI170229f2014-02-17 15:47:54 -0800145 if (event.eventData().getOriginID().equals(registryService.getControllerId())) {
146 // ignore event triggered by myself
147 continue;
148 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800149 TopologyEvent topologyEvent = event.eventData();
150 switch (event.eventType()) {
151 case ENTRY_ADD:
152 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
153 if (topologyEvent.switchEvent != null)
154 putSwitchReplicationEvent(topologyEvent.switchEvent);
155 if (topologyEvent.portEvent != null)
156 putPortReplicationEvent(topologyEvent.portEvent);
157 if (topologyEvent.linkEvent != null)
158 putLinkReplicationEvent(topologyEvent.linkEvent);
159 if (topologyEvent.deviceEvent != null)
160 putDeviceReplicationEvent(topologyEvent.deviceEvent);
161 break;
162 case ENTRY_REMOVE:
163 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
164 if (topologyEvent.switchEvent != null)
165 removeSwitchReplicationEvent(topologyEvent.switchEvent);
166 if (topologyEvent.portEvent != null)
167 removePortReplicationEvent(topologyEvent.portEvent);
168 if (topologyEvent.linkEvent != null)
169 removeLinkReplicationEvent(topologyEvent.linkEvent);
170 if (topologyEvent.deviceEvent != null)
171 removeDeviceReplicationEvent(topologyEvent.deviceEvent);
172 break;
173 }
174 }
175 }
176
177 /**
178 * Receive a notification that an entry is added.
179 *
180 * @param value the value for the entry.
181 */
182 @Override
183 public void entryAdded(TopologyEvent value) {
184 EventEntry<TopologyEvent> eventEntry =
185 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
186 value);
187 topologyEvents.add(eventEntry);
188 }
189
190 /**
191 * Receive a notification that an entry is removed.
192 *
193 * @param value the value for the entry.
194 */
195 @Override
196 public void entryRemoved(TopologyEvent value) {
197 EventEntry<TopologyEvent> eventEntry =
198 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
199 value);
200 topologyEvents.add(eventEntry);
201 }
202
203 /**
204 * Receive a notification that an entry is updated.
205 *
206 * @param value the value for the entry.
207 */
208 @Override
209 public void entryUpdated(TopologyEvent value) {
210 // NOTE: The ADD and UPDATE events are processed in same way
211 entryAdded(value);
212 }
213 }
214
215 /**
216 * Startup processing.
217 *
218 * @param datagridService the datagrid service to use.
219 */
220 void startup(IDatagridService datagridService) {
221 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
222 eventHandler,
223 byte[].class,
224 TopologyEvent.class);
225 eventHandler.start();
226 }
227
228 /**
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800229 * Exception to be thrown when Modification to the Network Graph cannot be
230 * continued due to broken invariant.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800231 *
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800232 * XXX Should this be checked exception or RuntimeException?
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800233 */
234 public static class BrokenInvariantException extends RuntimeException {
235 private static final long serialVersionUID = 1L;
236
237 public BrokenInvariantException() {
238 super();
239 }
240
241 public BrokenInvariantException(String message) {
242 super(message);
243 }
244 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800245
246 /* ******************************
247 * NetworkGraphDiscoveryInterface methods
248 * ******************************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800249
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800250 @Override
251 public void putSwitchEvent(SwitchEvent switchEvent) {
252 if (prepareForAddSwitchEvent(switchEvent)) {
253 datastore.addSwitch(switchEvent);
254 putSwitch(switchEvent);
255 // Send out notification
256 TopologyEvent topologyEvent =
257 new TopologyEvent(switchEvent, registryService.getControllerId());
258 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
259 }
260 // TODO handle invariant violation
261 }
262
263 @Override
264 public void removeSwitchEvent(SwitchEvent switchEvent) {
265 if (prepareForRemoveSwitchEvent(switchEvent)) {
266 datastore.deactivateSwitch(switchEvent);
267 removeSwitch(switchEvent);
268 // Send out notification
269 eventChannel.removeEntry(switchEvent.getID());
270 }
271 // TODO handle invariant violation
272 }
273
274 @Override
275 public void putPortEvent(PortEvent portEvent) {
276 if (prepareForAddPortEvent(portEvent)) {
277 datastore.addPort(portEvent);
278 putPort(portEvent);
279 // Send out notification
280 TopologyEvent topologyEvent =
281 new TopologyEvent(portEvent, registryService.getControllerId());
282 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
283 }
284 // TODO handle invariant violation
285 }
286
287 @Override
288 public void removePortEvent(PortEvent portEvent) {
289 if (prepareForRemovePortEvent(portEvent)) {
290 datastore.deactivatePort(portEvent);
291 removePort(portEvent);
292 // Send out notification
293 eventChannel.removeEntry(portEvent.getID());
294 }
295 // TODO handle invariant violation
296 }
297
298 @Override
299 public void putLinkEvent(LinkEvent linkEvent) {
300 if (prepareForAddLinkEvent(linkEvent)) {
301 datastore.addLink(linkEvent);
302 putLink(linkEvent);
303 // Send out notification
304 TopologyEvent topologyEvent =
305 new TopologyEvent(linkEvent, registryService.getControllerId());
306 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
307 }
308 // TODO handle invariant violation
309 }
310
311 @Override
312 public void removeLinkEvent(LinkEvent linkEvent) {
313 removeLinkEvent(linkEvent, false);
314 }
315
316 private void removeLinkEvent(LinkEvent linkEvent,
317 boolean dstCheckBeforeDBmodify) {
318 if (prepareForRemoveLinkEvent(linkEvent)) {
319 if (dstCheckBeforeDBmodify) {
320 // write to DB only if it is owner of the dst dpid
321 if (registryService.hasControl(linkEvent.getDst().dpid)) {
322 datastore.removeLink(linkEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800323 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800324 } else {
325 datastore.removeLink(linkEvent);
326 }
327 removeLink(linkEvent);
328 // Send out notification
329 eventChannel.removeEntry(linkEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800330 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800331 // TODO handle invariant violation
332 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800333
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800334 @Override
335 public void putDeviceEvent(DeviceEvent deviceEvent) {
336 if (prepareForAddDeviceEvent(deviceEvent)) {
337// datastore.addDevice(deviceEvent);
338// putDevice(deviceEvent);
339 // Send out notification
340 TopologyEvent topologyEvent =
341 new TopologyEvent(deviceEvent,
342 registryService.getControllerId());
343 eventChannel.addEntry(topologyEvent.getID(),
344 topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800345 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800346 // TODO handle invariant violation
347 // XXX if prepareFor~ method returned false, event should be dropped
348 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800349
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800350 @Override
351 public void removeDeviceEvent(DeviceEvent deviceEvent) {
352 if (prepareForRemoveDeviceEvent(deviceEvent)) {
353// datastore.removeDevice(deviceEvent);
354// removeDevice(deviceEvent);
355 // Send out notification
356 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800357 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800358 // TODO handle invariant violation
359 // XXX if prepareFor~ method returned false, event should be dropped
360 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800361
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800362 /* *****************
363 * Internal methods to maintain invariants of the network graph
364 * *****************/
Jonathan Hart22eb9882014-02-11 15:52:59 -0800365
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800366 /**
367 *
368 * @param swEvent
369 * @return true if ready to accept event.
370 */
371 private boolean prepareForAddSwitchEvent(SwitchEvent swEvent) {
372 // No show stopping precondition
373 // Prep: remove(deactivate) Ports on Switch, which is not on event
374 removePortsNotOnEvent(swEvent);
375 return true;
376 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800377
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800378 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvent) {
379 // No show stopping precondition
380 // Prep: remove(deactivate) Ports on Switch, which is not on event
381 // XXX may be remove switch should imply wipe all ports
382 removePortsNotOnEvent(swEvent);
383 return true;
384 }
Yuta HIGUCHI71e7a052014-02-17 22:14:15 -0800385
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800386 private void removePortsNotOnEvent(SwitchEvent swEvent) {
387 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
388 if (sw != null) {
389 Set<Long> port_noOnEvent = new HashSet<>();
390 for (PortEvent portEvent : swEvent.getPorts()) {
391 port_noOnEvent.add(portEvent.getNumber());
392 }
393 // Existing ports not on event should be removed.
394 // TODO Should batch eventually for performance?
395 List<Port> portsToRemove = new ArrayList<Port>();
396 for (Port p : sw.getPorts()) {
397 if (!port_noOnEvent.contains(p.getNumber())) {
398 //PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
399 // calling Discovery removePort() API to wipe from DB, etc.
400 //removePortEvent(rmEvent);
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800401
Jonathan Hart480c5572014-02-14 18:28:16 -0800402 // We can't remove ports here because this will trigger a remove
403 // from the switch's port list, which we are currently iterating
404 // over.
405 portsToRemove.add(p);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800406 }
407 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800408 for (Port p : portsToRemove) {
409 PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(),
410 p.getNumber());
411 // calling Discovery removePort() API to wipe from DB, etc.
412 removePortEvent(rmEvent);
413 }
414 }
415 }
416
417 private boolean prepareForAddPortEvent(PortEvent portEvent) {
418 // Parent Switch must exist
419 if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
420 log.warn("Dropping add port event because switch doesn't exist: {}",
421 portEvent);
422 return false;
423 }
424 // Prep: None
425 return true;
426 }
427
428 private boolean prepareForRemovePortEvent(PortEvent portEvent) {
429 Port port = networkGraph.getPort(portEvent.getDpid(),
430 portEvent.getNumber());
431 if (port == null) {
432 log.debug("Port already removed? {}", portEvent);
433 // let it pass
434 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800435 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800436
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800437 // Prep: Remove Link and Device Attachment
438 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
439 for (Device device : port.getDevices()) {
440 log.debug("Removing Device {} on Port {}", device, portEvent);
441 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
442 devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
443 port.getNumber()));
444 deviceEvents.add(devEvent);
445 }
446 for (DeviceEvent devEvent : deviceEvents) {
447 // calling Discovery API to wipe from DB, etc.
448 removeDeviceEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800449 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800450
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800451 Set<Link> links = new HashSet<>();
452 links.add(port.getOutgoingLink());
453 links.add(port.getIncomingLink());
454 for (Link link : links) {
455 if (link == null) {
456 continue;
457 }
458 log.debug("Removing Link {} on Port {}", link, portEvent);
459 LinkEvent linkEvent =
460 new LinkEvent(link.getSourceSwitchDpid(),
461 link.getSourcePortNumber(),
462 link.getDestinationSwitchDpid(),
463 link.getDestinationPortNumber());
464 // calling Discovery API to wipe from DB, etc.
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800465
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800466 // Call internal remove Link, which will check
467 // ownership of DST dpid and modify DB only if it is the owner
468 removeLinkEvent(linkEvent, true);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800469 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800470 return true;
471 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800472
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800473 private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
474 // Src/Dst Port must exist
475 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
476 linkEvent.getSrc().number);
477 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
478 linkEvent.getDst().number);
479 if (srcPort == null || dstPort == null) {
Jonathan Hart0a4846e2014-02-18 11:03:40 -0800480 log.warn("Dropping add link event because port doesn't exist: {}",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800481 linkEvent);
482 return false;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800483 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800484
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800485 // Prep: remove Device attachment on both Ports
486 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
487 for (Device device : srcPort.getDevices()) {
488 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
489 devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
490 deviceEvents.add(devEvent);
491 }
492 for (Device device : dstPort.getDevices()) {
493 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
494 devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
495 dstPort.getNumber()));
496 deviceEvents.add(devEvent);
497 }
498 for (DeviceEvent devEvent : deviceEvents) {
499 // calling Discovery API to wipe from DB, etc.
500 removeDeviceEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800501 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800502
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800503 return true;
504 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800505
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800506 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
507 // Src/Dst Port must exist
508 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
509 linkEvent.getSrc().number);
510 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
511 linkEvent.getDst().number);
512 if (srcPort == null || dstPort == null) {
513 log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
514 return false;
515 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800516
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800517 Link link = srcPort.getOutgoingLink();
518
519 // Link is already gone, or different Link exist in memory
520 // XXX Check if we should reject or just accept these cases.
521 // it should be harmless to remove the Link on event from DB anyways
522 if (link == null ||
523 !link.getDestinationPortNumber().equals(linkEvent.getDst().number)
524 || !link.getDestinationSwitchDpid().equals(linkEvent.getDst().dpid)) {
525 log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
526 return false;
527 }
528 // Prep: None
529 return true;
530 }
531
532 /**
533 *
534 * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
535 * @return false if this event should be dropped.
536 */
537 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
538 boolean preconditionBroken = false;
539 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
540 for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
541 // Attached Ports must exist
542 Port port = networkGraph.getPort(swp.dpid, swp.number);
543 if (port == null) {
544 preconditionBroken = true;
545 failedSwitchPort.add(swp);
546 continue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800547 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800548 // Attached Ports must not have Link
549 if (port.getOutgoingLink() != null ||
550 port.getIncomingLink() != null) {
551 preconditionBroken = true;
552 failedSwitchPort.add(swp);
553 continue;
554 }
555 }
556
557 // Rewriting event to exclude failed attachmentPoint
558 // XXX Assumption behind this is that inapplicable device event should
559 // be dropped, not deferred. If we decide to defer Device event,
560 // rewriting can become a problem
561 List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
562 attachmentPoints.removeAll(failedSwitchPort);
563 deviceEvent.setAttachmentPoints(attachmentPoints);
564
565 if (deviceEvent.getAttachmentPoints().isEmpty() &&
566 deviceEvent.getIpAddresses().isEmpty()) {
567 // return false to represent: Nothing left to do for this event.
568 // Caller should drop event
569 return false;
570 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800571
572 // Should we return false to tell caller that the event was trimmed?
573 // if ( preconditionBroken ) {
574 // return false;
575 // }
576
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800577 return true;
578 }
579
580 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
581 // No show stopping precondition?
582 // Prep: none
583 return true;
584 }
585
586 /* ******************************
587 * NetworkGraphReplicationInterface methods
588 * ******************************/
589
590 @Override
591 public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
592 if (prepareForAddSwitchEvent(switchEvent)) {
593 putSwitch(switchEvent);
594 }
595 // TODO handle invariant violation
596 // trigger instance local topology event handler
597 dispatchPutSwitchEvent(switchEvent);
598 }
599
600 @Override
601 public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
602 if (prepareForRemoveSwitchEvent(switchEvent)) {
603 removeSwitch(switchEvent);
604 }
605 // TODO handle invariant violation
606 // trigger instance local topology event handler
607 dispatchRemoveSwitchEvent(switchEvent);
608 }
609
610 @Override
611 public void putPortReplicationEvent(PortEvent portEvent) {
612 if (prepareForAddPortEvent(portEvent)) {
613 putPort(portEvent);
614 }
615 // TODO handle invariant violation
616 // trigger instance local topology event handler
617 dispatchPutPortEvent(portEvent);
618 }
619
620 @Override
621 public void removePortReplicationEvent(PortEvent portEvent) {
622 if (prepareForRemovePortEvent(portEvent)) {
623 removePort(portEvent);
624 }
625 // TODO handle invariant violation
626 // trigger instance local topology event handler
627 dispatchRemovePortEvent(portEvent);
628 }
629
630 @Override
631 public void putLinkReplicationEvent(LinkEvent linkEvent) {
632 if (prepareForAddLinkEvent(linkEvent)) {
633 putLink(linkEvent);
634 }
635 // TODO handle invariant violation
636 // trigger instance local topology event handler
637 dispatchPutLinkEvent(linkEvent);
638 }
639
640 @Override
641 public void removeLinkReplicationEvent(LinkEvent linkEvent) {
642 if (prepareForRemoveLinkEvent(linkEvent)) {
643 removeLink(linkEvent);
644 }
645 // TODO handle invariant violation
646 // trigger instance local topology event handler
647 dispatchRemoveLinkEvent(linkEvent);
648 }
649
650 @Override
651 public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
652 if (prepareForAddDeviceEvent(deviceEvent)) {
653 putDevice(deviceEvent);
654 }
655 // TODO handle invariant violation
656 // trigger instance local topology event handler
657 dispatchPutDeviceEvent(deviceEvent);
658 }
659
660 @Override
661 public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
662 if (prepareForRemoveDeviceEvent(deviceEvent)) {
663 removeDevice(deviceEvent);
664 }
665 // TODO handle invariant violation
666 // trigger instance local topology event handler
667 dispatchRemoveDeviceEvent(deviceEvent);
668 }
669
670 /* ************************************************
671 * Internal In-memory object mutation methods.
672 * ************************************************/
673
674 void putSwitch(SwitchEvent swEvent) {
675 if (swEvent == null) {
676 throw new IllegalArgumentException("Switch cannot be null");
Jonathan Hart22eb9882014-02-11 15:52:59 -0800677 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800678
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800679 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
680
681 if (sw == null) {
682 sw = new SwitchImpl(networkGraph, swEvent.getDpid());
683 networkGraph.putSwitch(sw);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800684 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800685
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800686 // Update when more attributes are added to Event object
687 // no attribute to update for now
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800688
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800689 // TODO handle child Port event properly for performance
690 for (PortEvent portEvent : swEvent.getPorts() ) {
691 putPort(portEvent);
692 }
693 }
694
695 void removeSwitch(SwitchEvent swEvent) {
696 if (swEvent == null) {
697 throw new IllegalArgumentException("Switch cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800698 }
699
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800700 // TODO handle child Port event properly for performance
701 for (PortEvent portEvent : swEvent.getPorts() ) {
702 removePort(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800703 }
704
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800705 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
706 if (sw == null) {
707 log.warn("Switch {} already removed, ignoring", swEvent);
708 return;
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800709 }
710
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800711 // remove all ports if there still exist
712 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
713 for (Port port : sw.getPorts()) {
714 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now",
715 port, swEvent);
716 PortEvent portEvent = new PortEvent(port.getDpid(),
717 port.getNumber());
718 portsToRemove.add(portEvent);
719 }
720 for (PortEvent portEvent : portsToRemove) {
721 // XXX calling removePortEvent() may trigger duplicate event,
722 // once at prepare phase, second time here
723 // If event can be squashed, ignored etc. at receiver side it
724 // shouldn't be a problem, but if not need to re-visit this issue.
725
726 // Note: removePortEvent() implies removal of attached Device, etc.
727 // if we decide not to call removePortEvent(), Device needs to be
728 // handled properly
729 removePortEvent(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800730 }
731
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800732 networkGraph.removeSwitch(swEvent.getDpid());
733 }
734
735 void putPort(PortEvent portEvent) {
736 if (portEvent == null) {
737 throw new IllegalArgumentException("Port cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800738 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800739 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
740 if (sw == null) {
741 throw new BrokenInvariantException(String.format(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800742 "Switch with dpid %s did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800743 new Dpid(portEvent.getDpid())));
744 }
745 Port p = sw.getPort(portEvent.getNumber());
746 PortImpl port = null;
747 if (p != null) {
748 port = getPortImpl(p);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800749 }
750
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800751 if (port == null) {
752 port = new PortImpl(networkGraph, sw, portEvent.getNumber());
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800753 }
754
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800755 // TODO update attributes
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800756
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800757 SwitchImpl s = getSwitchImpl(sw);
758 s.addPort(port);
759 }
760
761 void removePort(PortEvent portEvent) {
762 if (portEvent == null) {
763 throw new IllegalArgumentException("Port cannot be null");
764 }
765
766 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
767 if (sw == null) {
768 log.warn("Parent Switch for Port {} already removed, ignoring",
769 portEvent);
770 return;
771 }
772
773 Port p = sw.getPort(portEvent.getNumber());
774 if (p == null) {
775 log.warn("Port {} already removed, ignoring", portEvent);
776 return;
777 }
778
779 // Remove Link and Device Attachment
780 for (Device device : p.getDevices()) {
781 log.debug("Removing Device {} on Port {}", device, portEvent);
782 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
783 devEvent.addAttachmentPoint(new SwitchPort(p.getSwitch().getDpid(),
784 p.getNumber()));
785
786 // XXX calling removeDeviceEvent() may trigger duplicate event,
787 // once at prepare phase, second time here
788 // If event can be squashed, ignored etc. at receiver side it
789 // shouldn't be a problem, but if not need to re-visit
790
791 // calling Discovery API to wipe from DB, etc.
792 removeDeviceEvent(devEvent);
793 }
794 Set<Link> links = new HashSet<>();
795 links.add(p.getOutgoingLink());
796 links.add(p.getIncomingLink());
797 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
798 for (Link link : links) {
799 if (link == null) {
800 continue;
801 }
802 log.debug("Removing Link {} on Port {}", link, portEvent);
803 LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(),
804 link.getSourcePortNumber(),
805 link.getDestinationSwitchDpid(),
806 link.getDestinationPortNumber());
807 linksToRemove.add(linkEvent);
808 }
809 for (LinkEvent linkEvent : linksToRemove) {
810 // XXX calling removeLinkEvent() may trigger duplicate event,
811 // once at prepare phase, second time here
812 // If event can be squashed, ignored etc. at receiver side it
813 // shouldn't be a problem, but if not need to re-visit
814
815 // calling Discovery API to wipe from DB, etc.
816 removeLinkEvent(linkEvent);
817 }
818
819 // remove Port from Switch
820 SwitchImpl s = getSwitchImpl(sw);
821 s.removePort(p);
822 }
823
824 void putLink(LinkEvent linkEvent) {
825 if (linkEvent == null) {
826 throw new IllegalArgumentException("Link cannot be null");
827 }
828
829 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
830 linkEvent.getSrc().number);
831 if (srcPort == null) {
832 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800833 String.format(
834 "Src Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800835 linkEvent.getSrc() ));
836 }
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800837
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800838 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
839 linkEvent.getDst().number);
840 if (dstPort == null) {
841 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800842 String.format(
843 "Dst Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800844 linkEvent.getDst()));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800845 }
846
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800847 // getting Link instance from destination port incoming Link
848 Link l = dstPort.getIncomingLink();
849 LinkImpl link = null;
850 assert(l == srcPort.getOutgoingLink());
851 if (l != null) {
852 link = getLinkImpl(l);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800853 }
854
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800855 if (link == null) {
856 link = new LinkImpl(networkGraph, srcPort, dstPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800857 }
858
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800859 PortImpl dstPortMem = getPortImpl(dstPort);
860 PortImpl srcPortMem = getPortImpl(srcPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800861
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800862 // Add Link first to avoid further Device addition
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800863
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800864 // add Link to Port
865 dstPortMem.setIncomingLink(link);
866 srcPortMem.setOutgoingLink(link);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800867
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800868 // remove Device Pointing to Port if any
869 for (Device d : dstPortMem.getDevices() ) {
870 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
871 d, dstPort, linkEvent);
872 DeviceImpl dev = getDeviceImpl(d);
873 dev.removeAttachmentPoint(dstPort);
874 // This implies that change is made to Device Object.
875 // sending Device attachment point removed event
876 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
877 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
878 dstPort.getNumber()));
879 removeDeviceEvent(rmEvent);
880 }
881 dstPortMem.removeAllDevice();
882 for (Device d : srcPortMem.getDevices() ) {
883 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
884 d, srcPort, linkEvent);
885 DeviceImpl dev = getDeviceImpl(d);
886 dev.removeAttachmentPoint(srcPort);
887 // This implies that change is made to Device Object.
888 // sending Device attachment point removed event
889 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
890 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
891 dstPort.getNumber()));
892 removeDeviceEvent(rmEvent);
893 }
894 srcPortMem.removeAllDevice();
895 }
896
897 void removeLink(LinkEvent linkEvent) {
898 if (linkEvent == null) {
899 throw new IllegalArgumentException("Link cannot be null");
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800900 }
901
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800902 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
903 linkEvent.getSrc().number);
904 if (srcPort == null) {
905 log.warn("Src Port for Link {} already removed, ignoring",
906 linkEvent);
907 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800908 }
909
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800910 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
911 linkEvent.getDst().number);
912 if (dstPort == null) {
913 log.warn("Dst Port for Link {} already removed, ignoring",
914 linkEvent);
915 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800916 }
917
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800918 Link l = dstPort.getIncomingLink();
919 if ( l == null) {
920 log.warn("Link {} already removed on destination Port", linkEvent);
921 }
922 l = srcPort.getOutgoingLink();
923 if (l == null) {
924 log.warn("Link {} already removed on src Port", linkEvent);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800925 }
926
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800927 getPortImpl(dstPort).setIncomingLink(null);
928 getPortImpl(srcPort).setOutgoingLink(null);
929 }
930
931 // XXX Need to rework Device related
932 void putDevice(DeviceEvent deviceEvent) {
933 if (deviceEvent == null) {
934 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800935 }
936
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800937 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
938 if (device == null) {
939 device = new DeviceImpl(networkGraph, deviceEvent.getMac());
940 }
941 DeviceImpl memDevice = getDeviceImpl(device);
942
943 // for each IP address
944 for (InetAddress ipAddr : deviceEvent.getIpAddresses()) {
945 memDevice.addIpAddress(ipAddr);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800946 }
947
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800948 networkGraph.putDevice(device);
949
950 // for each attachment point
951 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
952 // Attached Ports must exist
953 Port port = networkGraph.getPort(swp.dpid, swp.number);
954 if (port == null) {
955 log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
956 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800957 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800958 // Attached Ports must not have Link
959 if (port.getOutgoingLink() != null ||
960 port.getIncomingLink() != null) {
961 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
962 port.getOutgoingLink(),
963 port.getIncomingLink());
964 continue;
965 }
966
967 // finally add Device <-> Port on In-memory structure
968 PortImpl memPort = getPortImpl(port);
969 memPort.addDevice(device);
970 memDevice.addAttachmentPoint(port);
971 }
972 }
973
974 void removeDevice(DeviceEvent deviceEvent) {
975 if (deviceEvent == null) {
976 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800977 }
978
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800979 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
980 if (device == null) {
981 log.warn("Device {} already removed, ignoring", deviceEvent);
982 return;
983 }
984 DeviceImpl memDevice = getDeviceImpl(device);
985
986 // for each attachment point
987 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
988 // Attached Ports must exist
989 Port port = networkGraph.getPort(swp.dpid, swp.number);
990 if (port == null) {
991 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
992 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800993 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800994
995 // finally remove Device <-> Port on In-memory structure
996 PortImpl memPort = getPortImpl(port);
997 memPort.removeDevice(device);
998 memDevice.removeAttachmentPoint(port);
999 }
1000 networkGraph.removeDevice(device);
1001 }
1002
1003 private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
1004 for (INetworkGraphListener listener : this.networkGraphListeners) {
1005 // TODO Should copy before handing them over to listener
1006 listener.putSwitchEvent(switchEvent);
1007 }
1008 }
1009
1010 private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
1011 for (INetworkGraphListener listener : this.networkGraphListeners) {
1012 // TODO Should copy before handing them over to listener
1013 listener.removeSwitchEvent(switchEvent);
1014 }
1015 }
1016
1017 private void dispatchPutPortEvent(PortEvent portEvent) {
1018 for (INetworkGraphListener listener : this.networkGraphListeners) {
1019 // TODO Should copy before handing them over to listener
1020 listener.putPortEvent(portEvent);
1021 }
1022 }
1023
1024 private void dispatchRemovePortEvent(PortEvent portEvent) {
1025 for (INetworkGraphListener listener : this.networkGraphListeners) {
1026 // TODO Should copy before handing them over to listener
1027 listener.removePortEvent(portEvent);
1028 }
1029 }
1030
1031 private void dispatchPutLinkEvent(LinkEvent linkEvent) {
1032 for (INetworkGraphListener listener : this.networkGraphListeners) {
1033 // TODO Should copy before handing them over to listener
1034 listener.putLinkEvent(linkEvent);
1035 }
1036 }
1037
1038 private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
1039 for (INetworkGraphListener listener : this.networkGraphListeners) {
1040 // TODO Should copy before handing them over to listener
1041 listener.removeLinkEvent(linkEvent);
1042 }
1043 }
1044
1045 private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
1046 for (INetworkGraphListener listener : this.networkGraphListeners) {
1047 // TODO Should copy before handing them over to listener
1048 listener.putDeviceEvent(deviceEvent);;
1049 }
1050 }
1051
1052 private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
1053 for (INetworkGraphListener listener : this.networkGraphListeners) {
1054 // TODO Should copy before handing them over to listener
1055 listener.removeDeviceEvent(deviceEvent);
1056 }
1057 }
1058
1059 private SwitchImpl getSwitchImpl(Switch sw) {
1060 if (sw instanceof SwitchImpl) {
1061 return (SwitchImpl) sw;
1062 }
1063 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
1064 }
1065
1066 private PortImpl getPortImpl(Port p) {
1067 if (p instanceof PortImpl) {
1068 return (PortImpl) p;
1069 }
1070 throw new ClassCastException("PortImpl expected, but found: " + p);
1071 }
1072
1073 private LinkImpl getLinkImpl(Link l) {
1074 if (l instanceof LinkImpl) {
1075 return (LinkImpl) l;
1076 }
1077 throw new ClassCastException("LinkImpl expected, but found: " + l);
1078 }
1079
1080 private DeviceImpl getDeviceImpl(Device d) {
1081 if (d instanceof DeviceImpl) {
1082 return (DeviceImpl) d;
1083 }
1084 throw new ClassCastException("DeviceImpl expected, but found: " + d);
1085 }
1086
1087 @Deprecated
1088 public void loadWholeTopologyFromDB() {
1089 // XXX May need to clear whole topology first, depending on
1090 // how we initially subscribe to replication events
1091
1092 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
1093 if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
1094 continue;
1095 }
1096 putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001097 }
1098
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001099 for (RCPort p : RCPort.getAllPorts()) {
1100 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1101 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001102 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001103 putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001104 }
1105
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001106 // TODO Is Device going to be in DB? If so, read from DB.
1107 // for (RCDevice d : RCDevice.getAllDevices()) {
1108 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
1109 // for (byte[] portId : d.getAllPortIds() ) {
1110 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
1111 // }
1112 // }
1113
1114 for (RCLink l : RCLink.getAllLinks()) {
1115 // check if src/dst switch/port exist before triggering event
1116 Port srcPort = networkGraph.getPort(l.getSrc().dpid,
1117 l.getSrc().number);
1118 Port dstPort = networkGraph.getPort(l.getDst().dpid,
1119 l.getDst().number);
1120 if (srcPort == null || dstPort == null) {
1121 continue;
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001122 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001123 putLinkReplicationEvent(new LinkEvent(l.getSrc().dpid,
1124 l.getSrc().number,
1125 l.getDst().dpid,
1126 l.getDst().number));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001127 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001128 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001129}