blob: 43f287c50c86e594a91ec75c251f955888d80231 [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 Hartdaea86f2014-02-19 15:28:42 -080066 datastore = new NetworkGraphDatastore();
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
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800251 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800252 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
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800264 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800265 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
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800275 public void putPortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800276 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
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800288 public void removePortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800289 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
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800299 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800300 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
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800312 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
313 removeLinkDiscoveryEvent(linkEvent, false);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800314 }
315
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800316 private void removeLinkDiscoveryEvent(LinkEvent linkEvent,
317 boolean dstCheckBeforeDBmodify) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800318 if (prepareForRemoveLinkEvent(linkEvent)) {
319 if (dstCheckBeforeDBmodify) {
320 // write to DB only if it is owner of the dst dpid
Jonathan Hartdaea86f2014-02-19 15:28:42 -0800321 // XXX this will cause link remove events to be dropped
322 // if the dst switch just disconnected
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800323 if (registryService.hasControl(linkEvent.getDst().dpid)) {
324 datastore.removeLink(linkEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800325 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800326 } else {
327 datastore.removeLink(linkEvent);
328 }
329 removeLink(linkEvent);
330 // Send out notification
331 eventChannel.removeEntry(linkEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800332 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800333 // TODO handle invariant violation
334 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800335
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800336 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800337 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800338 if (prepareForAddDeviceEvent(deviceEvent)) {
339// datastore.addDevice(deviceEvent);
340// putDevice(deviceEvent);
341 // Send out notification
342 TopologyEvent topologyEvent =
343 new TopologyEvent(deviceEvent,
344 registryService.getControllerId());
345 eventChannel.addEntry(topologyEvent.getID(),
346 topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800347 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800348 // TODO handle invariant violation
349 // XXX if prepareFor~ method returned false, event should be dropped
350 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800351
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800352 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800353 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800354 if (prepareForRemoveDeviceEvent(deviceEvent)) {
355// datastore.removeDevice(deviceEvent);
356// removeDevice(deviceEvent);
357 // Send out notification
358 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800359 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800360 // TODO handle invariant violation
361 // XXX if prepareFor~ method returned false, event should be dropped
362 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800363
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800364 /* *****************
365 * Internal methods to maintain invariants of the network graph
366 * *****************/
Jonathan Hart22eb9882014-02-11 15:52:59 -0800367
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800368 /**
369 *
370 * @param swEvent
371 * @return true if ready to accept event.
372 */
373 private boolean prepareForAddSwitchEvent(SwitchEvent swEvent) {
374 // No show stopping precondition
375 // Prep: remove(deactivate) Ports on Switch, which is not on event
376 removePortsNotOnEvent(swEvent);
377 return true;
378 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800379
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800380 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvent) {
381 // No show stopping precondition
382 // Prep: remove(deactivate) Ports on Switch, which is not on event
383 // XXX may be remove switch should imply wipe all ports
384 removePortsNotOnEvent(swEvent);
385 return true;
386 }
Yuta HIGUCHI71e7a052014-02-17 22:14:15 -0800387
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800388 private void removePortsNotOnEvent(SwitchEvent swEvent) {
389 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
390 if (sw != null) {
391 Set<Long> port_noOnEvent = new HashSet<>();
392 for (PortEvent portEvent : swEvent.getPorts()) {
393 port_noOnEvent.add(portEvent.getNumber());
394 }
395 // Existing ports not on event should be removed.
396 // TODO Should batch eventually for performance?
397 List<Port> portsToRemove = new ArrayList<Port>();
398 for (Port p : sw.getPorts()) {
399 if (!port_noOnEvent.contains(p.getNumber())) {
400 //PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
401 // calling Discovery removePort() API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800402 //removePortDiscoveryEvent(rmEvent);
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800403
Jonathan Hart480c5572014-02-14 18:28:16 -0800404 // We can't remove ports here because this will trigger a remove
405 // from the switch's port list, which we are currently iterating
406 // over.
407 portsToRemove.add(p);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800408 }
409 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800410 for (Port p : portsToRemove) {
411 PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(),
412 p.getNumber());
413 // calling Discovery removePort() API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800414 removePortDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800415 }
416 }
417 }
418
419 private boolean prepareForAddPortEvent(PortEvent portEvent) {
420 // Parent Switch must exist
421 if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
422 log.warn("Dropping add port event because switch doesn't exist: {}",
423 portEvent);
424 return false;
425 }
426 // Prep: None
427 return true;
428 }
429
430 private boolean prepareForRemovePortEvent(PortEvent portEvent) {
431 Port port = networkGraph.getPort(portEvent.getDpid(),
432 portEvent.getNumber());
433 if (port == null) {
434 log.debug("Port already removed? {}", portEvent);
435 // let it pass
436 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800437 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800438
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800439 // Prep: Remove Link and Device Attachment
440 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
441 for (Device device : port.getDevices()) {
442 log.debug("Removing Device {} on Port {}", device, portEvent);
443 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
444 devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
445 port.getNumber()));
446 deviceEvents.add(devEvent);
447 }
448 for (DeviceEvent devEvent : deviceEvents) {
449 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800450 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800451 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800452
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800453 Set<Link> links = new HashSet<>();
454 links.add(port.getOutgoingLink());
455 links.add(port.getIncomingLink());
456 for (Link link : links) {
457 if (link == null) {
458 continue;
459 }
460 log.debug("Removing Link {} on Port {}", link, portEvent);
461 LinkEvent linkEvent =
462 new LinkEvent(link.getSourceSwitchDpid(),
463 link.getSourcePortNumber(),
464 link.getDestinationSwitchDpid(),
465 link.getDestinationPortNumber());
466 // calling Discovery API to wipe from DB, etc.
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800467
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800468 // Call internal remove Link, which will check
469 // ownership of DST dpid and modify DB only if it is the owner
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800470 removeLinkDiscoveryEvent(linkEvent, true);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800471 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800472 return true;
473 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800474
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800475 private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
476 // Src/Dst Port must exist
477 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
478 linkEvent.getSrc().number);
479 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
480 linkEvent.getDst().number);
481 if (srcPort == null || dstPort == null) {
Jonathan Hart0a4846e2014-02-18 11:03:40 -0800482 log.warn("Dropping add link event because port doesn't exist: {}",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800483 linkEvent);
484 return false;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800485 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800486
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800487 // Prep: remove Device attachment on both Ports
488 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
489 for (Device device : srcPort.getDevices()) {
490 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
491 devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
492 deviceEvents.add(devEvent);
493 }
494 for (Device device : dstPort.getDevices()) {
495 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
496 devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
497 dstPort.getNumber()));
498 deviceEvents.add(devEvent);
499 }
500 for (DeviceEvent devEvent : deviceEvents) {
501 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800502 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800503 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800504
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800505 return true;
506 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800507
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800508 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
509 // Src/Dst Port must exist
510 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
511 linkEvent.getSrc().number);
512 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
513 linkEvent.getDst().number);
514 if (srcPort == null || dstPort == null) {
515 log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
516 return false;
517 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800518
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800519 Link link = srcPort.getOutgoingLink();
520
521 // Link is already gone, or different Link exist in memory
522 // XXX Check if we should reject or just accept these cases.
523 // it should be harmless to remove the Link on event from DB anyways
524 if (link == null ||
525 !link.getDestinationPortNumber().equals(linkEvent.getDst().number)
526 || !link.getDestinationSwitchDpid().equals(linkEvent.getDst().dpid)) {
527 log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
528 return false;
529 }
530 // Prep: None
531 return true;
532 }
533
534 /**
535 *
536 * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
537 * @return false if this event should be dropped.
538 */
539 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
540 boolean preconditionBroken = false;
541 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
542 for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
543 // Attached Ports must exist
544 Port port = networkGraph.getPort(swp.dpid, swp.number);
545 if (port == null) {
546 preconditionBroken = true;
547 failedSwitchPort.add(swp);
548 continue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800549 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800550 // Attached Ports must not have Link
551 if (port.getOutgoingLink() != null ||
552 port.getIncomingLink() != null) {
553 preconditionBroken = true;
554 failedSwitchPort.add(swp);
555 continue;
556 }
557 }
558
559 // Rewriting event to exclude failed attachmentPoint
560 // XXX Assumption behind this is that inapplicable device event should
561 // be dropped, not deferred. If we decide to defer Device event,
562 // rewriting can become a problem
563 List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
564 attachmentPoints.removeAll(failedSwitchPort);
565 deviceEvent.setAttachmentPoints(attachmentPoints);
566
567 if (deviceEvent.getAttachmentPoints().isEmpty() &&
568 deviceEvent.getIpAddresses().isEmpty()) {
569 // return false to represent: Nothing left to do for this event.
570 // Caller should drop event
571 return false;
572 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800573
574 // Should we return false to tell caller that the event was trimmed?
575 // if ( preconditionBroken ) {
576 // return false;
577 // }
578
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800579 return true;
580 }
581
582 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
583 // No show stopping precondition?
584 // Prep: none
585 return true;
586 }
587
588 /* ******************************
589 * NetworkGraphReplicationInterface methods
590 * ******************************/
591
592 @Override
593 public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
594 if (prepareForAddSwitchEvent(switchEvent)) {
595 putSwitch(switchEvent);
596 }
597 // TODO handle invariant violation
598 // trigger instance local topology event handler
599 dispatchPutSwitchEvent(switchEvent);
600 }
601
602 @Override
603 public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
604 if (prepareForRemoveSwitchEvent(switchEvent)) {
605 removeSwitch(switchEvent);
606 }
607 // TODO handle invariant violation
608 // trigger instance local topology event handler
609 dispatchRemoveSwitchEvent(switchEvent);
610 }
611
612 @Override
613 public void putPortReplicationEvent(PortEvent portEvent) {
614 if (prepareForAddPortEvent(portEvent)) {
615 putPort(portEvent);
616 }
617 // TODO handle invariant violation
618 // trigger instance local topology event handler
619 dispatchPutPortEvent(portEvent);
620 }
621
622 @Override
623 public void removePortReplicationEvent(PortEvent portEvent) {
624 if (prepareForRemovePortEvent(portEvent)) {
625 removePort(portEvent);
626 }
627 // TODO handle invariant violation
628 // trigger instance local topology event handler
629 dispatchRemovePortEvent(portEvent);
630 }
631
632 @Override
633 public void putLinkReplicationEvent(LinkEvent linkEvent) {
634 if (prepareForAddLinkEvent(linkEvent)) {
635 putLink(linkEvent);
636 }
637 // TODO handle invariant violation
638 // trigger instance local topology event handler
639 dispatchPutLinkEvent(linkEvent);
640 }
641
642 @Override
643 public void removeLinkReplicationEvent(LinkEvent linkEvent) {
644 if (prepareForRemoveLinkEvent(linkEvent)) {
645 removeLink(linkEvent);
646 }
647 // TODO handle invariant violation
648 // trigger instance local topology event handler
649 dispatchRemoveLinkEvent(linkEvent);
650 }
651
652 @Override
653 public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
654 if (prepareForAddDeviceEvent(deviceEvent)) {
655 putDevice(deviceEvent);
656 }
657 // TODO handle invariant violation
658 // trigger instance local topology event handler
659 dispatchPutDeviceEvent(deviceEvent);
660 }
661
662 @Override
663 public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
664 if (prepareForRemoveDeviceEvent(deviceEvent)) {
665 removeDevice(deviceEvent);
666 }
667 // TODO handle invariant violation
668 // trigger instance local topology event handler
669 dispatchRemoveDeviceEvent(deviceEvent);
670 }
671
672 /* ************************************************
673 * Internal In-memory object mutation methods.
674 * ************************************************/
675
676 void putSwitch(SwitchEvent swEvent) {
677 if (swEvent == null) {
678 throw new IllegalArgumentException("Switch cannot be null");
Jonathan Hart22eb9882014-02-11 15:52:59 -0800679 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800680
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800681 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
682
683 if (sw == null) {
684 sw = new SwitchImpl(networkGraph, swEvent.getDpid());
685 networkGraph.putSwitch(sw);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800686 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800687
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800688 // Update when more attributes are added to Event object
689 // no attribute to update for now
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800690
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800691 // TODO handle child Port event properly for performance
692 for (PortEvent portEvent : swEvent.getPorts() ) {
693 putPort(portEvent);
694 }
695 }
696
697 void removeSwitch(SwitchEvent swEvent) {
698 if (swEvent == null) {
699 throw new IllegalArgumentException("Switch cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800700 }
701
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800702 // TODO handle child Port event properly for performance
703 for (PortEvent portEvent : swEvent.getPorts() ) {
704 removePort(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800705 }
706
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800707 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
708 if (sw == null) {
709 log.warn("Switch {} already removed, ignoring", swEvent);
710 return;
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800711 }
712
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800713 // remove all ports if there still exist
714 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
715 for (Port port : sw.getPorts()) {
716 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now",
717 port, swEvent);
718 PortEvent portEvent = new PortEvent(port.getDpid(),
719 port.getNumber());
720 portsToRemove.add(portEvent);
721 }
722 for (PortEvent portEvent : portsToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800723 // XXX calling removePortDiscoveryEvent() may trigger duplicate
724 // event, once at prepare phase, second time here
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800725 // If event can be squashed, ignored etc. at receiver side it
726 // shouldn't be a problem, but if not need to re-visit this issue.
727
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800728 // Note: removePortDiscoveryEvent() implies removal of attached
729 // Device, etc. if we decide not to call
730 // removePortDiscoveryEvent(), Device needs to be handled properly.
731 removePortDiscoveryEvent(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800732 }
733
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800734 networkGraph.removeSwitch(swEvent.getDpid());
735 }
736
737 void putPort(PortEvent portEvent) {
738 if (portEvent == null) {
739 throw new IllegalArgumentException("Port cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800740 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800741 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
742 if (sw == null) {
743 throw new BrokenInvariantException(String.format(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800744 "Switch with dpid %s did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800745 new Dpid(portEvent.getDpid())));
746 }
747 Port p = sw.getPort(portEvent.getNumber());
748 PortImpl port = null;
749 if (p != null) {
750 port = getPortImpl(p);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800751 }
752
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800753 if (port == null) {
754 port = new PortImpl(networkGraph, sw, portEvent.getNumber());
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800755 }
756
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800757 // TODO update attributes
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800758
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800759 SwitchImpl s = getSwitchImpl(sw);
760 s.addPort(port);
761 }
762
763 void removePort(PortEvent portEvent) {
764 if (portEvent == null) {
765 throw new IllegalArgumentException("Port cannot be null");
766 }
767
768 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
769 if (sw == null) {
770 log.warn("Parent Switch for Port {} already removed, ignoring",
771 portEvent);
772 return;
773 }
774
775 Port p = sw.getPort(portEvent.getNumber());
776 if (p == null) {
777 log.warn("Port {} already removed, ignoring", portEvent);
778 return;
779 }
780
781 // Remove Link and Device Attachment
782 for (Device device : p.getDevices()) {
783 log.debug("Removing Device {} on Port {}", device, portEvent);
784 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
785 devEvent.addAttachmentPoint(new SwitchPort(p.getSwitch().getDpid(),
786 p.getNumber()));
787
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800788 // XXX calling removeDeviceDiscoveryEvent() may trigger duplicate
789 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800790 // If event can be squashed, ignored etc. at receiver side it
791 // shouldn't be a problem, but if not need to re-visit
792
793 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800794 removeDeviceDiscoveryEvent(devEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800795 }
796 Set<Link> links = new HashSet<>();
797 links.add(p.getOutgoingLink());
798 links.add(p.getIncomingLink());
799 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
800 for (Link link : links) {
801 if (link == null) {
802 continue;
803 }
804 log.debug("Removing Link {} on Port {}", link, portEvent);
805 LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(),
806 link.getSourcePortNumber(),
807 link.getDestinationSwitchDpid(),
808 link.getDestinationPortNumber());
809 linksToRemove.add(linkEvent);
810 }
811 for (LinkEvent linkEvent : linksToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800812 // XXX calling removeLinkDiscoveryEvent() may trigger duplicate
813 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800814 // If event can be squashed, ignored etc. at receiver side it
815 // shouldn't be a problem, but if not need to re-visit
816
817 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800818 removeLinkDiscoveryEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800819 }
820
821 // remove Port from Switch
822 SwitchImpl s = getSwitchImpl(sw);
823 s.removePort(p);
824 }
825
826 void putLink(LinkEvent linkEvent) {
827 if (linkEvent == null) {
828 throw new IllegalArgumentException("Link cannot be null");
829 }
830
831 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
832 linkEvent.getSrc().number);
833 if (srcPort == null) {
834 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800835 String.format(
836 "Src Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800837 linkEvent.getSrc() ));
838 }
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800839
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800840 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
841 linkEvent.getDst().number);
842 if (dstPort == null) {
843 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800844 String.format(
845 "Dst Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800846 linkEvent.getDst()));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800847 }
848
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800849 // getting Link instance from destination port incoming Link
850 Link l = dstPort.getIncomingLink();
851 LinkImpl link = null;
852 assert(l == srcPort.getOutgoingLink());
853 if (l != null) {
854 link = getLinkImpl(l);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800855 }
856
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800857 if (link == null) {
858 link = new LinkImpl(networkGraph, srcPort, dstPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800859 }
860
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800861 PortImpl dstPortMem = getPortImpl(dstPort);
862 PortImpl srcPortMem = getPortImpl(srcPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800863
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800864 // Add Link first to avoid further Device addition
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800865
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800866 // add Link to Port
867 dstPortMem.setIncomingLink(link);
868 srcPortMem.setOutgoingLink(link);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800869
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800870 // remove Device Pointing to Port if any
871 for (Device d : dstPortMem.getDevices() ) {
872 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
873 d, dstPort, linkEvent);
874 DeviceImpl dev = getDeviceImpl(d);
875 dev.removeAttachmentPoint(dstPort);
876 // This implies that change is made to Device Object.
877 // sending Device attachment point removed event
878 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
879 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
880 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800881 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800882 }
883 dstPortMem.removeAllDevice();
884 for (Device d : srcPortMem.getDevices() ) {
885 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
886 d, srcPort, linkEvent);
887 DeviceImpl dev = getDeviceImpl(d);
888 dev.removeAttachmentPoint(srcPort);
889 // This implies that change is made to Device Object.
890 // sending Device attachment point removed event
891 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
892 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
893 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800894 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800895 }
896 srcPortMem.removeAllDevice();
897 }
898
899 void removeLink(LinkEvent linkEvent) {
900 if (linkEvent == null) {
901 throw new IllegalArgumentException("Link cannot be null");
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800902 }
903
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800904 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
905 linkEvent.getSrc().number);
906 if (srcPort == null) {
907 log.warn("Src Port for Link {} already removed, ignoring",
908 linkEvent);
909 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800910 }
911
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800912 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
913 linkEvent.getDst().number);
914 if (dstPort == null) {
915 log.warn("Dst Port for Link {} already removed, ignoring",
916 linkEvent);
917 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800918 }
919
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800920 Link l = dstPort.getIncomingLink();
921 if ( l == null) {
922 log.warn("Link {} already removed on destination Port", linkEvent);
923 }
924 l = srcPort.getOutgoingLink();
925 if (l == null) {
926 log.warn("Link {} already removed on src Port", linkEvent);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800927 }
928
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800929 getPortImpl(dstPort).setIncomingLink(null);
930 getPortImpl(srcPort).setOutgoingLink(null);
931 }
932
933 // XXX Need to rework Device related
934 void putDevice(DeviceEvent deviceEvent) {
935 if (deviceEvent == null) {
936 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800937 }
938
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800939 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
940 if (device == null) {
941 device = new DeviceImpl(networkGraph, deviceEvent.getMac());
942 }
943 DeviceImpl memDevice = getDeviceImpl(device);
944
945 // for each IP address
946 for (InetAddress ipAddr : deviceEvent.getIpAddresses()) {
947 memDevice.addIpAddress(ipAddr);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800948 }
949
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800950 networkGraph.putDevice(device);
951
952 // for each attachment point
953 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
954 // Attached Ports must exist
955 Port port = networkGraph.getPort(swp.dpid, swp.number);
956 if (port == null) {
957 log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
958 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800959 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800960 // Attached Ports must not have Link
961 if (port.getOutgoingLink() != null ||
962 port.getIncomingLink() != null) {
963 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
964 port.getOutgoingLink(),
965 port.getIncomingLink());
966 continue;
967 }
968
969 // finally add Device <-> Port on In-memory structure
970 PortImpl memPort = getPortImpl(port);
971 memPort.addDevice(device);
972 memDevice.addAttachmentPoint(port);
973 }
974 }
975
976 void removeDevice(DeviceEvent deviceEvent) {
977 if (deviceEvent == null) {
978 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800979 }
980
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800981 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
982 if (device == null) {
983 log.warn("Device {} already removed, ignoring", deviceEvent);
984 return;
985 }
986 DeviceImpl memDevice = getDeviceImpl(device);
987
988 // for each attachment point
989 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
990 // Attached Ports must exist
991 Port port = networkGraph.getPort(swp.dpid, swp.number);
992 if (port == null) {
993 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
994 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800995 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800996
997 // finally remove Device <-> Port on In-memory structure
998 PortImpl memPort = getPortImpl(port);
999 memPort.removeDevice(device);
1000 memDevice.removeAttachmentPoint(port);
1001 }
1002 networkGraph.removeDevice(device);
1003 }
1004
1005 private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
1006 for (INetworkGraphListener listener : this.networkGraphListeners) {
1007 // TODO Should copy before handing them over to listener
1008 listener.putSwitchEvent(switchEvent);
1009 }
1010 }
1011
1012 private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
1013 for (INetworkGraphListener listener : this.networkGraphListeners) {
1014 // TODO Should copy before handing them over to listener
1015 listener.removeSwitchEvent(switchEvent);
1016 }
1017 }
1018
1019 private void dispatchPutPortEvent(PortEvent portEvent) {
1020 for (INetworkGraphListener listener : this.networkGraphListeners) {
1021 // TODO Should copy before handing them over to listener
1022 listener.putPortEvent(portEvent);
1023 }
1024 }
1025
1026 private void dispatchRemovePortEvent(PortEvent portEvent) {
1027 for (INetworkGraphListener listener : this.networkGraphListeners) {
1028 // TODO Should copy before handing them over to listener
1029 listener.removePortEvent(portEvent);
1030 }
1031 }
1032
1033 private void dispatchPutLinkEvent(LinkEvent linkEvent) {
1034 for (INetworkGraphListener listener : this.networkGraphListeners) {
1035 // TODO Should copy before handing them over to listener
1036 listener.putLinkEvent(linkEvent);
1037 }
1038 }
1039
1040 private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
1041 for (INetworkGraphListener listener : this.networkGraphListeners) {
1042 // TODO Should copy before handing them over to listener
1043 listener.removeLinkEvent(linkEvent);
1044 }
1045 }
1046
1047 private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
1048 for (INetworkGraphListener listener : this.networkGraphListeners) {
1049 // TODO Should copy before handing them over to listener
1050 listener.putDeviceEvent(deviceEvent);;
1051 }
1052 }
1053
1054 private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
1055 for (INetworkGraphListener listener : this.networkGraphListeners) {
1056 // TODO Should copy before handing them over to listener
1057 listener.removeDeviceEvent(deviceEvent);
1058 }
1059 }
1060
1061 private SwitchImpl getSwitchImpl(Switch sw) {
1062 if (sw instanceof SwitchImpl) {
1063 return (SwitchImpl) sw;
1064 }
1065 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
1066 }
1067
1068 private PortImpl getPortImpl(Port p) {
1069 if (p instanceof PortImpl) {
1070 return (PortImpl) p;
1071 }
1072 throw new ClassCastException("PortImpl expected, but found: " + p);
1073 }
1074
1075 private LinkImpl getLinkImpl(Link l) {
1076 if (l instanceof LinkImpl) {
1077 return (LinkImpl) l;
1078 }
1079 throw new ClassCastException("LinkImpl expected, but found: " + l);
1080 }
1081
1082 private DeviceImpl getDeviceImpl(Device d) {
1083 if (d instanceof DeviceImpl) {
1084 return (DeviceImpl) d;
1085 }
1086 throw new ClassCastException("DeviceImpl expected, but found: " + d);
1087 }
1088
1089 @Deprecated
1090 public void loadWholeTopologyFromDB() {
1091 // XXX May need to clear whole topology first, depending on
1092 // how we initially subscribe to replication events
1093
1094 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
1095 if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
1096 continue;
1097 }
1098 putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001099 }
1100
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001101 for (RCPort p : RCPort.getAllPorts()) {
1102 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1103 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001104 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001105 putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001106 }
1107
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001108 // TODO Is Device going to be in DB? If so, read from DB.
1109 // for (RCDevice d : RCDevice.getAllDevices()) {
1110 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
1111 // for (byte[] portId : d.getAllPortIds() ) {
1112 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
1113 // }
1114 // }
1115
1116 for (RCLink l : RCLink.getAllLinks()) {
1117 // check if src/dst switch/port exist before triggering event
1118 Port srcPort = networkGraph.getPort(l.getSrc().dpid,
1119 l.getSrc().number);
1120 Port dstPort = networkGraph.getPort(l.getDst().dpid,
1121 l.getDst().number);
1122 if (srcPort == null || dstPort == null) {
1123 continue;
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001124 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001125 putLinkReplicationEvent(new LinkEvent(l.getSrc().dpid,
1126 l.getSrc().number,
1127 l.getDst().dpid,
1128 l.getDst().number));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001129 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001130 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001131}