blob: f620614ab4f94d6fc0166c358a0c149b36febfe5 [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 Radoslavov87dcc262014-02-19 21:13:23 -080042public class TopologyManager implements NetworkGraphDiscoveryInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080043
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080044 private static final Logger log = LoggerFactory
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -080045 .getLogger(TopologyManager.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080046
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080047 private IEventChannel<byte[], TopologyEvent> eventChannel;
48 private static final String EVENT_CHANNEL_NAME = "onos.topology";
49 private EventHandler eventHandler = new EventHandler();
50
Jonathan Hart22eb9882014-02-11 15:52:59 -080051 private final NetworkGraphDatastore datastore;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080052 private final NetworkGraphImpl networkGraph = new NetworkGraphImpl();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080053 private final IControllerRegistryService registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080054 private CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners;
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080055
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080056 /**
57 * Constructor.
58 *
59 * @param registryService the Registry Service to use.
60 * @param networkGraphListeners the collection of Network Graph Listeners
61 * to use.
62 */
63 public TopologyManager(IControllerRegistryService registryService,
64 CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners) {
Jonathan Hartdaea86f2014-02-19 15:28:42 -080065 datastore = new NetworkGraphDatastore();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080066 this.registryService = registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080067 this.networkGraphListeners = networkGraphListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080068 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080069
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080070 /**
71 * Get the Network Graph.
72 *
73 * @return the Network Graph.
74 */
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080075 NetworkGraph getNetworkGraph() {
76 return networkGraph;
77 }
78
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080079 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080080 * Event handler class.
81 */
82 private class EventHandler extends Thread implements
83 IEventChannelListener<byte[], TopologyEvent> {
84 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
85 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
86
87 /**
88 * Startup processing.
89 */
90 private void startup() {
91 //
92 // TODO: Read all state from the database
93 // For now, as a shortcut we read it from the datagrid
94 //
95 Collection<TopologyEvent> topologyEvents =
96 eventChannel.getAllEntries();
97 Collection<EventEntry<TopologyEvent>> collection =
98 new LinkedList<EventEntry<TopologyEvent>>();
99
100 for (TopologyEvent topologyEvent : topologyEvents) {
101 EventEntry<TopologyEvent> eventEntry =
102 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
103 topologyEvent);
104 collection.add(eventEntry);
105 }
106 processEvents(collection);
107 }
108
109 /**
110 * Run the thread.
111 */
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800112 @Override
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800113 public void run() {
114 Collection<EventEntry<TopologyEvent>> collection =
115 new LinkedList<EventEntry<TopologyEvent>>();
116
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -0800117 this.setName("TopologyManager.EventHandler " + this.getId());
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800118 startup();
119
120 //
121 // The main loop
122 //
123 try {
124 while (true) {
125 EventEntry<TopologyEvent> eventEntry = topologyEvents.take();
126 collection.add(eventEntry);
127 topologyEvents.drainTo(collection);
128
129 processEvents(collection);
130 collection.clear();
131 }
132 } catch (Exception exception) {
133 log.debug("Exception processing Topology Events: ", exception);
134 }
135 }
136
137 /**
138 * Process all topology events.
139 *
140 * @param events the events to process.
141 */
142 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
143 for (EventEntry<TopologyEvent> event : events) {
144 TopologyEvent topologyEvent = event.eventData();
145 switch (event.eventType()) {
146 case ENTRY_ADD:
147 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
148 if (topologyEvent.switchEvent != null)
149 putSwitchReplicationEvent(topologyEvent.switchEvent);
150 if (topologyEvent.portEvent != null)
151 putPortReplicationEvent(topologyEvent.portEvent);
152 if (topologyEvent.linkEvent != null)
153 putLinkReplicationEvent(topologyEvent.linkEvent);
154 if (topologyEvent.deviceEvent != null)
155 putDeviceReplicationEvent(topologyEvent.deviceEvent);
156 break;
157 case ENTRY_REMOVE:
158 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
159 if (topologyEvent.switchEvent != null)
160 removeSwitchReplicationEvent(topologyEvent.switchEvent);
161 if (topologyEvent.portEvent != null)
162 removePortReplicationEvent(topologyEvent.portEvent);
163 if (topologyEvent.linkEvent != null)
164 removeLinkReplicationEvent(topologyEvent.linkEvent);
165 if (topologyEvent.deviceEvent != null)
166 removeDeviceReplicationEvent(topologyEvent.deviceEvent);
167 break;
168 }
169 }
170 }
171
172 /**
173 * Receive a notification that an entry is added.
174 *
175 * @param value the value for the entry.
176 */
177 @Override
178 public void entryAdded(TopologyEvent value) {
179 EventEntry<TopologyEvent> eventEntry =
180 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
181 value);
182 topologyEvents.add(eventEntry);
183 }
184
185 /**
186 * Receive a notification that an entry is removed.
187 *
188 * @param value the value for the entry.
189 */
190 @Override
191 public void entryRemoved(TopologyEvent value) {
192 EventEntry<TopologyEvent> eventEntry =
193 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
194 value);
195 topologyEvents.add(eventEntry);
196 }
197
198 /**
199 * Receive a notification that an entry is updated.
200 *
201 * @param value the value for the entry.
202 */
203 @Override
204 public void entryUpdated(TopologyEvent value) {
205 // NOTE: The ADD and UPDATE events are processed in same way
206 entryAdded(value);
207 }
208 }
209
210 /**
211 * Startup processing.
212 *
213 * @param datagridService the datagrid service to use.
214 */
215 void startup(IDatagridService datagridService) {
216 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
217 eventHandler,
218 byte[].class,
219 TopologyEvent.class);
220 eventHandler.start();
221 }
222
223 /**
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800224 * Exception to be thrown when Modification to the Network Graph cannot be
225 * continued due to broken invariant.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800226 *
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800227 * XXX Should this be checked exception or RuntimeException?
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800228 */
229 public static class BrokenInvariantException extends RuntimeException {
230 private static final long serialVersionUID = 1L;
231
232 public BrokenInvariantException() {
233 super();
234 }
235
236 public BrokenInvariantException(String message) {
237 super(message);
238 }
239 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800240
241 /* ******************************
242 * NetworkGraphDiscoveryInterface methods
243 * ******************************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800244
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800245 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800246 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800247 if (datastore.addSwitch(switchEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800248 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800249 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800250 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
251 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800252 }
253
254 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800255 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800256 if (datastore.deactivateSwitch(switchEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800257 // Send out notification
258 eventChannel.removeEntry(switchEvent.getID());
259 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800260 }
261
262 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800263 public void putPortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800264 if (datastore.addPort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800265 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800266 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800267 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800268 }
269
270 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800271 public void removePortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800272 if (datastore.deactivatePort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800273 // Send out notification
274 eventChannel.removeEntry(portEvent.getID());
275 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800276 }
277
278 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800279 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800280 if (datastore.addLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800281 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800282 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800283 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
284 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800285 }
286
287 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800288 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800289 if (datastore.removeLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800290 // Send out notification
291 eventChannel.removeEntry(linkEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800292 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800293 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800294
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800295 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800296 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800297 if (datastore.addDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800298 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800299 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800300 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800301 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800302 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800303
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800304 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800305 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800306 if (datastore.removeDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800307 // Send out notification
308 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800309 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800310 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800311
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800312 /* ************************************************
313 * Internal methods for processing the replication events
314 * ************************************************/
315
316 private void putSwitchReplicationEvent(SwitchEvent switchEvent) {
317 if (prepareForAddSwitchEvent(switchEvent)) {
318 putSwitch(switchEvent);
319 }
320 // TODO handle invariant violation
321 // trigger instance local topology event handler
322 dispatchPutSwitchEvent(switchEvent);
323 }
324
325 private void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
326 if (prepareForRemoveSwitchEvent(switchEvent)) {
327 removeSwitch(switchEvent);
328 }
329 // TODO handle invariant violation
330 // trigger instance local topology event handler
331 dispatchRemoveSwitchEvent(switchEvent);
332 }
333
334 private void putPortReplicationEvent(PortEvent portEvent) {
335 if (prepareForAddPortEvent(portEvent)) {
336 putPort(portEvent);
337 }
338 // TODO handle invariant violation
339 // trigger instance local topology event handler
340 dispatchPutPortEvent(portEvent);
341 }
342
343 private void removePortReplicationEvent(PortEvent portEvent) {
344 if (prepareForRemovePortEvent(portEvent)) {
345 removePort(portEvent);
346 }
347 // TODO handle invariant violation
348 // trigger instance local topology event handler
349 dispatchRemovePortEvent(portEvent);
350 }
351
352 private void putLinkReplicationEvent(LinkEvent linkEvent) {
353 if (prepareForAddLinkEvent(linkEvent)) {
354 putLink(linkEvent);
355 }
356 // TODO handle invariant violation
357 // trigger instance local topology event handler
358 dispatchPutLinkEvent(linkEvent);
359 }
360
361 private void removeLinkReplicationEvent(LinkEvent linkEvent) {
362 if (prepareForRemoveLinkEvent(linkEvent)) {
363 removeLink(linkEvent);
364 }
365 // TODO handle invariant violation
366 // trigger instance local topology event handler
367 dispatchRemoveLinkEvent(linkEvent);
368 }
369
370 private void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
371 if (prepareForAddDeviceEvent(deviceEvent)) {
372 putDevice(deviceEvent);
373 }
374 // TODO handle invariant violation
375 // trigger instance local topology event handler
376 dispatchPutDeviceEvent(deviceEvent);
377 }
378
379 private void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
380 if (prepareForRemoveDeviceEvent(deviceEvent)) {
381 removeDevice(deviceEvent);
382 }
383 // TODO handle invariant violation
384 // trigger instance local topology event handler
385 dispatchRemoveDeviceEvent(deviceEvent);
386 }
387
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800388 /* *****************
389 * Internal methods to maintain invariants of the network graph
390 * *****************/
Jonathan Hart22eb9882014-02-11 15:52:59 -0800391
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800392 /**
393 *
394 * @param swEvent
395 * @return true if ready to accept event.
396 */
397 private boolean prepareForAddSwitchEvent(SwitchEvent swEvent) {
398 // No show stopping precondition
399 // Prep: remove(deactivate) Ports on Switch, which is not on event
400 removePortsNotOnEvent(swEvent);
401 return true;
402 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800403
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800404 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvent) {
405 // No show stopping precondition
406 // Prep: remove(deactivate) Ports on Switch, which is not on event
407 // XXX may be remove switch should imply wipe all ports
408 removePortsNotOnEvent(swEvent);
409 return true;
410 }
Yuta HIGUCHI71e7a052014-02-17 22:14:15 -0800411
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800412 private void removePortsNotOnEvent(SwitchEvent swEvent) {
413 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
414 if (sw != null) {
415 Set<Long> port_noOnEvent = new HashSet<>();
416 for (PortEvent portEvent : swEvent.getPorts()) {
417 port_noOnEvent.add(portEvent.getNumber());
418 }
419 // Existing ports not on event should be removed.
420 // TODO Should batch eventually for performance?
421 List<Port> portsToRemove = new ArrayList<Port>();
422 for (Port p : sw.getPorts()) {
423 if (!port_noOnEvent.contains(p.getNumber())) {
424 //PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
425 // calling Discovery removePort() API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800426 //removePortDiscoveryEvent(rmEvent);
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800427
Jonathan Hart480c5572014-02-14 18:28:16 -0800428 // We can't remove ports here because this will trigger a remove
429 // from the switch's port list, which we are currently iterating
430 // over.
431 portsToRemove.add(p);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800432 }
433 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800434 for (Port p : portsToRemove) {
435 PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(),
436 p.getNumber());
437 // calling Discovery removePort() API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800438 removePortDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800439 }
440 }
441 }
442
443 private boolean prepareForAddPortEvent(PortEvent portEvent) {
444 // Parent Switch must exist
445 if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
446 log.warn("Dropping add port event because switch doesn't exist: {}",
447 portEvent);
448 return false;
449 }
450 // Prep: None
451 return true;
452 }
453
454 private boolean prepareForRemovePortEvent(PortEvent portEvent) {
455 Port port = networkGraph.getPort(portEvent.getDpid(),
456 portEvent.getNumber());
457 if (port == null) {
458 log.debug("Port already removed? {}", portEvent);
459 // let it pass
460 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800461 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800462
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800463 // Prep: Remove Link and Device Attachment
464 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
465 for (Device device : port.getDevices()) {
466 log.debug("Removing Device {} on Port {}", device, portEvent);
467 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
468 devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
469 port.getNumber()));
470 deviceEvents.add(devEvent);
471 }
472 for (DeviceEvent devEvent : deviceEvents) {
473 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800474 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800475 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800476
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800477 Set<Link> links = new HashSet<>();
478 links.add(port.getOutgoingLink());
479 links.add(port.getIncomingLink());
480 for (Link link : links) {
481 if (link == null) {
482 continue;
483 }
484 log.debug("Removing Link {} on Port {}", link, portEvent);
485 LinkEvent linkEvent =
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800486 new LinkEvent(link.getSrcSwitch().getDpid(),
487 link.getSrcPort().getNumber(),
488 link.getDstSwitch().getDpid(),
489 link.getDstPort().getNumber());
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800490 // calling Discovery API to wipe from DB, etc.
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800491
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800492 // Call internal remove Link, which will check
493 // ownership of DST dpid and modify DB only if it is the owner
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800494 removeLinkDiscoveryEvent(linkEvent, true);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800495 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800496 return true;
497 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800498
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800499 private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
500 // Src/Dst Port must exist
501 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
502 linkEvent.getSrc().number);
503 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
504 linkEvent.getDst().number);
505 if (srcPort == null || dstPort == null) {
Jonathan Hart0a4846e2014-02-18 11:03:40 -0800506 log.warn("Dropping add link event because port doesn't exist: {}",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800507 linkEvent);
508 return false;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800509 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800510
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800511 // Prep: remove Device attachment on both Ports
512 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
513 for (Device device : srcPort.getDevices()) {
514 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
515 devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
516 deviceEvents.add(devEvent);
517 }
518 for (Device device : dstPort.getDevices()) {
519 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
520 devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
521 dstPort.getNumber()));
522 deviceEvents.add(devEvent);
523 }
524 for (DeviceEvent devEvent : deviceEvents) {
525 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800526 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800527 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800528
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800529 return true;
530 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800531
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800532 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
533 // Src/Dst Port must exist
534 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
535 linkEvent.getSrc().number);
536 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
537 linkEvent.getDst().number);
538 if (srcPort == null || dstPort == null) {
539 log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
540 return false;
541 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800542
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800543 Link link = srcPort.getOutgoingLink();
544
545 // Link is already gone, or different Link exist in memory
546 // XXX Check if we should reject or just accept these cases.
547 // it should be harmless to remove the Link on event from DB anyways
548 if (link == null ||
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800549 !link.getDstPort().getNumber().equals(linkEvent.getDst().number)
550 || !link.getDstSwitch().getDpid().equals(linkEvent.getDst().dpid)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800551 log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
552 return false;
553 }
554 // Prep: None
555 return true;
556 }
557
558 /**
559 *
560 * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
561 * @return false if this event should be dropped.
562 */
563 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
564 boolean preconditionBroken = false;
565 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
566 for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
567 // Attached Ports must exist
568 Port port = networkGraph.getPort(swp.dpid, swp.number);
569 if (port == null) {
570 preconditionBroken = true;
571 failedSwitchPort.add(swp);
572 continue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800573 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800574 // Attached Ports must not have Link
575 if (port.getOutgoingLink() != null ||
576 port.getIncomingLink() != null) {
577 preconditionBroken = true;
578 failedSwitchPort.add(swp);
579 continue;
580 }
581 }
582
583 // Rewriting event to exclude failed attachmentPoint
584 // XXX Assumption behind this is that inapplicable device event should
585 // be dropped, not deferred. If we decide to defer Device event,
586 // rewriting can become a problem
587 List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
588 attachmentPoints.removeAll(failedSwitchPort);
589 deviceEvent.setAttachmentPoints(attachmentPoints);
590
591 if (deviceEvent.getAttachmentPoints().isEmpty() &&
592 deviceEvent.getIpAddresses().isEmpty()) {
593 // return false to represent: Nothing left to do for this event.
594 // Caller should drop event
595 return false;
596 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800597
598 // Should we return false to tell caller that the event was trimmed?
599 // if ( preconditionBroken ) {
600 // return false;
601 // }
602
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800603 return true;
604 }
605
606 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
607 // No show stopping precondition?
608 // Prep: none
609 return true;
610 }
611
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800612 /* ************************************************
613 * Internal In-memory object mutation methods.
614 * ************************************************/
615
616 void putSwitch(SwitchEvent swEvent) {
617 if (swEvent == null) {
618 throw new IllegalArgumentException("Switch cannot be null");
Jonathan Hart22eb9882014-02-11 15:52:59 -0800619 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800620
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800621 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
622
623 if (sw == null) {
624 sw = new SwitchImpl(networkGraph, swEvent.getDpid());
625 networkGraph.putSwitch(sw);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800626 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800627
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800628 // Update when more attributes are added to Event object
629 // no attribute to update for now
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800630
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800631 // TODO handle child Port event properly for performance
632 for (PortEvent portEvent : swEvent.getPorts() ) {
633 putPort(portEvent);
634 }
635 }
636
637 void removeSwitch(SwitchEvent swEvent) {
638 if (swEvent == null) {
639 throw new IllegalArgumentException("Switch cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800640 }
641
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800642 // TODO handle child Port event properly for performance
643 for (PortEvent portEvent : swEvent.getPorts() ) {
644 removePort(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800645 }
646
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800647 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
648 if (sw == null) {
649 log.warn("Switch {} already removed, ignoring", swEvent);
650 return;
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800651 }
652
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800653 // remove all ports if there still exist
654 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
655 for (Port port : sw.getPorts()) {
656 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now",
657 port, swEvent);
658 PortEvent portEvent = new PortEvent(port.getDpid(),
659 port.getNumber());
660 portsToRemove.add(portEvent);
661 }
662 for (PortEvent portEvent : portsToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800663 // XXX calling removePortDiscoveryEvent() may trigger duplicate
664 // event, once at prepare phase, second time here
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800665 // If event can be squashed, ignored etc. at receiver side it
666 // shouldn't be a problem, but if not need to re-visit this issue.
667
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800668 // Note: removePortDiscoveryEvent() implies removal of attached
669 // Device, etc. if we decide not to call
670 // removePortDiscoveryEvent(), Device needs to be handled properly.
671 removePortDiscoveryEvent(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800672 }
673
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800674 networkGraph.removeSwitch(swEvent.getDpid());
675 }
676
677 void putPort(PortEvent portEvent) {
678 if (portEvent == null) {
679 throw new IllegalArgumentException("Port cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800680 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800681 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
682 if (sw == null) {
683 throw new BrokenInvariantException(String.format(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800684 "Switch with dpid %s did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800685 new Dpid(portEvent.getDpid())));
686 }
687 Port p = sw.getPort(portEvent.getNumber());
688 PortImpl port = null;
689 if (p != null) {
690 port = getPortImpl(p);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800691 }
692
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800693 if (port == null) {
694 port = new PortImpl(networkGraph, sw, portEvent.getNumber());
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800695 }
696
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800697 // TODO update attributes
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800698
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800699 SwitchImpl s = getSwitchImpl(sw);
700 s.addPort(port);
701 }
702
703 void removePort(PortEvent portEvent) {
704 if (portEvent == null) {
705 throw new IllegalArgumentException("Port cannot be null");
706 }
707
708 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
709 if (sw == null) {
710 log.warn("Parent Switch for Port {} already removed, ignoring",
711 portEvent);
712 return;
713 }
714
715 Port p = sw.getPort(portEvent.getNumber());
716 if (p == null) {
717 log.warn("Port {} already removed, ignoring", portEvent);
718 return;
719 }
720
721 // Remove Link and Device Attachment
722 for (Device device : p.getDevices()) {
723 log.debug("Removing Device {} on Port {}", device, portEvent);
724 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
725 devEvent.addAttachmentPoint(new SwitchPort(p.getSwitch().getDpid(),
726 p.getNumber()));
727
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800728 // XXX calling removeDeviceDiscoveryEvent() may trigger duplicate
729 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800730 // If event can be squashed, ignored etc. at receiver side it
731 // shouldn't be a problem, but if not need to re-visit
732
733 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800734 removeDeviceDiscoveryEvent(devEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800735 }
736 Set<Link> links = new HashSet<>();
737 links.add(p.getOutgoingLink());
738 links.add(p.getIncomingLink());
739 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
740 for (Link link : links) {
741 if (link == null) {
742 continue;
743 }
744 log.debug("Removing Link {} on Port {}", link, portEvent);
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800745 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
746 link.getSrcPort().getNumber(),
747 link.getDstSwitch().getDpid(),
748 link.getDstPort().getNumber());
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800749 linksToRemove.add(linkEvent);
750 }
751 for (LinkEvent linkEvent : linksToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800752 // XXX calling removeLinkDiscoveryEvent() may trigger duplicate
753 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800754 // If event can be squashed, ignored etc. at receiver side it
755 // shouldn't be a problem, but if not need to re-visit
756
757 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800758 removeLinkDiscoveryEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800759 }
760
761 // remove Port from Switch
762 SwitchImpl s = getSwitchImpl(sw);
763 s.removePort(p);
764 }
765
766 void putLink(LinkEvent linkEvent) {
767 if (linkEvent == null) {
768 throw new IllegalArgumentException("Link cannot be null");
769 }
770
771 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
772 linkEvent.getSrc().number);
773 if (srcPort == null) {
774 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800775 String.format(
776 "Src Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800777 linkEvent.getSrc() ));
778 }
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800779
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800780 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
781 linkEvent.getDst().number);
782 if (dstPort == null) {
783 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800784 String.format(
785 "Dst Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800786 linkEvent.getDst()));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800787 }
788
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800789 // getting Link instance from destination port incoming Link
790 Link l = dstPort.getIncomingLink();
791 LinkImpl link = null;
792 assert(l == srcPort.getOutgoingLink());
793 if (l != null) {
794 link = getLinkImpl(l);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800795 }
796
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800797 if (link == null) {
798 link = new LinkImpl(networkGraph, srcPort, dstPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800799 }
800
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800801 PortImpl dstPortMem = getPortImpl(dstPort);
802 PortImpl srcPortMem = getPortImpl(srcPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800803
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800804 // Add Link first to avoid further Device addition
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800805
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800806 // add Link to Port
807 dstPortMem.setIncomingLink(link);
808 srcPortMem.setOutgoingLink(link);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800809
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800810 // remove Device Pointing to Port if any
811 for (Device d : dstPortMem.getDevices() ) {
812 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
813 d, dstPort, linkEvent);
814 DeviceImpl dev = getDeviceImpl(d);
815 dev.removeAttachmentPoint(dstPort);
816 // This implies that change is made to Device Object.
817 // sending Device attachment point removed event
818 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
819 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
820 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800821 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800822 }
823 dstPortMem.removeAllDevice();
824 for (Device d : srcPortMem.getDevices() ) {
825 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
826 d, srcPort, linkEvent);
827 DeviceImpl dev = getDeviceImpl(d);
828 dev.removeAttachmentPoint(srcPort);
829 // This implies that change is made to Device Object.
830 // sending Device attachment point removed event
831 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
832 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
833 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800834 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800835 }
836 srcPortMem.removeAllDevice();
837 }
838
839 void removeLink(LinkEvent linkEvent) {
840 if (linkEvent == null) {
841 throw new IllegalArgumentException("Link cannot be null");
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800842 }
843
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800844 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
845 linkEvent.getSrc().number);
846 if (srcPort == null) {
847 log.warn("Src Port for Link {} already removed, ignoring",
848 linkEvent);
849 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800850 }
851
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800852 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
853 linkEvent.getDst().number);
854 if (dstPort == null) {
855 log.warn("Dst Port for Link {} already removed, ignoring",
856 linkEvent);
857 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800858 }
859
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800860 Link l = dstPort.getIncomingLink();
861 if ( l == null) {
862 log.warn("Link {} already removed on destination Port", linkEvent);
863 }
864 l = srcPort.getOutgoingLink();
865 if (l == null) {
866 log.warn("Link {} already removed on src Port", linkEvent);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800867 }
868
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800869 getPortImpl(dstPort).setIncomingLink(null);
870 getPortImpl(srcPort).setOutgoingLink(null);
871 }
872
873 // XXX Need to rework Device related
874 void putDevice(DeviceEvent deviceEvent) {
875 if (deviceEvent == null) {
876 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800877 }
878
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800879 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
880 if (device == null) {
881 device = new DeviceImpl(networkGraph, deviceEvent.getMac());
882 }
883 DeviceImpl memDevice = getDeviceImpl(device);
884
885 // for each IP address
886 for (InetAddress ipAddr : deviceEvent.getIpAddresses()) {
887 memDevice.addIpAddress(ipAddr);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800888 }
889
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800890 networkGraph.putDevice(device);
891
892 // for each attachment point
893 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
894 // Attached Ports must exist
895 Port port = networkGraph.getPort(swp.dpid, swp.number);
896 if (port == null) {
897 log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
898 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800899 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800900 // Attached Ports must not have Link
901 if (port.getOutgoingLink() != null ||
902 port.getIncomingLink() != null) {
903 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
904 port.getOutgoingLink(),
905 port.getIncomingLink());
906 continue;
907 }
908
909 // finally add Device <-> Port on In-memory structure
910 PortImpl memPort = getPortImpl(port);
911 memPort.addDevice(device);
912 memDevice.addAttachmentPoint(port);
913 }
914 }
915
916 void removeDevice(DeviceEvent deviceEvent) {
917 if (deviceEvent == null) {
918 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800919 }
920
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800921 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
922 if (device == null) {
923 log.warn("Device {} already removed, ignoring", deviceEvent);
924 return;
925 }
926 DeviceImpl memDevice = getDeviceImpl(device);
927
928 // for each attachment point
929 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
930 // Attached Ports must exist
931 Port port = networkGraph.getPort(swp.dpid, swp.number);
932 if (port == null) {
933 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
934 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800935 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800936
937 // finally remove Device <-> Port on In-memory structure
938 PortImpl memPort = getPortImpl(port);
939 memPort.removeDevice(device);
940 memDevice.removeAttachmentPoint(port);
941 }
942 networkGraph.removeDevice(device);
943 }
944
945 private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
946 for (INetworkGraphListener listener : this.networkGraphListeners) {
947 // TODO Should copy before handing them over to listener
948 listener.putSwitchEvent(switchEvent);
949 }
950 }
951
952 private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
953 for (INetworkGraphListener listener : this.networkGraphListeners) {
954 // TODO Should copy before handing them over to listener
955 listener.removeSwitchEvent(switchEvent);
956 }
957 }
958
959 private void dispatchPutPortEvent(PortEvent portEvent) {
960 for (INetworkGraphListener listener : this.networkGraphListeners) {
961 // TODO Should copy before handing them over to listener
962 listener.putPortEvent(portEvent);
963 }
964 }
965
966 private void dispatchRemovePortEvent(PortEvent portEvent) {
967 for (INetworkGraphListener listener : this.networkGraphListeners) {
968 // TODO Should copy before handing them over to listener
969 listener.removePortEvent(portEvent);
970 }
971 }
972
973 private void dispatchPutLinkEvent(LinkEvent linkEvent) {
974 for (INetworkGraphListener listener : this.networkGraphListeners) {
975 // TODO Should copy before handing them over to listener
976 listener.putLinkEvent(linkEvent);
977 }
978 }
979
980 private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
981 for (INetworkGraphListener listener : this.networkGraphListeners) {
982 // TODO Should copy before handing them over to listener
983 listener.removeLinkEvent(linkEvent);
984 }
985 }
986
987 private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
988 for (INetworkGraphListener listener : this.networkGraphListeners) {
989 // TODO Should copy before handing them over to listener
990 listener.putDeviceEvent(deviceEvent);;
991 }
992 }
993
994 private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
995 for (INetworkGraphListener listener : this.networkGraphListeners) {
996 // TODO Should copy before handing them over to listener
997 listener.removeDeviceEvent(deviceEvent);
998 }
999 }
1000
1001 private SwitchImpl getSwitchImpl(Switch sw) {
1002 if (sw instanceof SwitchImpl) {
1003 return (SwitchImpl) sw;
1004 }
1005 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
1006 }
1007
1008 private PortImpl getPortImpl(Port p) {
1009 if (p instanceof PortImpl) {
1010 return (PortImpl) p;
1011 }
1012 throw new ClassCastException("PortImpl expected, but found: " + p);
1013 }
1014
1015 private LinkImpl getLinkImpl(Link l) {
1016 if (l instanceof LinkImpl) {
1017 return (LinkImpl) l;
1018 }
1019 throw new ClassCastException("LinkImpl expected, but found: " + l);
1020 }
1021
1022 private DeviceImpl getDeviceImpl(Device d) {
1023 if (d instanceof DeviceImpl) {
1024 return (DeviceImpl) d;
1025 }
1026 throw new ClassCastException("DeviceImpl expected, but found: " + d);
1027 }
1028
1029 @Deprecated
1030 public void loadWholeTopologyFromDB() {
1031 // XXX May need to clear whole topology first, depending on
1032 // how we initially subscribe to replication events
1033
1034 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
1035 if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
1036 continue;
1037 }
1038 putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001039 }
1040
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001041 for (RCPort p : RCPort.getAllPorts()) {
1042 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1043 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001044 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001045 putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001046 }
1047
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001048 // TODO Is Device going to be in DB? If so, read from DB.
1049 // for (RCDevice d : RCDevice.getAllDevices()) {
1050 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
1051 // for (byte[] portId : d.getAllPortIds() ) {
1052 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
1053 // }
1054 // }
1055
1056 for (RCLink l : RCLink.getAllLinks()) {
1057 // check if src/dst switch/port exist before triggering event
1058 Port srcPort = networkGraph.getPort(l.getSrc().dpid,
1059 l.getSrc().number);
1060 Port dstPort = networkGraph.getPort(l.getDst().dpid,
1061 l.getDst().number);
1062 if (srcPort == null || dstPort == null) {
1063 continue;
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001064 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001065 putLinkReplicationEvent(new LinkEvent(l.getSrc().dpid,
1066 l.getSrc().number,
1067 l.getDst().dpid,
1068 l.getDst().number));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001069 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001070 }
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -08001071
1072 @Deprecated
1073 private void removeLinkDiscoveryEvent(LinkEvent linkEvent,
1074 boolean dstCheckBeforeDBmodify) {
1075 if (prepareForRemoveLinkEvent(linkEvent)) {
1076 if (dstCheckBeforeDBmodify) {
1077 // write to DB only if it is owner of the dst dpid
1078 // XXX this will cause link remove events to be dropped
1079 // if the dst switch just disconnected
1080 if (registryService.hasControl(linkEvent.getDst().dpid)) {
1081 datastore.removeLink(linkEvent);
1082 }
1083 } else {
1084 datastore.removeLink(linkEvent);
1085 }
1086 removeLink(linkEvent);
1087 // Send out notification
1088 eventChannel.removeEntry(linkEvent.getID());
1089 }
1090 // TODO handle invariant violation
1091 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001092}