blob: 9acf727bbd7a18f8b269ddff03547001a0dddbd6 [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;
11import java.util.concurrent.LinkedBlockingQueue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080012
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080013import net.onrc.onos.datagrid.IDatagridService;
14import net.onrc.onos.datagrid.IEventChannel;
15import net.onrc.onos.datagrid.IEventChannelListener;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080016import net.onrc.onos.datastore.topology.RCLink;
Jonathan Hart062a2e82014-02-03 09:41:57 -080017import net.onrc.onos.datastore.topology.RCPort;
18import net.onrc.onos.datastore.topology.RCSwitch;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080019import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080020import net.onrc.onos.ofcontroller.util.EventEntry;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080021import net.onrc.onos.ofcontroller.util.Dpid;
Jonathan Hart062a2e82014-02-03 09:41:57 -080022
23import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
25
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080026/**
27 * The "NB" read-only Network Map.
28 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080029 * - Maintain Invariant/Relationships between Topology Objects.
30 *
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080031 * TODO To be synchronized based on TopologyEvent Notification.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080032 *
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080033 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
Yuta HIGUCHI1c700102014-02-12 16:30:52 -080034 * Object must exist before adding sub component(Add Switch -> Port).
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080035 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080036 * TODO TBD: This class may delay the requested change to handle event
37 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080038 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080039 */
Yuta HIGUCHI928fa682014-02-11 19:07:57 -080040public class NetworkGraphImpl extends AbstractNetworkGraph implements
41 NetworkGraphDiscoveryInterface, NetworkGraphReplicationInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080042
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080043 private static final Logger log = LoggerFactory
44 .getLogger(NetworkGraphImpl.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080045
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080046 private IEventChannel<byte[], TopologyEvent> eventChannel;
47 private static final String EVENT_CHANNEL_NAME = "onos.topology";
48 private EventHandler eventHandler = new EventHandler();
49
Jonathan Hart22eb9882014-02-11 15:52:59 -080050 private final NetworkGraphDatastore datastore;
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080051
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080052 public NetworkGraphImpl() {
53 super();
Jonathan Hart22eb9882014-02-11 15:52:59 -080054 datastore = new NetworkGraphDatastore(this);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080055 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080056
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080057 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080058 * Event handler class.
59 */
60 private class EventHandler extends Thread implements
61 IEventChannelListener<byte[], TopologyEvent> {
62 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
63 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
64
65 /**
66 * Startup processing.
67 */
68 private void startup() {
69 //
70 // TODO: Read all state from the database
71 // For now, as a shortcut we read it from the datagrid
72 //
73 Collection<TopologyEvent> topologyEvents =
74 eventChannel.getAllEntries();
75 Collection<EventEntry<TopologyEvent>> collection =
76 new LinkedList<EventEntry<TopologyEvent>>();
77
78 for (TopologyEvent topologyEvent : topologyEvents) {
79 EventEntry<TopologyEvent> eventEntry =
80 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
81 topologyEvent);
82 collection.add(eventEntry);
83 }
84 processEvents(collection);
85 }
86
87 /**
88 * Run the thread.
89 */
90 public void run() {
91 Collection<EventEntry<TopologyEvent>> collection =
92 new LinkedList<EventEntry<TopologyEvent>>();
93
94 this.setName("NetworkGraphImpl.EventHandler " + this.getId());
95 startup();
96
97 //
98 // The main loop
99 //
100 try {
101 while (true) {
102 EventEntry<TopologyEvent> eventEntry = topologyEvents.take();
103 collection.add(eventEntry);
104 topologyEvents.drainTo(collection);
105
106 processEvents(collection);
107 collection.clear();
108 }
109 } catch (Exception exception) {
110 log.debug("Exception processing Topology Events: ", exception);
111 }
112 }
113
114 /**
115 * Process all topology events.
116 *
117 * @param events the events to process.
118 */
119 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
120 for (EventEntry<TopologyEvent> event : events) {
121 TopologyEvent topologyEvent = event.eventData();
122 switch (event.eventType()) {
123 case ENTRY_ADD:
124 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
125 if (topologyEvent.switchEvent != null)
126 putSwitchReplicationEvent(topologyEvent.switchEvent);
127 if (topologyEvent.portEvent != null)
128 putPortReplicationEvent(topologyEvent.portEvent);
129 if (topologyEvent.linkEvent != null)
130 putLinkReplicationEvent(topologyEvent.linkEvent);
131 if (topologyEvent.deviceEvent != null)
132 putDeviceReplicationEvent(topologyEvent.deviceEvent);
133 break;
134 case ENTRY_REMOVE:
135 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
136 if (topologyEvent.switchEvent != null)
137 removeSwitchReplicationEvent(topologyEvent.switchEvent);
138 if (topologyEvent.portEvent != null)
139 removePortReplicationEvent(topologyEvent.portEvent);
140 if (topologyEvent.linkEvent != null)
141 removeLinkReplicationEvent(topologyEvent.linkEvent);
142 if (topologyEvent.deviceEvent != null)
143 removeDeviceReplicationEvent(topologyEvent.deviceEvent);
144 break;
145 }
146 }
147 }
148
149 /**
150 * Receive a notification that an entry is added.
151 *
152 * @param value the value for the entry.
153 */
154 @Override
155 public void entryAdded(TopologyEvent value) {
156 EventEntry<TopologyEvent> eventEntry =
157 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
158 value);
159 topologyEvents.add(eventEntry);
160 }
161
162 /**
163 * Receive a notification that an entry is removed.
164 *
165 * @param value the value for the entry.
166 */
167 @Override
168 public void entryRemoved(TopologyEvent value) {
169 EventEntry<TopologyEvent> eventEntry =
170 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
171 value);
172 topologyEvents.add(eventEntry);
173 }
174
175 /**
176 * Receive a notification that an entry is updated.
177 *
178 * @param value the value for the entry.
179 */
180 @Override
181 public void entryUpdated(TopologyEvent value) {
182 // NOTE: The ADD and UPDATE events are processed in same way
183 entryAdded(value);
184 }
185 }
186
187 /**
188 * Startup processing.
189 *
190 * @param datagridService the datagrid service to use.
191 */
192 void startup(IDatagridService datagridService) {
193 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
194 eventHandler,
195 byte[].class,
196 TopologyEvent.class);
197 eventHandler.start();
198 }
199
200 /**
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800201 * Exception to be thrown when Modification to the Network Graph cannot be continued due to broken invariant.
202 *
203 * XXX Should this be checked exception or RuntimeException
204 */
205 public static class BrokenInvariantException extends RuntimeException {
206 private static final long serialVersionUID = 1L;
207
208 public BrokenInvariantException() {
209 super();
210 }
211
212 public BrokenInvariantException(String message) {
213 super(message);
214 }
215 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800216
217 /* ******************************
218 * NetworkGraphDiscoveryInterface methods
219 * ******************************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800220
Jonathan Hart22eb9882014-02-11 15:52:59 -0800221 @Override
222 public void putSwitchEvent(SwitchEvent switchEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800223 if (prepareForAddSwitchEvent(switchEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800224 datastore.addSwitch(switchEvent);
225 putSwitch(switchEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800226 // Send out notification
227 TopologyEvent topologyEvent =
228 new TopologyEvent(switchEvent);
229 eventChannel.addEntry(topologyEvent.getID(),
230 topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800231 }
232 // TODO handle invariant violation
233 }
234
235 @Override
236 public void removeSwitchEvent(SwitchEvent switchEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800237 if (prepareForRemoveSwitchEvent(switchEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800238 datastore.deactivateSwitch(switchEvent);
239 removeSwitch(switchEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800240 // Send out notification
241 eventChannel.removeEntry(switchEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800242 }
243 // TODO handle invariant violation
244 }
245
246 @Override
247 public void putPortEvent(PortEvent portEvent) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800248 if (prepareForAddPortEvent(portEvent)) {
249 datastore.addPort(portEvent);
250 putPort(portEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800251 // Send out notification
252 TopologyEvent topologyEvent =
253 new TopologyEvent(portEvent);
254 eventChannel.addEntry(topologyEvent.getID(),
255 topologyEvent);
Jonathan Hart4c263272014-02-13 17:41:05 -0800256 }
Yuta HIGUCHI75c51ed2014-02-13 17:02:26 -0800257 // TODO handle invariant violation
Jonathan Hart22eb9882014-02-11 15:52:59 -0800258 }
259
260 @Override
261 public void removePortEvent(PortEvent portEvent) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800262 if (prepareForRemovePortEvent(portEvent)) {
263 datastore.deactivatePort(portEvent);
264 removePort(portEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800265 // Send out notification
266 eventChannel.removeEntry(portEvent.getID());
Jonathan Hart4c263272014-02-13 17:41:05 -0800267 }
Yuta HIGUCHI75c51ed2014-02-13 17:02:26 -0800268 // TODO handle invariant violation
Jonathan Hart22eb9882014-02-11 15:52:59 -0800269 }
270
271 @Override
272 public void putLinkEvent(LinkEvent linkEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800273 if (prepareForAddLinkEvent(linkEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800274 datastore.addLink(linkEvent);
275 putLink(linkEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800276 // Send out notification
277 TopologyEvent topologyEvent =
278 new TopologyEvent(linkEvent);
279 eventChannel.addEntry(topologyEvent.getID(),
280 topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800281 }
282 // TODO handle invariant violation
283 }
284
285 @Override
286 public void removeLinkEvent(LinkEvent linkEvent) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800287 if (prepareForRemoveLinkEvent(linkEvent)) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800288 datastore.removeLink(linkEvent);
289 removeLink(linkEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800290 // Send out notification
291 eventChannel.removeEntry(linkEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800292 }
293 // TODO handle invariant violation
294 }
295
296 @Override
Yuta HIGUCHI586d33e2014-02-13 17:05:08 -0800297 public void putDeviceEvent(DeviceEvent deviceEvent) {
298 if (prepareForAddDeviceEvent(deviceEvent)) {
299// datastore.addDevice(deviceEvent);
Yuta HIGUCHId457c052014-02-14 18:33:04 -0800300// putDevice(deviceEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800301 // Send out notification
302 TopologyEvent topologyEvent =
303 new TopologyEvent(deviceEvent);
304 eventChannel.addEntry(topologyEvent.getID(),
305 topologyEvent);
Yuta HIGUCHI586d33e2014-02-13 17:05:08 -0800306 }
307 // TODO handle invariant violation
308 // XXX if prepareFor~ method returned false, event should be dropped
Jonathan Hart22eb9882014-02-11 15:52:59 -0800309 }
310
311 @Override
312 public void removeDeviceEvent(DeviceEvent deviceEvent) {
Yuta HIGUCHI586d33e2014-02-13 17:05:08 -0800313 if (prepareForRemoveDeviceEvent(deviceEvent)) {
314// datastore.removeDevice(deviceEvent);
Yuta HIGUCHId457c052014-02-14 18:33:04 -0800315// removeDevice(deviceEvent);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800316 // Send out notification
317 eventChannel.removeEntry(deviceEvent.getID());
Yuta HIGUCHI586d33e2014-02-13 17:05:08 -0800318 }
319 // TODO handle invariant violation
320 // XXX if prepareFor~ method returned false, event should be dropped
Jonathan Hart22eb9882014-02-11 15:52:59 -0800321 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800322
Jonathan Hart22eb9882014-02-11 15:52:59 -0800323 /* *****************
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800324 * Internal methods to maintain invariants of the network graph
Jonathan Hart22eb9882014-02-11 15:52:59 -0800325 * *****************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800326
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800327 /**
328 *
329 * @param swEvt
330 * @return true if ready to accept event.
331 */
332 private boolean prepareForAddSwitchEvent(SwitchEvent swEvt) {
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800333 // No show stopping precondition
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800334 // Prep: remove(deactivate) Ports on Switch, which is not on event
335 removePortsNotOnEvent(swEvt);
336 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800337 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800338
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800339 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvt) {
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800340 // No show stopping precondition
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800341 // Prep: remove(deactivate) Ports on Switch, which is not on event
342 // XXX may be remove switch should imply wipe all ports
343 removePortsNotOnEvent(swEvt);
344 return true;
345 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800346
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800347 private void removePortsNotOnEvent(SwitchEvent swEvt) {
348 Switch sw = switches.get( swEvt.getDpid() );
349 if ( sw != null ) {
350 Set<Long> port_noOnEvent = new HashSet<>();
351 for( PortEvent portEvent : swEvt.getPorts()) {
352 port_noOnEvent.add(portEvent.getNumber());
353 }
354 // Existing ports not on event should be removed.
355 // TODO Should batch eventually for performance?
Jonathan Hart480c5572014-02-14 18:28:16 -0800356 List<Port> portsToRemove = new ArrayList<Port>();
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800357 for( Port p : sw.getPorts() ) {
358 if ( !port_noOnEvent.contains(p.getNumber()) ) {
Jonathan Hart480c5572014-02-14 18:28:16 -0800359 //PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
360 // calling Discovery removePort() API to wipe from DB, etc.
361 //removePortEvent(rmEvent);
362
363 // We can't remove ports here because this will trigger a remove
364 // from the switch's port list, which we are currently iterating
365 // over.
366 portsToRemove.add(p);
367 }
368 }
369 for (Port p : portsToRemove) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800370 PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
371 // calling Discovery removePort() API to wipe from DB, etc.
372 removePortEvent(rmEvent);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800373 }
374 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800375 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800376
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800377 private boolean prepareForAddPortEvent(PortEvent portEvt) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800378 // Parent Switch must exist
379 if ( getSwitch(portEvt.getDpid()) == null) {
380 return false;
381 }
382 // Prep: None
Jonathan Hart22eb9882014-02-11 15:52:59 -0800383 return true;
384 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800385
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800386 private boolean prepareForRemovePortEvent(PortEvent portEvt) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800387 // Parent Switch must exist
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800388 Switch sw = getSwitch(portEvt.getDpid());
389 if ( sw == null ) {
Yuta HIGUCHI88be0f22014-02-14 17:20:43 -0800390 log.debug("Switch already removed? {}", portEvt);
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800391 return false;
392 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800393 Port port = sw.getPort(portEvt.getNumber());
394 if ( port == null ) {
395 log.debug("Port already removed? {}", portEvt);
396 // let it pass
397 return true;
398 }
399
400 // Prep: Remove Link and Device Attachment
401 for (Device device : port.getDevices()) {
Yuta HIGUCHI88be0f22014-02-14 17:20:43 -0800402 log.debug("Removing Device {} on Port {}", device, portEvt);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800403 DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
404 devEvt.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(), port.getNumber()));
405 // calling Discovery API to wipe from DB, etc.
406 removeDeviceEvent(devEvt);
407 }
408 Set<Link> links = new HashSet<>();
409 links.add(port.getOutgoingLink());
410 links.add(port.getIncomingLink());
411 for ( Link link : links) {
412 if (link == null ) {
413 continue;
414 }
Yuta HIGUCHI88be0f22014-02-14 17:20:43 -0800415 log.debug("Removing Link {} on Port {}", link, portEvt);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800416 LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(), link.getSourcePortNumber(), link.getDestinationSwitchDpid(), link.getDestinationPortNumber());
417 // calling Discovery API to wipe from DB, etc.
418 removeLinkEvent(linkEvent);
419 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800420 return true;
421 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800422
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800423 private boolean prepareForAddLinkEvent(LinkEvent linkEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800424 // Src/Dst Switch must exist
425 Switch srcSw = getSwitch(linkEvt.getSrc().dpid);
426 Switch dstSw = getSwitch(linkEvt.getDst().dpid);
427 if ( srcSw == null || dstSw == null ) {
428 return false;
429 }
430 // Src/Dst Port must exist
431 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
Jonathan Hart4c263272014-02-13 17:41:05 -0800432 Port dstPort = dstSw.getPort(linkEvt.getDst().number);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800433 if ( srcPort == null || dstPort == null ) {
434 return false;
435 }
436
437 // Prep: remove Device attachment on both Ports
438 for (Device device : srcPort.getDevices()) {
439 DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
440 devEvt.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
441 // calling Discovery API to wipe from DB, etc.
442 removeDeviceEvent(devEvt);
443 }
444 for (Device device : dstPort.getDevices()) {
445 DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
446 devEvt.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(), dstPort.getNumber()));
447 // calling Discovery API to wipe from DB, etc.
448 removeDeviceEvent(devEvt);
449 }
450
451 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800452 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800453
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800454 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800455 // Src/Dst Switch must exist
456 Switch srcSw = getSwitch(linkEvt.getSrc().dpid);
457 Switch dstSw = getSwitch(linkEvt.getDst().dpid);
458 if ( srcSw == null || dstSw == null ) {
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800459 log.warn("Rejecting removeLink {} because switch doesn't exist", linkEvt);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800460 return false;
461 }
462 // Src/Dst Port must exist
463 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800464 Port dstPort = dstSw.getPort(linkEvt.getDst().number);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800465 if ( srcPort == null || dstPort == null ) {
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800466 log.warn("Rejecting removeLink {} because port doesn't exist", linkEvt);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800467 return false;
468 }
469
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800470 Link link = srcPort.getOutgoingLink();
471
472 // Link is already gone, or different Link exist in memory
473 // XXX Check if we should reject or just accept these cases.
474 // it should be harmless to remove the Link on event from DB anyways
475 if (link == null ||
476 !link.getDestinationPortNumber().equals(linkEvt.getDst().number)
477 || !link.getDestinationSwitchDpid().equals(linkEvt.getDst().dpid)) {
478 log.warn("Rejecting removeLink {} because link doesn't exist", linkEvt);
479 return false;
480 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800481 // Prep: None
482 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800483 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800484
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800485 /**
486 *
487 * @param deviceEvt Event will be modified to remove inapplicable attachemntPoints/ipAddress
488 * @return false if this event should be dropped.
489 */
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800490 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvt) {
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800491 boolean preconditionBroken = false;
492 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
493 for ( PortEvent.SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800494 // Attached Ports' Parent Switch must exist
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800495 Switch sw = getSwitch(swp.dpid);
496 if ( sw == null ) {
497 preconditionBroken = true;
498 failedSwitchPort.add(swp);
499 continue;
500 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800501 // Attached Ports must exist
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800502 Port port = sw.getPort(swp.number);
503 if ( port == null ) {
504 preconditionBroken = true;
505 failedSwitchPort.add(swp);
506 continue;
507 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800508 // Attached Ports must not have Link
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800509 if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
510 preconditionBroken = true;
511 failedSwitchPort.add(swp);
512 continue;
513 }
514 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800515
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800516 // Rewriting event to exclude failed attachmentPoint
517 // XXX Assumption behind this is that inapplicable device event should
518 // be dropped, not deferred. If we decide to defer Device event,
519 // rewriting can become a problem
520 List<SwitchPort> attachmentPoints = deviceEvt.getAttachmentPoints();
521 attachmentPoints.removeAll(failedSwitchPort);
522 deviceEvt.setAttachmentPoints(attachmentPoints);
523
524 if ( deviceEvt.getAttachmentPoints().isEmpty() && deviceEvt.getIpAddresses().isEmpty() ) {
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800525 // return false to represent: Nothing left to do for this event. Caller should drop event
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800526 return false;
527 }
528
529 // Should we return false to tell caller that the event was trimmed?
530 // if ( preconditionBroken ) {
531 // return false;
532 // }
533
534 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800535 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800536
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800537 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvt) {
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800538 // No show stopping precondition?
539 // Prep: none
Jonathan Hart22eb9882014-02-11 15:52:59 -0800540 return true;
541 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800542
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800543 /* ******************************
544 * NetworkGraphReplicationInterface methods
545 * ******************************/
546
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800547 @Override
548 public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800549 if (prepareForAddSwitchEvent(switchEvent)) {
550 putSwitch(switchEvent);
551 }
552 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800553 }
554
555 @Override
556 public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800557 if (prepareForRemoveSwitchEvent(switchEvent)) {
558 removeSwitch(switchEvent);
559 }
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800560 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800561 }
562
563 @Override
564 public void putPortReplicationEvent(PortEvent portEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800565 if (prepareForAddPortEvent(portEvent)) {
566 putPort(portEvent);
567 }
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800568 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800569 }
570
571 @Override
572 public void removePortReplicationEvent(PortEvent portEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800573 if (prepareForRemovePortEvent(portEvent)) {
574 removePort(portEvent);
575 }
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800576 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800577 }
578
579 @Override
580 public void putLinkReplicationEvent(LinkEvent linkEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800581 if (prepareForAddLinkEvent(linkEvent)) {
582 putLink(linkEvent);
583 }
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800584 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800585 }
586
587 @Override
588 public void removeLinkReplicationEvent(LinkEvent linkEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800589 if (prepareForRemoveLinkEvent(linkEvent)) {
590 removeLink(linkEvent);
591 }
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800592 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800593 }
594
595 @Override
596 public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800597 if (prepareForAddDeviceEvent(deviceEvent)) {
598 putDevice(deviceEvent);
599 }
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800600 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800601 }
602
603 @Override
604 public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
Yuta HIGUCHI9fc10ac2014-02-12 17:18:57 -0800605 if (prepareForRemoveDeviceEvent(deviceEvent)) {
606 removeDevice(deviceEvent);
607 }
Yuta HIGUCHI125c7df2014-02-14 12:28:10 -0800608 // TODO handle invariant violation
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800609 }
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800610
611 /* ************************************************
612 * Internal In-memory object mutation methods.
613 * ************************************************/
614
615 void putSwitch(SwitchEvent swEvt) {
616 if (swEvt == null) {
617 throw new IllegalArgumentException("Switch cannot be null");
618 }
619
620 Switch sw = switches.get(swEvt.getDpid());
621
622 if (sw == null) {
623 sw = new SwitchImpl(this, swEvt.getDpid());
624 Switch existing = switches.putIfAbsent(swEvt.getDpid(), sw);
625 if (existing != null) {
626 log.warn(
627 "Concurrent putSwitch not expected. Continuing updating {}",
628 existing);
629 sw = existing;
630 }
631 }
632
633 // Update when more attributes are added to Event object
634 // no attribute to update for now
635
636 // TODO handle child Port event properly for performance
637 for (PortEvent portEvt : swEvt.getPorts() ) {
638 putPort(portEvt);
639 }
640
641 }
642
643 void removeSwitch(SwitchEvent swEvt) {
644 if (swEvt == null) {
645 throw new IllegalArgumentException("Switch cannot be null");
646 }
647
648 // TODO handle child Port event properly for performance
649 for (PortEvent portEvt : swEvt.getPorts() ) {
650 removePort(portEvt);
651 }
652
653 Switch sw = switches.get(swEvt.getDpid());
654
655 if (sw == null) {
656 log.warn("Switch {} already removed, ignoring", swEvt);
657 return;
658 }
659
660 // Sanity check
661 if (!sw.getPorts().isEmpty()) {
662 log.warn(
663 "Ports on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
664 swEvt);
665 // XXX Should we remove Port?
666 }
667 if (!sw.getDevices().isEmpty()) {
668 log.warn(
669 "Devices on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
670 swEvt);
671 // XXX Should we remove Device to Switch relation?
672 }
673 if (!sw.getIncomingLinks().iterator().hasNext()) {
674 log.warn(
675 "IncomingLinks on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
676 swEvt);
677 // XXX Should we remove Link?
678 }
679 if (!sw.getOutgoingLinks().iterator().hasNext()) {
680 log.warn(
681 "OutgoingLinks on Switch {} should be removed prior to removing Switch. Removing Switch anyways",
682 swEvt);
683 // XXX Should we remove Link?
684 }
685
686 boolean removed = switches.remove(swEvt.getDpid(), sw);
687 if (removed) {
688 log.warn(
689 "Switch instance was replaced concurrently while removing {}. Something is not right.",
690 sw);
691 }
692 }
693
694 void putPort(PortEvent portEvt) {
695 if (portEvt == null) {
696 throw new IllegalArgumentException("Port cannot be null");
697 }
698 Switch sw = switches.get(portEvt.getDpid());
699 if (sw == null) {
700 throw new BrokenInvariantException(String.format(
701 "Switch with dpid %s did not exist.",
702 new Dpid(portEvt.getDpid())));
703 }
704 Port p = sw.getPort(portEvt.getNumber());
705 PortImpl port = null;
706 if (p != null) {
707 port = getPortImpl(p);
708 }
709
710 if (port == null) {
711 port = new PortImpl(this, sw, portEvt.getNumber());
712 }
713
714 // TODO update attributes
715
716 SwitchImpl s = getSwitchImpl(sw);
717 s.addPort(port);
718 }
719
720 void removePort(PortEvent portEvt) {
721 if (portEvt == null) {
722 throw new IllegalArgumentException("Port cannot be null");
723 }
724
725 Switch sw = switches.get(portEvt.getDpid());
726 if (sw == null) {
727 log.warn("Parent Switch for Port {} already removed, ignoring", portEvt);
728 return;
729 }
730
731 Port p = sw.getPort(portEvt.getNumber());
732 if (p == null) {
733 log.warn("Port {} already removed, ignoring", portEvt);
734 return;
735 }
736
737 // check if there is something referring to this Port
738
739 if (!p.getDevices().iterator().hasNext()) {
740 log.warn(
741 "Devices on Port {} should be removed prior to removing Port. Removing Port anyways",
742 portEvt);
743 // XXX Should we remove Device to Port relation?
744 }
745 if (p.getIncomingLink() != null) {
746 log.warn(
747 "IncomingLinks on Port {} should be removed prior to removing Port. Removing Port anyways",
748 portEvt);
749 // XXX Should we remove Link?
750 }
751 if (p.getOutgoingLink() != null) {
752 log.warn(
753 "OutgoingLinks on Port {} should be removed prior to removing Port. Removing Port anyways",
754 portEvt);
755 // XXX Should we remove Link?
756 }
757
758 // remove Port from Switch
759 SwitchImpl s = getSwitchImpl(sw);
760 s.removePort(p);
761 }
762
763 void putLink(LinkEvent linkEvt) {
764 if (linkEvt == null) {
765 throw new IllegalArgumentException("Link cannot be null");
766 }
767
768 Switch srcSw = switches.get(linkEvt.getSrc().dpid);
769 if (srcSw == null) {
770 throw new BrokenInvariantException(
771 String.format(
772 "Switch with dpid %s did not exist.",
773 new Dpid(linkEvt.getSrc().dpid)));
774 }
775
776 Switch dstSw = switches.get(linkEvt.getDst().dpid);
777 if (dstSw == null) {
778 throw new BrokenInvariantException(
779 String.format(
780 "Switch with dpid %s did not exist.",
781 new Dpid(linkEvt.getDst().dpid)));
782 }
783
784 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
785 if (srcPort == null) {
786 throw new BrokenInvariantException(
787 String.format(
788 "Src Port %s of a Link did not exist.",
789 linkEvt.getSrc() ));
790 }
791
792 Port dstPort = dstSw.getPort(linkEvt.getDst().number);
793 if (dstPort == null) {
794 throw new BrokenInvariantException(
795 String.format(
796 "Dst Port %s of a Link did not exist.",
797 linkEvt.getDst() ));
798 }
799
800 // getting Link instance from destination port incoming Link
801 Link l = dstPort.getIncomingLink();
802 LinkImpl link = null;
803 assert( l == srcPort.getOutgoingLink() );
804 if (l != null) {
805 link = getLinkImpl(l);
806 }
807
808 if (link == null) {
809 link = new LinkImpl(this, srcPort, dstPort);
810 }
811
812
813 PortImpl dstPortMem = getPortImpl(dstPort);
814 PortImpl srcPortMem = getPortImpl(srcPort);
815
816 // Add Link first to avoid further Device addition
817
818 // add Link to Port
819 dstPortMem.setIncomingLink(link);
820 srcPortMem.setOutgoingLink(link);
821
822 // remove Device Pointing to Port if any
823 for(Device d : dstPortMem.getDevices() ) {
824 log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, dstPort, linkEvt);
825 DeviceImpl dev = getDeviceImpl(d);
826 dev.removeAttachmentPoint(dstPort);
Yuta HIGUCHI407261a2014-02-13 16:34:06 -0800827 // This implies that change is made to Device Object.
828 // sending Device attachment point removed event
829 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
830 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(), dstPort.getNumber()));
831 removeDeviceEvent(rmEvent);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800832 }
833 dstPortMem.removeAllDevice();
834 for(Device d : srcPortMem.getDevices() ) {
835 log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, srcPort, linkEvt);
836 DeviceImpl dev = getDeviceImpl(d);
837 dev.removeAttachmentPoint(srcPort);
Yuta HIGUCHI407261a2014-02-13 16:34:06 -0800838 // This implies that change is made to Device Object.
839 // sending Device attachment point removed event
840 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
841 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(), dstPort.getNumber()));
842 removeDeviceEvent(rmEvent);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800843 }
844 srcPortMem.removeAllDevice();
845
846 }
847
848 void removeLink(LinkEvent linkEvt) {
849 if (linkEvt == null) {
850 throw new IllegalArgumentException("Link cannot be null");
851 }
852
853 Switch srcSw = switches.get(linkEvt.getSrc().dpid);
854 if (srcSw == null) {
855 log.warn("Src Switch for Link {} already removed, ignoring", linkEvt);
856 return;
857 }
858
859 Switch dstSw = switches.get(linkEvt.getDst().dpid);
860 if (dstSw == null) {
861 log.warn("Dst Switch for Link {} already removed, ignoring", linkEvt);
862 return;
863 }
864
865 Port srcPort = srcSw.getPort(linkEvt.getSrc().number);
866 if (srcPort == null) {
867 log.warn("Src Port for Link {} already removed, ignoring", linkEvt);
868 return;
869 }
870
871 Port dstPort = dstSw.getPort(linkEvt.getDst().number);
872 if (dstPort == null) {
873 log.warn("Dst Port for Link {} already removed, ignoring", linkEvt);
874 return;
875 }
876
877 Link l = dstPort.getIncomingLink();
878 if ( l == null ) {
879 log.warn("Link {} already removed on destination Port", linkEvt);
880 }
881 l = srcPort.getOutgoingLink();
882 if ( l == null ) {
883 log.warn("Link {} already removed on src Port", linkEvt);
884 }
885
886 getPortImpl(dstPort).setIncomingLink(null);
887 getPortImpl(srcPort).setOutgoingLink(null);
888 }
889
890 // XXX Need to rework Device related
891 void putDevice(DeviceEvent deviceEvt) {
892 if (deviceEvt == null) {
893 throw new IllegalArgumentException("Device cannot be null");
894 }
895
896 Device device = getDeviceByMac(deviceEvt.getMac());
897 if ( device == null ) {
898 device = new DeviceImpl(this, deviceEvt.getMac());
899 Device existing = mac2Device.putIfAbsent(deviceEvt.getMac(), device);
900 if (existing != null) {
901 log.warn(
902 "Concurrent putDevice seems to be in action. Continuing updating {}",
903 existing);
904 device = existing;
905 }
906 }
907 DeviceImpl memDevice = getDeviceImpl(device);
908
909 // for each attachment point
910 for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
911 // Attached Ports' Parent Switch must exist
912 Switch sw = getSwitch(swp.dpid);
913 if ( sw == null ) {
Yuta HIGUCHI25719052014-02-13 14:42:06 -0800914 log.warn("Switch for the attachment point {} did not exist. skipping mutation", swp);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800915 continue;
916 }
917 // Attached Ports must exist
918 Port port = sw.getPort(swp.number);
919 if ( port == null ) {
Yuta HIGUCHI25719052014-02-13 14:42:06 -0800920 log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800921 continue;
922 }
923 // Attached Ports must not have Link
924 if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
925 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.", port.getOutgoingLink(), port.getIncomingLink());
926 continue;
927 }
928
929 // finally add Device <-> Port on In-memory structure
930 PortImpl memPort = getPortImpl(port);
931 memPort.addDevice(device);
932 memDevice.addAttachmentPoint(port);
933 }
934
935 // for each IP address
936 for( InetAddress ipAddr : deviceEvt.getIpAddresses() ) {
937 // Add Device -> IP
938 memDevice.addIpAddress(ipAddr);
939
940 // Add IP -> Set<Device>
941 boolean updated = false;
942 do {
943 Set<Device> devices = this.addr2Device.get(ipAddr);
944 if ( devices == null ) {
945 devices = new HashSet<>();
946 Set<Device> existing = this.addr2Device.putIfAbsent(ipAddr, devices);
947 if ( existing == null ) {
948 // success
949 updated = true;
950 }
951 } else {
952 Set<Device> updateDevices = new HashSet<>(devices);
953 updateDevices.add(device);
954 updated = this.addr2Device.replace(ipAddr, devices, updateDevices);
955 }
956 if (!updated) {
957 log.debug("Collision detected, updating IP to Device mapping retrying.");
958 }
959 } while( !updated );
960 }
961 }
962
963 void removeDevice(DeviceEvent deviceEvt) {
964 if (deviceEvt == null) {
965 throw new IllegalArgumentException("Device cannot be null");
966 }
967
968 Device device = getDeviceByMac(deviceEvt.getMac());
969 if ( device == null ) {
970 log.warn("Device {} already removed, ignoring", deviceEvt);
971 return;
972 }
973 DeviceImpl memDevice = getDeviceImpl(device);
974
975 // for each attachment point
976 for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
977 // Attached Ports' Parent Switch must exist
978 Switch sw = getSwitch(swp.dpid);
979 if ( sw == null ) {
Yuta HIGUCHI25719052014-02-13 14:42:06 -0800980 log.warn("Switch for the attachment point {} did not exist. skipping attachment point mutation", swp);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800981 continue;
982 }
983 // Attached Ports must exist
984 Port port = sw.getPort(swp.number);
985 if ( port == null ) {
Yuta HIGUCHI25719052014-02-13 14:42:06 -0800986 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800987 continue;
988 }
989
990 // finally remove Device <-> Port on In-memory structure
991 PortImpl memPort = getPortImpl(port);
992 memPort.removeDevice(device);
993 memDevice.removeAttachmentPoint(port);
994 }
995
996 // for each IP address
997 for( InetAddress ipAddr : deviceEvt.getIpAddresses() ) {
998 // Remove Device -> IP
999 memDevice.removeIpAddress(ipAddr);
1000
1001 // Remove IP -> Set<Device>
1002 boolean updated = false;
1003 do {
1004 Set<Device> devices = this.addr2Device.get(ipAddr);
1005 if ( devices == null ) {
1006 // already empty set, nothing to do
1007 updated = true;
1008 } else {
1009 Set<Device> updateDevices = new HashSet<>(devices);
1010 updateDevices.remove(device);
1011 updated = this.addr2Device.replace(ipAddr, devices, updateDevices);
1012 }
1013 if (!updated) {
1014 log.debug("Collision detected, updating IP to Device mapping retrying.");
1015 }
1016 } while( !updated );
1017 }
1018 }
1019
1020 private SwitchImpl getSwitchImpl(Switch sw) {
1021 if (sw instanceof SwitchImpl) {
1022 return (SwitchImpl) sw;
1023 }
1024 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
1025 }
1026
1027 private PortImpl getPortImpl(Port p) {
1028 if (p instanceof PortImpl) {
1029 return (PortImpl) p;
1030 }
1031 throw new ClassCastException("PortImpl expected, but found: " + p);
1032 }
1033
1034 private LinkImpl getLinkImpl(Link l) {
1035 if (l instanceof LinkImpl) {
1036 return (LinkImpl) l;
1037 }
1038 throw new ClassCastException("LinkImpl expected, but found: " + l);
1039 }
1040
1041 private DeviceImpl getDeviceImpl(Device d) {
1042 if (d instanceof DeviceImpl) {
1043 return (DeviceImpl) d;
1044 }
1045 throw new ClassCastException("DeviceImpl expected, but found: " + d);
1046 }
1047
1048 @Deprecated
1049 public void loadWholeTopologyFromDB() {
1050 // XXX clear everything first?
1051
1052 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
1053 if ( sw.getStatus() != RCSwitch.STATUS.ACTIVE ) {
1054 continue;
1055 }
1056 putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
1057 }
1058
1059 for (RCPort p : RCPort.getAllPorts()) {
1060 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1061 continue;
1062 }
1063 putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber() ));
1064 }
1065
1066 // TODO Is Device going to be in DB? If so, read from DB.
1067 // for (RCDevice d : RCDevice.getAllDevices()) {
1068 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
1069 // for (byte[] portId : d.getAllPortIds() ) {
1070 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
1071 // }
1072 // }
1073
1074 for (RCLink l : RCLink.getAllLinks()) {
1075 putLinkReplicationEvent( new LinkEvent(l.getSrc().dpid, l.getSrc().number, l.getDst().dpid, l.getDst().number));
1076 }
1077 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001078}