blob: ebe99005fb65c0475b9cabd0ee581e20284e6736 [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;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08004import java.nio.ByteBuffer;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08005import java.util.ArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08006import java.util.Collection;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08007import java.util.HashMap;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08008import java.util.HashSet;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08009import java.util.LinkedList;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080010import java.util.List;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080011import java.util.Map;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080012import java.util.Set;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080013import java.util.concurrent.BlockingQueue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080014import java.util.concurrent.CopyOnWriteArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080015import java.util.concurrent.LinkedBlockingQueue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080016
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080017import net.onrc.onos.datagrid.IDatagridService;
18import net.onrc.onos.datagrid.IEventChannel;
19import net.onrc.onos.datagrid.IEventChannelListener;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080020import net.onrc.onos.datastore.topology.RCLink;
Jonathan Hart062a2e82014-02-03 09:41:57 -080021import net.onrc.onos.datastore.topology.RCPort;
22import net.onrc.onos.datastore.topology.RCSwitch;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080023import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080024import net.onrc.onos.ofcontroller.util.EventEntry;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080025import net.onrc.onos.ofcontroller.util.Dpid;
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080026import net.onrc.onos.registry.controller.IControllerRegistryService;
Jonathan Hart062a2e82014-02-03 09:41:57 -080027
28import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
30
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080031/**
32 * The "NB" read-only Network Map.
33 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080034 * - Maintain Invariant/Relationships between Topology Objects.
35 *
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080036 * TODO To be synchronized based on TopologyEvent Notification.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080037 *
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080038 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
Yuta HIGUCHI1c700102014-02-12 16:30:52 -080039 * Object must exist before adding sub component(Add Switch -> Port).
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080040 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080041 * TODO TBD: This class may delay the requested change to handle event
42 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080043 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080044 */
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -080045public class TopologyManager implements NetworkGraphDiscoveryInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080046
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080047 private static final Logger log = LoggerFactory
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -080048 .getLogger(TopologyManager.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080049
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080050 private IEventChannel<byte[], TopologyEvent> eventChannel;
51 private static final String EVENT_CHANNEL_NAME = "onos.topology";
52 private EventHandler eventHandler = new EventHandler();
53
Jonathan Hart22eb9882014-02-11 15:52:59 -080054 private final NetworkGraphDatastore datastore;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080055 private final NetworkGraphImpl networkGraph = new NetworkGraphImpl();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080056 private final IControllerRegistryService registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080057 private CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners;
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080058
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080059 // Local state for computing the final set of events
60 private Map<ByteBuffer, SwitchEvent> addedSwitchEvents =
61 new HashMap<ByteBuffer, SwitchEvent>();
62 private Map<ByteBuffer, SwitchEvent> removedSwitchEvents =
63 new HashMap<ByteBuffer, SwitchEvent>();
64 private Map<ByteBuffer, PortEvent> addedPortEvents =
65 new HashMap<ByteBuffer, PortEvent>();
66 private Map<ByteBuffer, PortEvent> removedPortEvents =
67 new HashMap<ByteBuffer, PortEvent>();
68 private Map<ByteBuffer, LinkEvent> addedLinkEvents =
69 new HashMap<ByteBuffer, LinkEvent>();
70 private Map<ByteBuffer, LinkEvent> removedLinkEvents =
71 new HashMap<ByteBuffer, LinkEvent>();
72 private Map<ByteBuffer, DeviceEvent> addedDeviceEvents =
73 new HashMap<ByteBuffer, DeviceEvent>();
74 private Map<ByteBuffer, DeviceEvent> removedDeviceEvents =
75 new HashMap<ByteBuffer, DeviceEvent>();
76
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080077 /**
78 * Constructor.
79 *
80 * @param registryService the Registry Service to use.
81 * @param networkGraphListeners the collection of Network Graph Listeners
82 * to use.
83 */
84 public TopologyManager(IControllerRegistryService registryService,
85 CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners) {
Jonathan Hartdaea86f2014-02-19 15:28:42 -080086 datastore = new NetworkGraphDatastore();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080087 this.registryService = registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080088 this.networkGraphListeners = networkGraphListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080089 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080090
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080091 /**
92 * Get the Network Graph.
93 *
94 * @return the Network Graph.
95 */
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080096 NetworkGraph getNetworkGraph() {
97 return networkGraph;
98 }
99
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800100 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800101 * Event handler class.
102 */
103 private class EventHandler extends Thread implements
104 IEventChannelListener<byte[], TopologyEvent> {
105 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
106 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
107
108 /**
109 * Startup processing.
110 */
111 private void startup() {
112 //
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800113 // TODO: Read all state from the database:
114 //
115 // Collection<EventEntry<TopologyEvent>> collection =
116 // readWholeTopologyFromDB();
117 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800118 // For now, as a shortcut we read it from the datagrid
119 //
120 Collection<TopologyEvent> topologyEvents =
121 eventChannel.getAllEntries();
122 Collection<EventEntry<TopologyEvent>> collection =
123 new LinkedList<EventEntry<TopologyEvent>>();
124
125 for (TopologyEvent topologyEvent : topologyEvents) {
126 EventEntry<TopologyEvent> eventEntry =
127 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
128 topologyEvent);
129 collection.add(eventEntry);
130 }
131 processEvents(collection);
132 }
133
134 /**
135 * Run the thread.
136 */
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800137 @Override
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800138 public void run() {
139 Collection<EventEntry<TopologyEvent>> collection =
140 new LinkedList<EventEntry<TopologyEvent>>();
141
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -0800142 this.setName("TopologyManager.EventHandler " + this.getId());
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800143 startup();
144
145 //
146 // The main loop
147 //
148 try {
149 while (true) {
150 EventEntry<TopologyEvent> eventEntry = topologyEvents.take();
151 collection.add(eventEntry);
152 topologyEvents.drainTo(collection);
153
154 processEvents(collection);
155 collection.clear();
156 }
157 } catch (Exception exception) {
158 log.debug("Exception processing Topology Events: ", exception);
159 }
160 }
161
162 /**
163 * Process all topology events.
164 *
165 * @param events the events to process.
166 */
167 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
168 for (EventEntry<TopologyEvent> event : events) {
169 TopologyEvent topologyEvent = event.eventData();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800170 SwitchEvent switchEvent = topologyEvent.switchEvent;
171 PortEvent portEvent = topologyEvent.portEvent;
172 LinkEvent linkEvent = topologyEvent.linkEvent;
173 DeviceEvent deviceEvent = topologyEvent.deviceEvent;
174
175 //
176 // Extract the events by cancelling matching events
177 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800178 switch (event.eventType()) {
179 case ENTRY_ADD:
180 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800181 if (switchEvent != null) {
182 ByteBuffer id = ByteBuffer.wrap(switchEvent.getID());
183 addedSwitchEvents.put(id, switchEvent);
184 removedSwitchEvents.remove(id);
185 }
186 if (portEvent != null) {
187 ByteBuffer id = ByteBuffer.wrap(portEvent.getID());
188 addedPortEvents.put(id, portEvent);
189 removedPortEvents.remove(id);
190 }
191 if (linkEvent != null) {
192 ByteBuffer id = ByteBuffer.wrap(linkEvent.getID());
193 addedLinkEvents.put(id, linkEvent);
194 removedLinkEvents.remove(id);
195 }
196 if (deviceEvent != null) {
197 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
198 addedDeviceEvents.put(id, deviceEvent);
199 removedDeviceEvents.remove(id);
200 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800201 break;
202 case ENTRY_REMOVE:
203 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800204 if (switchEvent != null) {
205 ByteBuffer id = ByteBuffer.wrap(switchEvent.getID());
206 addedSwitchEvents.remove(id);
207 removedSwitchEvents.put(id, switchEvent);
208 }
209 if (portEvent != null) {
210 ByteBuffer id = ByteBuffer.wrap(portEvent.getID());
211 addedPortEvents.remove(id);
212 removedPortEvents.put(id, portEvent);
213 }
214 if (linkEvent != null) {
215 ByteBuffer id = ByteBuffer.wrap(linkEvent.getID());
216 addedLinkEvents.remove(id);
217 removedLinkEvents.put(id, linkEvent);
218 }
219 if (deviceEvent != null) {
220 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
221 addedDeviceEvents.remove(id);
222 removedDeviceEvents.put(id, deviceEvent);
223 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800224 break;
225 }
226 }
227 }
228
229 /**
230 * Receive a notification that an entry is added.
231 *
232 * @param value the value for the entry.
233 */
234 @Override
235 public void entryAdded(TopologyEvent value) {
236 EventEntry<TopologyEvent> eventEntry =
237 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
238 value);
239 topologyEvents.add(eventEntry);
240 }
241
242 /**
243 * Receive a notification that an entry is removed.
244 *
245 * @param value the value for the entry.
246 */
247 @Override
248 public void entryRemoved(TopologyEvent value) {
249 EventEntry<TopologyEvent> eventEntry =
250 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
251 value);
252 topologyEvents.add(eventEntry);
253 }
254
255 /**
256 * Receive a notification that an entry is updated.
257 *
258 * @param value the value for the entry.
259 */
260 @Override
261 public void entryUpdated(TopologyEvent value) {
262 // NOTE: The ADD and UPDATE events are processed in same way
263 entryAdded(value);
264 }
265 }
266
267 /**
268 * Startup processing.
269 *
270 * @param datagridService the datagrid service to use.
271 */
272 void startup(IDatagridService datagridService) {
273 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
274 eventHandler,
275 byte[].class,
276 TopologyEvent.class);
277 eventHandler.start();
278 }
279
280 /**
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800281 * Exception to be thrown when Modification to the Network Graph cannot be
282 * continued due to broken invariant.
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800283 *
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800284 * XXX Should this be checked exception or RuntimeException?
Yuta HIGUCHIcb951982014-02-11 13:31:44 -0800285 */
286 public static class BrokenInvariantException extends RuntimeException {
287 private static final long serialVersionUID = 1L;
288
289 public BrokenInvariantException() {
290 super();
291 }
292
293 public BrokenInvariantException(String message) {
294 super(message);
295 }
296 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800297
298 /* ******************************
299 * NetworkGraphDiscoveryInterface methods
300 * ******************************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800301
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800302 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800303 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
304 Collection<PortEvent> portEvents) {
305 if (datastore.addSwitch(switchEvent, portEvents)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800306 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800307 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800308 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800309
310 for (PortEvent portEvent : portEvents) {
311 topologyEvent = new TopologyEvent(portEvent);
312 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
313 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800314 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800315 }
316
317 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800318 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800319 // TODO: Use a copy of the port events previously added for that switch
320 Collection<PortEvent> portEvents = new LinkedList<PortEvent>();
321
322 if (datastore.deactivateSwitch(switchEvent, portEvents)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800323 // Send out notification
324 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800325
326 for (PortEvent portEvent : portEvents) {
327 eventChannel.removeEntry(portEvent.getID());
328 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800329 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800330 }
331
332 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800333 public void putPortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800334 if (datastore.addPort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800335 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800336 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800337 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800338 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800339 }
340
341 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800342 public void removePortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800343 if (datastore.deactivatePort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800344 // Send out notification
345 eventChannel.removeEntry(portEvent.getID());
346 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800347 }
348
349 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800350 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800351 if (datastore.addLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800352 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800353 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800354 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
355 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800356 }
357
358 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800359 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800360 if (datastore.removeLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800361 // Send out notification
362 eventChannel.removeEntry(linkEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800363 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800364 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800365
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800366 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800367 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800368 if (datastore.addDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800369 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800370 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800371 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800372 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800373 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800374
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800375 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800376 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800377 if (datastore.removeDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800378 // Send out notification
379 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800380 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800381 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800382
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800383 /* *****************
384 * Internal methods to maintain invariants of the network graph
385 * *****************/
Jonathan Hart22eb9882014-02-11 15:52:59 -0800386
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800387 /**
388 *
389 * @param swEvent
390 * @return true if ready to accept event.
391 */
392 private boolean prepareForAddSwitchEvent(SwitchEvent swEvent) {
393 // No show stopping precondition
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800394 return true;
395 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800396
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800397 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvent) {
398 // No show stopping precondition
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800399 return true;
400 }
Yuta HIGUCHI71e7a052014-02-17 22:14:15 -0800401
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800402 private boolean prepareForAddPortEvent(PortEvent portEvent) {
403 // Parent Switch must exist
404 if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
405 log.warn("Dropping add port event because switch doesn't exist: {}",
406 portEvent);
407 return false;
408 }
409 // Prep: None
410 return true;
411 }
412
413 private boolean prepareForRemovePortEvent(PortEvent portEvent) {
414 Port port = networkGraph.getPort(portEvent.getDpid(),
415 portEvent.getNumber());
416 if (port == null) {
417 log.debug("Port already removed? {}", portEvent);
418 // let it pass
419 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800420 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800421
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800422 // Prep: Remove Link and Device Attachment
423 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
424 for (Device device : port.getDevices()) {
425 log.debug("Removing Device {} on Port {}", device, portEvent);
426 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
427 devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
428 port.getNumber()));
429 deviceEvents.add(devEvent);
430 }
431 for (DeviceEvent devEvent : deviceEvents) {
432 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800433 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800434 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800435
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800436 Set<Link> links = new HashSet<>();
437 links.add(port.getOutgoingLink());
438 links.add(port.getIncomingLink());
439 for (Link link : links) {
440 if (link == null) {
441 continue;
442 }
443 log.debug("Removing Link {} on Port {}", link, portEvent);
444 LinkEvent linkEvent =
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800445 new LinkEvent(link.getSrcSwitch().getDpid(),
446 link.getSrcPort().getNumber(),
447 link.getDstSwitch().getDpid(),
448 link.getDstPort().getNumber());
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800449 // calling Discovery API to wipe from DB, etc.
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800450
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800451 // Call internal remove Link, which will check
452 // ownership of DST dpid and modify DB only if it is the owner
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800453 removeLinkDiscoveryEvent(linkEvent, true);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800454 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800455 return true;
456 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800457
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800458 private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
459 // Src/Dst Port must exist
460 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
461 linkEvent.getSrc().number);
462 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
463 linkEvent.getDst().number);
464 if (srcPort == null || dstPort == null) {
Jonathan Hart0a4846e2014-02-18 11:03:40 -0800465 log.warn("Dropping add link event because port doesn't exist: {}",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800466 linkEvent);
467 return false;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800468 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800469
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800470 // Prep: remove Device attachment on both Ports
471 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
472 for (Device device : srcPort.getDevices()) {
473 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
474 devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
475 deviceEvents.add(devEvent);
476 }
477 for (Device device : dstPort.getDevices()) {
478 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
479 devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
480 dstPort.getNumber()));
481 deviceEvents.add(devEvent);
482 }
483 for (DeviceEvent devEvent : deviceEvents) {
484 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800485 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800486 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800487
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800488 return true;
489 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800490
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800491 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
492 // Src/Dst Port must exist
493 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
494 linkEvent.getSrc().number);
495 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
496 linkEvent.getDst().number);
497 if (srcPort == null || dstPort == null) {
498 log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
499 return false;
500 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800501
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800502 Link link = srcPort.getOutgoingLink();
503
504 // Link is already gone, or different Link exist in memory
505 // XXX Check if we should reject or just accept these cases.
506 // it should be harmless to remove the Link on event from DB anyways
507 if (link == null ||
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800508 !link.getDstPort().getNumber().equals(linkEvent.getDst().number)
509 || !link.getDstSwitch().getDpid().equals(linkEvent.getDst().dpid)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800510 log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
511 return false;
512 }
513 // Prep: None
514 return true;
515 }
516
517 /**
518 *
519 * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
520 * @return false if this event should be dropped.
521 */
522 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
523 boolean preconditionBroken = false;
524 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
525 for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
526 // Attached Ports must exist
527 Port port = networkGraph.getPort(swp.dpid, swp.number);
528 if (port == null) {
529 preconditionBroken = true;
530 failedSwitchPort.add(swp);
531 continue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800532 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800533 // Attached Ports must not have Link
534 if (port.getOutgoingLink() != null ||
535 port.getIncomingLink() != null) {
536 preconditionBroken = true;
537 failedSwitchPort.add(swp);
538 continue;
539 }
540 }
541
542 // Rewriting event to exclude failed attachmentPoint
543 // XXX Assumption behind this is that inapplicable device event should
544 // be dropped, not deferred. If we decide to defer Device event,
545 // rewriting can become a problem
546 List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
547 attachmentPoints.removeAll(failedSwitchPort);
548 deviceEvent.setAttachmentPoints(attachmentPoints);
549
550 if (deviceEvent.getAttachmentPoints().isEmpty() &&
551 deviceEvent.getIpAddresses().isEmpty()) {
552 // return false to represent: Nothing left to do for this event.
553 // Caller should drop event
554 return false;
555 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800556
557 // Should we return false to tell caller that the event was trimmed?
558 // if ( preconditionBroken ) {
559 // return false;
560 // }
561
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800562 return true;
563 }
564
565 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
566 // No show stopping precondition?
567 // Prep: none
568 return true;
569 }
570
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800571 /* ************************************************
572 * Internal In-memory object mutation methods.
573 * ************************************************/
574
575 void putSwitch(SwitchEvent swEvent) {
576 if (swEvent == null) {
577 throw new IllegalArgumentException("Switch cannot be null");
Jonathan Hart22eb9882014-02-11 15:52:59 -0800578 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800579
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800580 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
581
582 if (sw == null) {
583 sw = new SwitchImpl(networkGraph, swEvent.getDpid());
584 networkGraph.putSwitch(sw);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800585 }
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800586
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800587 // Update when more attributes are added to Event object
588 // no attribute to update for now
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800589 }
590
591 void removeSwitch(SwitchEvent swEvent) {
592 if (swEvent == null) {
593 throw new IllegalArgumentException("Switch cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800594 }
595
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800596 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
597 if (sw == null) {
598 log.warn("Switch {} already removed, ignoring", swEvent);
599 return;
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800600 }
601
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800602 // remove all ports if there still exist
603 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
604 for (Port port : sw.getPorts()) {
605 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now",
606 port, swEvent);
607 PortEvent portEvent = new PortEvent(port.getDpid(),
608 port.getNumber());
609 portsToRemove.add(portEvent);
610 }
611 for (PortEvent portEvent : portsToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800612 // XXX calling removePortDiscoveryEvent() may trigger duplicate
613 // event, once at prepare phase, second time here
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800614 // If event can be squashed, ignored etc. at receiver side it
615 // shouldn't be a problem, but if not need to re-visit this issue.
616
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800617 // Note: removePortDiscoveryEvent() implies removal of attached
618 // Device, etc. if we decide not to call
619 // removePortDiscoveryEvent(), Device needs to be handled properly.
620 removePortDiscoveryEvent(portEvent);
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800621 }
622
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800623 networkGraph.removeSwitch(swEvent.getDpid());
624 }
625
626 void putPort(PortEvent portEvent) {
627 if (portEvent == null) {
628 throw new IllegalArgumentException("Port cannot be null");
Yuta HIGUCHI928fa682014-02-11 19:07:57 -0800629 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800630 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
631 if (sw == null) {
632 throw new BrokenInvariantException(String.format(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800633 "Switch with dpid %s did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800634 new Dpid(portEvent.getDpid())));
635 }
636 Port p = sw.getPort(portEvent.getNumber());
637 PortImpl port = null;
638 if (p != null) {
639 port = getPortImpl(p);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800640 }
641
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800642 if (port == null) {
643 port = new PortImpl(networkGraph, sw, portEvent.getNumber());
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800644 }
645
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800646 // TODO update attributes
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800647
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800648 SwitchImpl s = getSwitchImpl(sw);
649 s.addPort(port);
650 }
651
652 void removePort(PortEvent portEvent) {
653 if (portEvent == null) {
654 throw new IllegalArgumentException("Port cannot be null");
655 }
656
657 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
658 if (sw == null) {
659 log.warn("Parent Switch for Port {} already removed, ignoring",
660 portEvent);
661 return;
662 }
663
664 Port p = sw.getPort(portEvent.getNumber());
665 if (p == null) {
666 log.warn("Port {} already removed, ignoring", portEvent);
667 return;
668 }
669
670 // Remove Link and Device Attachment
671 for (Device device : p.getDevices()) {
672 log.debug("Removing Device {} on Port {}", device, portEvent);
673 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
674 devEvent.addAttachmentPoint(new SwitchPort(p.getSwitch().getDpid(),
675 p.getNumber()));
676
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800677 // XXX calling removeDeviceDiscoveryEvent() may trigger duplicate
678 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800679 // If event can be squashed, ignored etc. at receiver side it
680 // shouldn't be a problem, but if not need to re-visit
681
682 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800683 removeDeviceDiscoveryEvent(devEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800684 }
685 Set<Link> links = new HashSet<>();
686 links.add(p.getOutgoingLink());
687 links.add(p.getIncomingLink());
688 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
689 for (Link link : links) {
690 if (link == null) {
691 continue;
692 }
693 log.debug("Removing Link {} on Port {}", link, portEvent);
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800694 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
695 link.getSrcPort().getNumber(),
696 link.getDstSwitch().getDpid(),
697 link.getDstPort().getNumber());
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800698 linksToRemove.add(linkEvent);
699 }
700 for (LinkEvent linkEvent : linksToRemove) {
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800701 // XXX calling removeLinkDiscoveryEvent() may trigger duplicate
702 // event, once at prepare phase, second time here.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800703 // If event can be squashed, ignored etc. at receiver side it
704 // shouldn't be a problem, but if not need to re-visit
705
706 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800707 removeLinkDiscoveryEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800708 }
709
710 // remove Port from Switch
711 SwitchImpl s = getSwitchImpl(sw);
712 s.removePort(p);
713 }
714
715 void putLink(LinkEvent linkEvent) {
716 if (linkEvent == null) {
717 throw new IllegalArgumentException("Link cannot be null");
718 }
719
720 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
721 linkEvent.getSrc().number);
722 if (srcPort == null) {
723 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800724 String.format(
725 "Src Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800726 linkEvent.getSrc() ));
727 }
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800728
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800729 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
730 linkEvent.getDst().number);
731 if (dstPort == null) {
732 throw new BrokenInvariantException(
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800733 String.format(
734 "Dst Port %s of a Link did not exist.",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800735 linkEvent.getDst()));
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800736 }
737
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800738 // getting Link instance from destination port incoming Link
739 Link l = dstPort.getIncomingLink();
740 LinkImpl link = null;
741 assert(l == srcPort.getOutgoingLink());
742 if (l != null) {
743 link = getLinkImpl(l);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800744 }
745
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800746 if (link == null) {
747 link = new LinkImpl(networkGraph, srcPort, dstPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800748 }
749
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800750 PortImpl dstPortMem = getPortImpl(dstPort);
751 PortImpl srcPortMem = getPortImpl(srcPort);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800752
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800753 // Add Link first to avoid further Device addition
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800754
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800755 // add Link to Port
756 dstPortMem.setIncomingLink(link);
757 srcPortMem.setOutgoingLink(link);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800758
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800759 // remove Device Pointing to Port if any
760 for (Device d : dstPortMem.getDevices() ) {
761 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
762 d, dstPort, linkEvent);
763 DeviceImpl dev = getDeviceImpl(d);
764 dev.removeAttachmentPoint(dstPort);
765 // This implies that change is made to Device Object.
766 // sending Device attachment point removed event
767 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
768 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
769 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800770 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800771 }
772 dstPortMem.removeAllDevice();
773 for (Device d : srcPortMem.getDevices() ) {
774 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
775 d, srcPort, linkEvent);
776 DeviceImpl dev = getDeviceImpl(d);
777 dev.removeAttachmentPoint(srcPort);
778 // This implies that change is made to Device Object.
779 // sending Device attachment point removed event
780 DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
781 rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
782 dstPort.getNumber()));
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800783 removeDeviceDiscoveryEvent(rmEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800784 }
785 srcPortMem.removeAllDevice();
786 }
787
788 void removeLink(LinkEvent linkEvent) {
789 if (linkEvent == null) {
790 throw new IllegalArgumentException("Link cannot be null");
Yuta HIGUCHI76df2472014-02-12 22:36:51 -0800791 }
792
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800793 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
794 linkEvent.getSrc().number);
795 if (srcPort == null) {
796 log.warn("Src Port for Link {} already removed, ignoring",
797 linkEvent);
798 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800799 }
800
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800801 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
802 linkEvent.getDst().number);
803 if (dstPort == null) {
804 log.warn("Dst Port for Link {} already removed, ignoring",
805 linkEvent);
806 return;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800807 }
808
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800809 Link l = dstPort.getIncomingLink();
810 if ( l == null) {
811 log.warn("Link {} already removed on destination Port", linkEvent);
812 }
813 l = srcPort.getOutgoingLink();
814 if (l == null) {
815 log.warn("Link {} already removed on src Port", linkEvent);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800816 }
817
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800818 getPortImpl(dstPort).setIncomingLink(null);
819 getPortImpl(srcPort).setOutgoingLink(null);
820 }
821
822 // XXX Need to rework Device related
823 void putDevice(DeviceEvent deviceEvent) {
824 if (deviceEvent == null) {
825 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800826 }
827
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800828 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
829 if (device == null) {
830 device = new DeviceImpl(networkGraph, deviceEvent.getMac());
831 }
832 DeviceImpl memDevice = getDeviceImpl(device);
833
834 // for each IP address
835 for (InetAddress ipAddr : deviceEvent.getIpAddresses()) {
836 memDevice.addIpAddress(ipAddr);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800837 }
838
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800839 networkGraph.putDevice(device);
840
841 // for each attachment point
842 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
843 // Attached Ports must exist
844 Port port = networkGraph.getPort(swp.dpid, swp.number);
845 if (port == null) {
846 log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
847 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800848 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800849 // Attached Ports must not have Link
850 if (port.getOutgoingLink() != null ||
851 port.getIncomingLink() != null) {
852 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
853 port.getOutgoingLink(),
854 port.getIncomingLink());
855 continue;
856 }
857
858 // finally add Device <-> Port on In-memory structure
859 PortImpl memPort = getPortImpl(port);
860 memPort.addDevice(device);
861 memDevice.addAttachmentPoint(port);
862 }
863 }
864
865 void removeDevice(DeviceEvent deviceEvent) {
866 if (deviceEvent == null) {
867 throw new IllegalArgumentException("Device cannot be null");
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800868 }
869
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800870 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
871 if (device == null) {
872 log.warn("Device {} already removed, ignoring", deviceEvent);
873 return;
874 }
875 DeviceImpl memDevice = getDeviceImpl(device);
876
877 // for each attachment point
878 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
879 // Attached Ports must exist
880 Port port = networkGraph.getPort(swp.dpid, swp.number);
881 if (port == null) {
882 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
883 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800884 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800885
886 // finally remove Device <-> Port on In-memory structure
887 PortImpl memPort = getPortImpl(port);
888 memPort.removeDevice(device);
889 memDevice.removeAttachmentPoint(port);
890 }
891 networkGraph.removeDevice(device);
892 }
893
894 private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
895 for (INetworkGraphListener listener : this.networkGraphListeners) {
896 // TODO Should copy before handing them over to listener
897 listener.putSwitchEvent(switchEvent);
898 }
899 }
900
901 private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
902 for (INetworkGraphListener listener : this.networkGraphListeners) {
903 // TODO Should copy before handing them over to listener
904 listener.removeSwitchEvent(switchEvent);
905 }
906 }
907
908 private void dispatchPutPortEvent(PortEvent portEvent) {
909 for (INetworkGraphListener listener : this.networkGraphListeners) {
910 // TODO Should copy before handing them over to listener
911 listener.putPortEvent(portEvent);
912 }
913 }
914
915 private void dispatchRemovePortEvent(PortEvent portEvent) {
916 for (INetworkGraphListener listener : this.networkGraphListeners) {
917 // TODO Should copy before handing them over to listener
918 listener.removePortEvent(portEvent);
919 }
920 }
921
922 private void dispatchPutLinkEvent(LinkEvent linkEvent) {
923 for (INetworkGraphListener listener : this.networkGraphListeners) {
924 // TODO Should copy before handing them over to listener
925 listener.putLinkEvent(linkEvent);
926 }
927 }
928
929 private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
930 for (INetworkGraphListener listener : this.networkGraphListeners) {
931 // TODO Should copy before handing them over to listener
932 listener.removeLinkEvent(linkEvent);
933 }
934 }
935
936 private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
937 for (INetworkGraphListener listener : this.networkGraphListeners) {
938 // TODO Should copy before handing them over to listener
939 listener.putDeviceEvent(deviceEvent);;
940 }
941 }
942
943 private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
944 for (INetworkGraphListener listener : this.networkGraphListeners) {
945 // TODO Should copy before handing them over to listener
946 listener.removeDeviceEvent(deviceEvent);
947 }
948 }
949
950 private SwitchImpl getSwitchImpl(Switch sw) {
951 if (sw instanceof SwitchImpl) {
952 return (SwitchImpl) sw;
953 }
954 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
955 }
956
957 private PortImpl getPortImpl(Port p) {
958 if (p instanceof PortImpl) {
959 return (PortImpl) p;
960 }
961 throw new ClassCastException("PortImpl expected, but found: " + p);
962 }
963
964 private LinkImpl getLinkImpl(Link l) {
965 if (l instanceof LinkImpl) {
966 return (LinkImpl) l;
967 }
968 throw new ClassCastException("LinkImpl expected, but found: " + l);
969 }
970
971 private DeviceImpl getDeviceImpl(Device d) {
972 if (d instanceof DeviceImpl) {
973 return (DeviceImpl) d;
974 }
975 throw new ClassCastException("DeviceImpl expected, but found: " + d);
976 }
977
978 @Deprecated
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800979 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
980 Collection<EventEntry<TopologyEvent>> collection =
981 new LinkedList<EventEntry<TopologyEvent>>();
982
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800983 // XXX May need to clear whole topology first, depending on
984 // how we initially subscribe to replication events
985
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800986 // Add all active switches
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800987 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
988 if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
989 continue;
990 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800991
992 SwitchEvent switchEvent = new SwitchEvent(sw.getDpid());
993 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
994 EventEntry<TopologyEvent> eventEntry =
995 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
996 topologyEvent);
997 collection.add(eventEntry);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800998 }
999
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001000 // Add all active ports
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001001 for (RCPort p : RCPort.getAllPorts()) {
1002 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1003 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001004 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001005
1006 PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
1007 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
1008 EventEntry<TopologyEvent> eventEntry =
1009 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1010 topologyEvent);
1011 collection.add(eventEntry);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001012 }
1013
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001014 // TODO Is Device going to be in DB? If so, read from DB.
1015 // for (RCDevice d : RCDevice.getAllDevices()) {
1016 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
1017 // for (byte[] portId : d.getAllPortIds() ) {
1018 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
1019 // }
1020 // }
1021
1022 for (RCLink l : RCLink.getAllLinks()) {
1023 // check if src/dst switch/port exist before triggering event
1024 Port srcPort = networkGraph.getPort(l.getSrc().dpid,
1025 l.getSrc().number);
1026 Port dstPort = networkGraph.getPort(l.getDst().dpid,
1027 l.getDst().number);
1028 if (srcPort == null || dstPort == null) {
1029 continue;
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001030 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001031
1032 LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
1033 l.getSrc().number,
1034 l.getDst().dpid,
1035 l.getDst().number);
1036 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
1037 EventEntry<TopologyEvent> eventEntry =
1038 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1039 topologyEvent);
1040 collection.add(eventEntry);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001041 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001042
1043 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001044 }
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -08001045
1046 @Deprecated
1047 private void removeLinkDiscoveryEvent(LinkEvent linkEvent,
1048 boolean dstCheckBeforeDBmodify) {
1049 if (prepareForRemoveLinkEvent(linkEvent)) {
1050 if (dstCheckBeforeDBmodify) {
1051 // write to DB only if it is owner of the dst dpid
1052 // XXX this will cause link remove events to be dropped
1053 // if the dst switch just disconnected
1054 if (registryService.hasControl(linkEvent.getDst().dpid)) {
1055 datastore.removeLink(linkEvent);
1056 }
1057 } else {
1058 datastore.removeLink(linkEvent);
1059 }
1060 removeLink(linkEvent);
1061 // Send out notification
1062 eventChannel.removeEntry(linkEvent.getID());
1063 }
1064 // TODO handle invariant violation
1065 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001066}