blob: 02755758f239e92570c3fe32bdc9a0fa1a0847f8 [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 Radoslavov50cd1482014-02-19 16:57:03 -0800252 if (datastore.addSwitch(switchEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800253 // Send out notification
254 TopologyEvent topologyEvent =
255 new TopologyEvent(switchEvent, registryService.getControllerId());
256 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
257 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800258 }
259
260 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800261 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800262 if (datastore.deactivateSwitch(switchEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800263 // Send out notification
264 eventChannel.removeEntry(switchEvent.getID());
265 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800266 }
267
268 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800269 public void putPortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800270 if (datastore.addPort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800271 // Send out notification
272 TopologyEvent topologyEvent =
273 new TopologyEvent(portEvent, registryService.getControllerId());
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800274 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800275 }
276
277 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800278 public void removePortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800279 if (datastore.deactivatePort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800280 // Send out notification
281 eventChannel.removeEntry(portEvent.getID());
282 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800283 }
284
285 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800286 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800287 if (datastore.addLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800288 // Send out notification
289 TopologyEvent topologyEvent =
290 new TopologyEvent(linkEvent, registryService.getControllerId());
291 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
292 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800293 }
294
295 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800296 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800297 if (datastore.removeLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800298 // Send out notification
299 eventChannel.removeEntry(linkEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800300 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800301 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800302
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800303 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800304 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800305 if (datastore.addDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800306 // Send out notification
307 TopologyEvent topologyEvent =
308 new TopologyEvent(deviceEvent,
309 registryService.getControllerId());
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800310 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800311 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800312 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800313
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800314 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800315 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800316 if (datastore.removeDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800317 // Send out notification
318 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800319 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800320 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800321
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800322 /* *****************
323 * Internal methods to maintain invariants of the network graph
324 * *****************/
Jonathan Hart22eb9882014-02-11 15:52:59 -0800325
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800326 /**
327 *
328 * @param swEvent
329 * @return true if ready to accept event.
330 */
331 private boolean prepareForAddSwitchEvent(SwitchEvent swEvent) {
332 // No show stopping precondition
333 // Prep: remove(deactivate) Ports on Switch, which is not on event
334 removePortsNotOnEvent(swEvent);
335 return true;
336 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800337
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800338 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvent) {
339 // No show stopping precondition
340 // Prep: remove(deactivate) Ports on Switch, which is not on event
341 // XXX may be remove switch should imply wipe all ports
342 removePortsNotOnEvent(swEvent);
343 return true;
344 }
Yuta HIGUCHI71e7a052014-02-17 22:14:15 -0800345
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800346 private void removePortsNotOnEvent(SwitchEvent swEvent) {
347 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
348 if (sw != null) {
349 Set<Long> port_noOnEvent = new HashSet<>();
350 for (PortEvent portEvent : swEvent.getPorts()) {
351 port_noOnEvent.add(portEvent.getNumber());
352 }
353 // Existing ports not on event should be removed.
354 // TODO Should batch eventually for performance?
355 List<Port> portsToRemove = new ArrayList<Port>();
356 for (Port p : sw.getPorts()) {
357 if (!port_noOnEvent.contains(p.getNumber())) {
358 //PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
359 // calling Discovery removePort() API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800360 //removePortDiscoveryEvent(rmEvent);
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800361
Jonathan Hart480c5572014-02-14 18:28:16 -0800362 // We can't remove ports here because this will trigger a remove
363 // from the switch's port list, which we are currently iterating
364 // over.
365 portsToRemove.add(p);
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800366 }
367 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800368 for (Port p : portsToRemove) {
369 PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(),
370 p.getNumber());
371 // calling Discovery removePort() API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800372 removePortDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800373 }
374 }
375 }
376
377 private boolean prepareForAddPortEvent(PortEvent portEvent) {
378 // Parent Switch must exist
379 if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
380 log.warn("Dropping add port event because switch doesn't exist: {}",
381 portEvent);
382 return false;
383 }
384 // Prep: None
385 return true;
386 }
387
388 private boolean prepareForRemovePortEvent(PortEvent portEvent) {
389 Port port = networkGraph.getPort(portEvent.getDpid(),
390 portEvent.getNumber());
391 if (port == null) {
392 log.debug("Port already removed? {}", portEvent);
393 // let it pass
394 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800395 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800396
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800397 // Prep: Remove Link and Device Attachment
398 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
399 for (Device device : port.getDevices()) {
400 log.debug("Removing Device {} on Port {}", device, portEvent);
401 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
402 devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
403 port.getNumber()));
404 deviceEvents.add(devEvent);
405 }
406 for (DeviceEvent devEvent : deviceEvents) {
407 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800408 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800409 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800410
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800411 Set<Link> links = new HashSet<>();
412 links.add(port.getOutgoingLink());
413 links.add(port.getIncomingLink());
414 for (Link link : links) {
415 if (link == null) {
416 continue;
417 }
418 log.debug("Removing Link {} on Port {}", link, portEvent);
419 LinkEvent linkEvent =
420 new LinkEvent(link.getSourceSwitchDpid(),
421 link.getSourcePortNumber(),
422 link.getDestinationSwitchDpid(),
423 link.getDestinationPortNumber());
424 // calling Discovery API to wipe from DB, etc.
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800425
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800426 // Call internal remove Link, which will check
427 // ownership of DST dpid and modify DB only if it is the owner
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800428 removeLinkDiscoveryEvent(linkEvent, true);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800429 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800430 return true;
431 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800432
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800433 private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
434 // Src/Dst Port must exist
435 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
436 linkEvent.getSrc().number);
437 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
438 linkEvent.getDst().number);
439 if (srcPort == null || dstPort == null) {
Jonathan Hart0a4846e2014-02-18 11:03:40 -0800440 log.warn("Dropping add link event because port doesn't exist: {}",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800441 linkEvent);
442 return false;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800443 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800444
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800445 // Prep: remove Device attachment on both Ports
446 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
447 for (Device device : srcPort.getDevices()) {
448 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
449 devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
450 deviceEvents.add(devEvent);
451 }
452 for (Device device : dstPort.getDevices()) {
453 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
454 devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
455 dstPort.getNumber()));
456 deviceEvents.add(devEvent);
457 }
458 for (DeviceEvent devEvent : deviceEvents) {
459 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800460 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800461 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800462
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800463 return true;
464 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800465
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800466 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
467 // Src/Dst Port must exist
468 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
469 linkEvent.getSrc().number);
470 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
471 linkEvent.getDst().number);
472 if (srcPort == null || dstPort == null) {
473 log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
474 return false;
475 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800476
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800477 Link link = srcPort.getOutgoingLink();
478
479 // Link is already gone, or different Link exist in memory
480 // XXX Check if we should reject or just accept these cases.
481 // it should be harmless to remove the Link on event from DB anyways
482 if (link == null ||
483 !link.getDestinationPortNumber().equals(linkEvent.getDst().number)
484 || !link.getDestinationSwitchDpid().equals(linkEvent.getDst().dpid)) {
485 log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
486 return false;
487 }
488 // Prep: None
489 return true;
490 }
491
492 /**
493 *
494 * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
495 * @return false if this event should be dropped.
496 */
497 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
498 boolean preconditionBroken = false;
499 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
500 for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
501 // Attached Ports must exist
502 Port port = networkGraph.getPort(swp.dpid, swp.number);
503 if (port == null) {
504 preconditionBroken = true;
505 failedSwitchPort.add(swp);
506 continue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800507 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800508 // Attached Ports must not have Link
509 if (port.getOutgoingLink() != null ||
510 port.getIncomingLink() != null) {
511 preconditionBroken = true;
512 failedSwitchPort.add(swp);
513 continue;
514 }
515 }
516
517 // Rewriting event to exclude failed attachmentPoint
518 // XXX Assumption behind this is that inapplicable device event should
519 // be dropped, not deferred. If we decide to defer Device event,
520 // rewriting can become a problem
521 List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
522 attachmentPoints.removeAll(failedSwitchPort);
523 deviceEvent.setAttachmentPoints(attachmentPoints);
524
525 if (deviceEvent.getAttachmentPoints().isEmpty() &&
526 deviceEvent.getIpAddresses().isEmpty()) {
527 // return false to represent: Nothing left to do for this event.
528 // Caller should drop event
529 return false;
530 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800531
532 // Should we return false to tell caller that the event was trimmed?
533 // if ( preconditionBroken ) {
534 // return false;
535 // }
536
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800537 return true;
538 }
539
540 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
541 // No show stopping precondition?
542 // Prep: none
543 return true;
544 }
545
546 /* ******************************
547 * NetworkGraphReplicationInterface methods
548 * ******************************/
549
550 @Override
551 public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
552 if (prepareForAddSwitchEvent(switchEvent)) {
553 putSwitch(switchEvent);
554 }
555 // TODO handle invariant violation
556 // trigger instance local topology event handler
557 dispatchPutSwitchEvent(switchEvent);
558 }
559
560 @Override
561 public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
562 if (prepareForRemoveSwitchEvent(switchEvent)) {
563 removeSwitch(switchEvent);
564 }
565 // TODO handle invariant violation
566 // trigger instance local topology event handler
567 dispatchRemoveSwitchEvent(switchEvent);
568 }
569
570 @Override
571 public void putPortReplicationEvent(PortEvent portEvent) {
572 if (prepareForAddPortEvent(portEvent)) {
573 putPort(portEvent);
574 }
575 // TODO handle invariant violation
576 // trigger instance local topology event handler
577 dispatchPutPortEvent(portEvent);
578 }
579
580 @Override
581 public void removePortReplicationEvent(PortEvent portEvent) {
582 if (prepareForRemovePortEvent(portEvent)) {
583 removePort(portEvent);
584 }
585 // TODO handle invariant violation
586 // trigger instance local topology event handler
587 dispatchRemovePortEvent(portEvent);
588 }
589
590 @Override
591 public void putLinkReplicationEvent(LinkEvent linkEvent) {
592 if (prepareForAddLinkEvent(linkEvent)) {
593 putLink(linkEvent);
594 }
595 // TODO handle invariant violation
596 // trigger instance local topology event handler
597 dispatchPutLinkEvent(linkEvent);
598 }
599
600 @Override
601 public void removeLinkReplicationEvent(LinkEvent linkEvent) {
602 if (prepareForRemoveLinkEvent(linkEvent)) {
603 removeLink(linkEvent);
604 }
605 // TODO handle invariant violation
606 // trigger instance local topology event handler
607 dispatchRemoveLinkEvent(linkEvent);
608 }
609
610 @Override
611 public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
612 if (prepareForAddDeviceEvent(deviceEvent)) {
613 putDevice(deviceEvent);
614 }
615 // TODO handle invariant violation
616 // trigger instance local topology event handler
617 dispatchPutDeviceEvent(deviceEvent);
618 }
619
620 @Override
621 public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
622 if (prepareForRemoveDeviceEvent(deviceEvent)) {
623 removeDevice(deviceEvent);
624 }
625 // TODO handle invariant violation
626 // trigger instance local topology event handler
627 dispatchRemoveDeviceEvent(deviceEvent);
628 }
629
630 /* ************************************************
631 * Internal In-memory object mutation methods.
632 * ************************************************/
633
634 void putSwitch(SwitchEvent swEvent) {
635 if (swEvent == null) {
636 throw new IllegalArgumentException("Switch cannot be null");
Jonathan Hart22eb9882014-02-11 15:52:59 -0800637 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800638
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800639 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
640
641 if (sw == null) {
642 sw = new SwitchImpl(networkGraph, swEvent.getDpid());
643 networkGraph.putSwitch(sw);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800644 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800645
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800646 // Update when more attributes are added to Event object
647 // no attribute to update for now
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800648
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800649 // TODO handle child Port event properly for performance
650 for (PortEvent portEvent : swEvent.getPorts() ) {
651 putPort(portEvent);
652 }
653 }
654
655 void removeSwitch(SwitchEvent swEvent) {
656 if (swEvent == null) {
657 throw new IllegalArgumentException("Switch cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800658 }
659
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800660 // TODO handle child Port event properly for performance
661 for (PortEvent portEvent : swEvent.getPorts() ) {
662 removePort(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800663 }
664
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800665 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
666 if (sw == null) {
667 log.warn("Switch {} already removed, ignoring", swEvent);
668 return;
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800669 }
670
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800671 // remove all ports if there still exist
672 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
673 for (Port port : sw.getPorts()) {
674 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now",
675 port, swEvent);
676 PortEvent portEvent = new PortEvent(port.getDpid(),
677 port.getNumber());
678 portsToRemove.add(portEvent);
679 }
680 for (PortEvent portEvent : portsToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800681 // XXX calling removePortDiscoveryEvent() may trigger duplicate
682 // event, once at prepare phase, second time here
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800683 // If event can be squashed, ignored etc. at receiver side it
684 // shouldn't be a problem, but if not need to re-visit this issue.
685
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800686 // Note: removePortDiscoveryEvent() implies removal of attached
687 // Device, etc. if we decide not to call
688 // removePortDiscoveryEvent(), Device needs to be handled properly.
689 removePortDiscoveryEvent(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800690 }
691
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800692 networkGraph.removeSwitch(swEvent.getDpid());
693 }
694
695 void putPort(PortEvent portEvent) {
696 if (portEvent == null) {
697 throw new IllegalArgumentException("Port cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800698 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800699 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
700 if (sw == null) {
701 throw new BrokenInvariantException(String.format(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800702 "Switch with dpid %s did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800703 new Dpid(portEvent.getDpid())));
704 }
705 Port p = sw.getPort(portEvent.getNumber());
706 PortImpl port = null;
707 if (p != null) {
708 port = getPortImpl(p);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800709 }
710
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800711 if (port == null) {
712 port = new PortImpl(networkGraph, sw, portEvent.getNumber());
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800713 }
714
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800715 // TODO update attributes
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800716
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800717 SwitchImpl s = getSwitchImpl(sw);
718 s.addPort(port);
719 }
720
721 void removePort(PortEvent portEvent) {
722 if (portEvent == null) {
723 throw new IllegalArgumentException("Port cannot be null");
724 }
725
726 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
727 if (sw == null) {
728 log.warn("Parent Switch for Port {} already removed, ignoring",
729 portEvent);
730 return;
731 }
732
733 Port p = sw.getPort(portEvent.getNumber());
734 if (p == null) {
735 log.warn("Port {} already removed, ignoring", portEvent);
736 return;
737 }
738
739 // Remove Link and Device Attachment
740 for (Device device : p.getDevices()) {
741 log.debug("Removing Device {} on Port {}", device, portEvent);
742 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
743 devEvent.addAttachmentPoint(new SwitchPort(p.getSwitch().getDpid(),
744 p.getNumber()));
745
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800746 // XXX calling removeDeviceDiscoveryEvent() may trigger duplicate
747 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800748 // If event can be squashed, ignored etc. at receiver side it
749 // shouldn't be a problem, but if not need to re-visit
750
751 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800752 removeDeviceDiscoveryEvent(devEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800753 }
754 Set<Link> links = new HashSet<>();
755 links.add(p.getOutgoingLink());
756 links.add(p.getIncomingLink());
757 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
758 for (Link link : links) {
759 if (link == null) {
760 continue;
761 }
762 log.debug("Removing Link {} on Port {}", link, portEvent);
763 LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(),
764 link.getSourcePortNumber(),
765 link.getDestinationSwitchDpid(),
766 link.getDestinationPortNumber());
767 linksToRemove.add(linkEvent);
768 }
769 for (LinkEvent linkEvent : linksToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800770 // XXX calling removeLinkDiscoveryEvent() may trigger duplicate
771 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800772 // If event can be squashed, ignored etc. at receiver side it
773 // shouldn't be a problem, but if not need to re-visit
774
775 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800776 removeLinkDiscoveryEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800777 }
778
779 // remove Port from Switch
780 SwitchImpl s = getSwitchImpl(sw);
781 s.removePort(p);
782 }
783
784 void putLink(LinkEvent linkEvent) {
785 if (linkEvent == null) {
786 throw new IllegalArgumentException("Link cannot be null");
787 }
788
789 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
790 linkEvent.getSrc().number);
791 if (srcPort == null) {
792 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800793 String.format(
794 "Src Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800795 linkEvent.getSrc() ));
796 }
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800797
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800798 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
799 linkEvent.getDst().number);
800 if (dstPort == null) {
801 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800802 String.format(
803 "Dst Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800804 linkEvent.getDst()));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800805 }
806
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800807 // getting Link instance from destination port incoming Link
808 Link l = dstPort.getIncomingLink();
809 LinkImpl link = null;
810 assert(l == srcPort.getOutgoingLink());
811 if (l != null) {
812 link = getLinkImpl(l);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800813 }
814
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800815 if (link == null) {
816 link = new LinkImpl(networkGraph, srcPort, dstPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800817 }
818
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800819 PortImpl dstPortMem = getPortImpl(dstPort);
820 PortImpl srcPortMem = getPortImpl(srcPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800821
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800822 // Add Link first to avoid further Device addition
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800823
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800824 // add Link to Port
825 dstPortMem.setIncomingLink(link);
826 srcPortMem.setOutgoingLink(link);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800827
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800828 // remove Device Pointing to Port if any
829 for (Device d : dstPortMem.getDevices() ) {
830 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
831 d, dstPort, linkEvent);
832 DeviceImpl dev = getDeviceImpl(d);
833 dev.removeAttachmentPoint(dstPort);
834 // This implies that change is made to Device Object.
835 // sending Device attachment point removed event
836 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
837 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
838 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800839 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800840 }
841 dstPortMem.removeAllDevice();
842 for (Device d : srcPortMem.getDevices() ) {
843 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
844 d, srcPort, linkEvent);
845 DeviceImpl dev = getDeviceImpl(d);
846 dev.removeAttachmentPoint(srcPort);
847 // This implies that change is made to Device Object.
848 // sending Device attachment point removed event
849 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
850 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
851 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800852 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800853 }
854 srcPortMem.removeAllDevice();
855 }
856
857 void removeLink(LinkEvent linkEvent) {
858 if (linkEvent == null) {
859 throw new IllegalArgumentException("Link cannot be null");
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800860 }
861
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800862 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
863 linkEvent.getSrc().number);
864 if (srcPort == null) {
865 log.warn("Src Port for Link {} already removed, ignoring",
866 linkEvent);
867 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800868 }
869
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800870 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
871 linkEvent.getDst().number);
872 if (dstPort == null) {
873 log.warn("Dst Port for Link {} already removed, ignoring",
874 linkEvent);
875 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800876 }
877
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800878 Link l = dstPort.getIncomingLink();
879 if ( l == null) {
880 log.warn("Link {} already removed on destination Port", linkEvent);
881 }
882 l = srcPort.getOutgoingLink();
883 if (l == null) {
884 log.warn("Link {} already removed on src Port", linkEvent);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800885 }
886
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800887 getPortImpl(dstPort).setIncomingLink(null);
888 getPortImpl(srcPort).setOutgoingLink(null);
889 }
890
891 // XXX Need to rework Device related
892 void putDevice(DeviceEvent deviceEvent) {
893 if (deviceEvent == null) {
894 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800895 }
896
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800897 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
898 if (device == null) {
899 device = new DeviceImpl(networkGraph, deviceEvent.getMac());
900 }
901 DeviceImpl memDevice = getDeviceImpl(device);
902
903 // for each IP address
904 for (InetAddress ipAddr : deviceEvent.getIpAddresses()) {
905 memDevice.addIpAddress(ipAddr);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800906 }
907
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800908 networkGraph.putDevice(device);
909
910 // for each attachment point
911 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
912 // Attached Ports must exist
913 Port port = networkGraph.getPort(swp.dpid, swp.number);
914 if (port == null) {
915 log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
916 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800917 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800918 // Attached Ports must not have Link
919 if (port.getOutgoingLink() != null ||
920 port.getIncomingLink() != null) {
921 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
922 port.getOutgoingLink(),
923 port.getIncomingLink());
924 continue;
925 }
926
927 // finally add Device <-> Port on In-memory structure
928 PortImpl memPort = getPortImpl(port);
929 memPort.addDevice(device);
930 memDevice.addAttachmentPoint(port);
931 }
932 }
933
934 void removeDevice(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 log.warn("Device {} already removed, ignoring", deviceEvent);
942 return;
943 }
944 DeviceImpl memDevice = getDeviceImpl(device);
945
946 // for each attachment point
947 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
948 // Attached Ports must exist
949 Port port = networkGraph.getPort(swp.dpid, swp.number);
950 if (port == null) {
951 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
952 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800953 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800954
955 // finally remove Device <-> Port on In-memory structure
956 PortImpl memPort = getPortImpl(port);
957 memPort.removeDevice(device);
958 memDevice.removeAttachmentPoint(port);
959 }
960 networkGraph.removeDevice(device);
961 }
962
963 private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
964 for (INetworkGraphListener listener : this.networkGraphListeners) {
965 // TODO Should copy before handing them over to listener
966 listener.putSwitchEvent(switchEvent);
967 }
968 }
969
970 private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
971 for (INetworkGraphListener listener : this.networkGraphListeners) {
972 // TODO Should copy before handing them over to listener
973 listener.removeSwitchEvent(switchEvent);
974 }
975 }
976
977 private void dispatchPutPortEvent(PortEvent portEvent) {
978 for (INetworkGraphListener listener : this.networkGraphListeners) {
979 // TODO Should copy before handing them over to listener
980 listener.putPortEvent(portEvent);
981 }
982 }
983
984 private void dispatchRemovePortEvent(PortEvent portEvent) {
985 for (INetworkGraphListener listener : this.networkGraphListeners) {
986 // TODO Should copy before handing them over to listener
987 listener.removePortEvent(portEvent);
988 }
989 }
990
991 private void dispatchPutLinkEvent(LinkEvent linkEvent) {
992 for (INetworkGraphListener listener : this.networkGraphListeners) {
993 // TODO Should copy before handing them over to listener
994 listener.putLinkEvent(linkEvent);
995 }
996 }
997
998 private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
999 for (INetworkGraphListener listener : this.networkGraphListeners) {
1000 // TODO Should copy before handing them over to listener
1001 listener.removeLinkEvent(linkEvent);
1002 }
1003 }
1004
1005 private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
1006 for (INetworkGraphListener listener : this.networkGraphListeners) {
1007 // TODO Should copy before handing them over to listener
1008 listener.putDeviceEvent(deviceEvent);;
1009 }
1010 }
1011
1012 private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
1013 for (INetworkGraphListener listener : this.networkGraphListeners) {
1014 // TODO Should copy before handing them over to listener
1015 listener.removeDeviceEvent(deviceEvent);
1016 }
1017 }
1018
1019 private SwitchImpl getSwitchImpl(Switch sw) {
1020 if (sw instanceof SwitchImpl) {
1021 return (SwitchImpl) sw;
1022 }
1023 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
1024 }
1025
1026 private PortImpl getPortImpl(Port p) {
1027 if (p instanceof PortImpl) {
1028 return (PortImpl) p;
1029 }
1030 throw new ClassCastException("PortImpl expected, but found: " + p);
1031 }
1032
1033 private LinkImpl getLinkImpl(Link l) {
1034 if (l instanceof LinkImpl) {
1035 return (LinkImpl) l;
1036 }
1037 throw new ClassCastException("LinkImpl expected, but found: " + l);
1038 }
1039
1040 private DeviceImpl getDeviceImpl(Device d) {
1041 if (d instanceof DeviceImpl) {
1042 return (DeviceImpl) d;
1043 }
1044 throw new ClassCastException("DeviceImpl expected, but found: " + d);
1045 }
1046
1047 @Deprecated
1048 public void loadWholeTopologyFromDB() {
1049 // XXX May need to clear whole topology first, depending on
1050 // how we initially subscribe to replication events
1051
1052 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
1053 if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
1054 continue;
1055 }
1056 putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001057 }
1058
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001059 for (RCPort p : RCPort.getAllPorts()) {
1060 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1061 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001062 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001063 putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber()));
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001064 }
1065
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001066 // 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 // check if src/dst switch/port exist before triggering event
1076 Port srcPort = networkGraph.getPort(l.getSrc().dpid,
1077 l.getSrc().number);
1078 Port dstPort = networkGraph.getPort(l.getDst().dpid,
1079 l.getDst().number);
1080 if (srcPort == null || dstPort == null) {
1081 continue;
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001082 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001083 putLinkReplicationEvent(new LinkEvent(l.getSrc().dpid,
1084 l.getSrc().number,
1085 l.getDst().dpid,
1086 l.getDst().number));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001087 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001088 }
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -08001089
1090 @Deprecated
1091 private void removeLinkDiscoveryEvent(LinkEvent linkEvent,
1092 boolean dstCheckBeforeDBmodify) {
1093 if (prepareForRemoveLinkEvent(linkEvent)) {
1094 if (dstCheckBeforeDBmodify) {
1095 // write to DB only if it is owner of the dst dpid
1096 // XXX this will cause link remove events to be dropped
1097 // if the dst switch just disconnected
1098 if (registryService.hasControl(linkEvent.getDst().dpid)) {
1099 datastore.removeLink(linkEvent);
1100 }
1101 } else {
1102 datastore.removeLink(linkEvent);
1103 }
1104 removeLink(linkEvent);
1105 // Send out notification
1106 eventChannel.removeEntry(linkEvent.getID());
1107 }
1108 // TODO handle invariant violation
1109 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001110}