blob: 7377ce6f4efaf8d82468fbebfa9b32203c7f70d9 [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 Radoslavov706add22014-02-20 12:15:59 -080059 //
60 // Local state for keeping track of reordered events.
61 // NOTE: Switch Events are not affected by the event reordering.
62 //
63 private Map<ByteBuffer, PortEvent> reorderedAddedPortEvents =
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080064 new HashMap<ByteBuffer, PortEvent>();
Pavlin Radoslavov706add22014-02-20 12:15:59 -080065 private Map<ByteBuffer, LinkEvent> reorderedAddedLinkEvents =
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080066 new HashMap<ByteBuffer, LinkEvent>();
Pavlin Radoslavov706add22014-02-20 12:15:59 -080067 private Map<ByteBuffer, DeviceEvent> reorderedAddedDeviceEvents =
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080068 new HashMap<ByteBuffer, DeviceEvent>();
69
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080070 /**
71 * Constructor.
72 *
73 * @param registryService the Registry Service to use.
74 * @param networkGraphListeners the collection of Network Graph Listeners
75 * to use.
76 */
77 public TopologyManager(IControllerRegistryService registryService,
78 CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners) {
Jonathan Hartdaea86f2014-02-19 15:28:42 -080079 datastore = new NetworkGraphDatastore();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080080 this.registryService = registryService;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080081 this.networkGraphListeners = networkGraphListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080082 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080083
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -080084 /**
85 * Get the Network Graph.
86 *
87 * @return the Network Graph.
88 */
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -080089 NetworkGraph getNetworkGraph() {
90 return networkGraph;
91 }
92
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080093 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080094 * Event handler class.
95 */
96 private class EventHandler extends Thread implements
97 IEventChannelListener<byte[], TopologyEvent> {
98 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
99 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
100
101 /**
102 * Startup processing.
103 */
104 private void startup() {
105 //
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800106 // TODO: Read all state from the database:
107 //
108 // Collection<EventEntry<TopologyEvent>> collection =
109 // readWholeTopologyFromDB();
110 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800111 // For now, as a shortcut we read it from the datagrid
112 //
113 Collection<TopologyEvent> topologyEvents =
114 eventChannel.getAllEntries();
115 Collection<EventEntry<TopologyEvent>> collection =
116 new LinkedList<EventEntry<TopologyEvent>>();
117
118 for (TopologyEvent topologyEvent : topologyEvents) {
119 EventEntry<TopologyEvent> eventEntry =
120 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
121 topologyEvent);
122 collection.add(eventEntry);
123 }
124 processEvents(collection);
125 }
126
127 /**
128 * Run the thread.
129 */
Yuta HIGUCHI240bf072014-02-17 10:55:21 -0800130 @Override
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800131 public void run() {
132 Collection<EventEntry<TopologyEvent>> collection =
133 new LinkedList<EventEntry<TopologyEvent>>();
134
Pavlin Radoslavovdb7dbb22014-02-18 14:45:10 -0800135 this.setName("TopologyManager.EventHandler " + this.getId());
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800136 startup();
137
138 //
139 // The main loop
140 //
141 try {
142 while (true) {
143 EventEntry<TopologyEvent> eventEntry = topologyEvents.take();
144 collection.add(eventEntry);
145 topologyEvents.drainTo(collection);
146
147 processEvents(collection);
148 collection.clear();
149 }
150 } catch (Exception exception) {
151 log.debug("Exception processing Topology Events: ", exception);
152 }
153 }
154
155 /**
156 * Process all topology events.
157 *
158 * @param events the events to process.
159 */
160 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800161 // Local state for computing the final set of events
162 Map<ByteBuffer, SwitchEvent> addedSwitchEvents =
163 new HashMap<ByteBuffer, SwitchEvent>();
164 Map<ByteBuffer, SwitchEvent> removedSwitchEvents =
165 new HashMap<ByteBuffer, SwitchEvent>();
166 Map<ByteBuffer, PortEvent> addedPortEvents =
167 new HashMap<ByteBuffer, PortEvent>();
168 Map<ByteBuffer, PortEvent> removedPortEvents =
169 new HashMap<ByteBuffer, PortEvent>();
170 Map<ByteBuffer, LinkEvent> addedLinkEvents =
171 new HashMap<ByteBuffer, LinkEvent>();
172 Map<ByteBuffer, LinkEvent> removedLinkEvents =
173 new HashMap<ByteBuffer, LinkEvent>();
174 Map<ByteBuffer, DeviceEvent> addedDeviceEvents =
175 new HashMap<ByteBuffer, DeviceEvent>();
176 Map<ByteBuffer, DeviceEvent> removedDeviceEvents =
177 new HashMap<ByteBuffer, DeviceEvent>();
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800178
179 //
180 // Classify and suppress matching events
181 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800182 for (EventEntry<TopologyEvent> event : events) {
183 TopologyEvent topologyEvent = event.eventData();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800184 SwitchEvent switchEvent = topologyEvent.switchEvent;
185 PortEvent portEvent = topologyEvent.portEvent;
186 LinkEvent linkEvent = topologyEvent.linkEvent;
187 DeviceEvent deviceEvent = topologyEvent.deviceEvent;
188
189 //
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800190 // Extract the events
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800191 //
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800192 switch (event.eventType()) {
193 case ENTRY_ADD:
194 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800195 if (switchEvent != null) {
196 ByteBuffer id = ByteBuffer.wrap(switchEvent.getID());
197 addedSwitchEvents.put(id, switchEvent);
198 removedSwitchEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800199 // Switch Events are not affected by event reordering
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800200 }
201 if (portEvent != null) {
202 ByteBuffer id = ByteBuffer.wrap(portEvent.getID());
203 addedPortEvents.put(id, portEvent);
204 removedPortEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800205 reorderedAddedPortEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800206 }
207 if (linkEvent != null) {
208 ByteBuffer id = ByteBuffer.wrap(linkEvent.getID());
209 addedLinkEvents.put(id, linkEvent);
210 removedLinkEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800211 reorderedAddedLinkEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800212 }
213 if (deviceEvent != null) {
214 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
215 addedDeviceEvents.put(id, deviceEvent);
216 removedDeviceEvents.remove(id);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800217 reorderedAddedDeviceEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800218 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800219 break;
220 case ENTRY_REMOVE:
221 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800222 if (switchEvent != null) {
223 ByteBuffer id = ByteBuffer.wrap(switchEvent.getID());
224 addedSwitchEvents.remove(id);
225 removedSwitchEvents.put(id, switchEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800226 // Switch Events are not affected by event reordering
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800227 }
228 if (portEvent != null) {
229 ByteBuffer id = ByteBuffer.wrap(portEvent.getID());
230 addedPortEvents.remove(id);
231 removedPortEvents.put(id, portEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800232 reorderedAddedPortEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800233 }
234 if (linkEvent != null) {
235 ByteBuffer id = ByteBuffer.wrap(linkEvent.getID());
236 addedLinkEvents.remove(id);
237 removedLinkEvents.put(id, linkEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800238 reorderedAddedLinkEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800239 }
240 if (deviceEvent != null) {
241 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
242 addedDeviceEvents.remove(id);
243 removedDeviceEvents.put(id, deviceEvent);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800244 reorderedAddedDeviceEvents.remove(id);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800245 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800246 break;
247 }
248 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800249
250 //
251 // Apply the classified events.
252 //
253 // Apply the "add" events in the proper order:
254 // switch, port, link, device
255 //
256 for (SwitchEvent switchEvent : addedSwitchEvents.values())
257 addSwitch(switchEvent);
258 for (PortEvent portEvent : addedPortEvents.values())
259 addPort(portEvent);
260 for (LinkEvent linkEvent : addedLinkEvents.values())
261 addLink(linkEvent);
262 for (DeviceEvent deviceEvent : addedDeviceEvents.values())
263 addDevice(deviceEvent);
264 //
265 // Apply the "remove" events in the reverse order:
266 // device, link, port, switch
267 //
268 for (DeviceEvent deviceEvent : removedDeviceEvents.values())
269 removeDevice(deviceEvent);
270 for (LinkEvent linkEvent : removedLinkEvents.values())
271 removeLink(linkEvent);
272 for (PortEvent portEvent : removedPortEvents.values())
273 removePort(portEvent);
274 for (SwitchEvent switchEvent : removedSwitchEvents.values())
275 removeSwitch(switchEvent);
276
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800277 //
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800278 // Try to apply the reordered events.
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800279 //
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800280 // NOTE: For simplicity we try to apply all events of a particular
281 // type if any "parent" type event was processed:
282 // - Apply reordered Port Events if Switches were added
283 // - Apply reordered Link and Device Events if Switches or Ports
284 // were added
285 //
286 if (! (addedSwitchEvents.isEmpty() && addedPortEvents.isEmpty())) {
287 Map<ByteBuffer, PortEvent> portEvents = reorderedAddedPortEvents;
288 Map<ByteBuffer, LinkEvent> linkEvents = reorderedAddedLinkEvents;
289 Map<ByteBuffer, DeviceEvent> deviceEvents = reorderedAddedDeviceEvents;
290 reorderedAddedPortEvents = new HashMap<>();
291 reorderedAddedLinkEvents = new HashMap<>();
292 reorderedAddedDeviceEvents = new HashMap<>();
293 //
294 // Apply reordered Port Events if Switches were added
295 //
296 if (! addedSwitchEvents.isEmpty()) {
297 for (PortEvent portEvent : portEvents.values())
298 addPort(portEvent);
299 }
300 //
301 // Apply reordered Link and Device Events if Switches or Ports
302 // were added.
303 //
304 for (LinkEvent linkEvent : linkEvents.values())
305 addLink(linkEvent);
306 for (DeviceEvent deviceEvent : deviceEvents.values())
307 addDevice(deviceEvent);
308 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800309 }
310
311 /**
312 * Receive a notification that an entry is added.
313 *
314 * @param value the value for the entry.
315 */
316 @Override
317 public void entryAdded(TopologyEvent value) {
318 EventEntry<TopologyEvent> eventEntry =
319 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
320 value);
321 topologyEvents.add(eventEntry);
322 }
323
324 /**
325 * Receive a notification that an entry is removed.
326 *
327 * @param value the value for the entry.
328 */
329 @Override
330 public void entryRemoved(TopologyEvent value) {
331 EventEntry<TopologyEvent> eventEntry =
332 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
333 value);
334 topologyEvents.add(eventEntry);
335 }
336
337 /**
338 * Receive a notification that an entry is updated.
339 *
340 * @param value the value for the entry.
341 */
342 @Override
343 public void entryUpdated(TopologyEvent value) {
344 // NOTE: The ADD and UPDATE events are processed in same way
345 entryAdded(value);
346 }
347 }
348
349 /**
350 * Startup processing.
351 *
352 * @param datagridService the datagrid service to use.
353 */
354 void startup(IDatagridService datagridService) {
355 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
356 eventHandler,
357 byte[].class,
358 TopologyEvent.class);
359 eventHandler.start();
360 }
361
Jonathan Hart22eb9882014-02-11 15:52:59 -0800362 /* ******************************
363 * NetworkGraphDiscoveryInterface methods
364 * ******************************/
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800365
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800366 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800367 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
368 Collection<PortEvent> portEvents) {
369 if (datastore.addSwitch(switchEvent, portEvents)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800370 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800371 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800372 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800373
374 for (PortEvent portEvent : portEvents) {
375 topologyEvent = new TopologyEvent(portEvent);
376 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
377 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800378 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800379 }
380
381 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800382 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800383 // TODO: Use a copy of the port events previously added for that switch
384 Collection<PortEvent> portEvents = new LinkedList<PortEvent>();
385
386 if (datastore.deactivateSwitch(switchEvent, portEvents)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800387 // Send out notification
388 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800389
390 for (PortEvent portEvent : portEvents) {
391 eventChannel.removeEntry(portEvent.getID());
392 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800393 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800394 }
395
396 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800397 public void putPortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800398 if (datastore.addPort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800399 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800400 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800401 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800402 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800403 }
404
405 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800406 public void removePortDiscoveryEvent(PortEvent portEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800407 if (datastore.deactivatePort(portEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800408 // Send out notification
409 eventChannel.removeEntry(portEvent.getID());
410 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800411 }
412
413 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800414 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800415 if (datastore.addLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800416 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800417 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800418 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
419 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800420 }
421
422 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800423 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800424 if (datastore.removeLink(linkEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800425 // Send out notification
426 eventChannel.removeEntry(linkEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800427 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800428 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800429
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800430 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800431 public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800432 if (datastore.addDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800433 // Send out notification
Pavlin Radoslavov87dcc262014-02-19 21:13:23 -0800434 TopologyEvent topologyEvent = new TopologyEvent(deviceEvent);
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800435 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800436 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800437 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800438
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800439 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800440 public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -0800441 if (datastore.removeDevice(deviceEvent)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800442 // Send out notification
443 eventChannel.removeEntry(deviceEvent.getID());
Jonathan Hart22eb9882014-02-11 15:52:59 -0800444 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800445 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800446
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800447 /* ************************************************
448 * Internal methods to maintain the network graph
449 * ************************************************/
450 private void addSwitch(SwitchEvent swEvent) {
451 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
452 if (sw == null) {
453 sw = new SwitchImpl(networkGraph, swEvent.getDpid());
454 networkGraph.putSwitch(sw);
455 } else {
456 // TODO: Update the switch attributes
457 // TODO: Nothing to do for now
458 }
459 }
460
461 private void removeSwitch(SwitchEvent swEvent) {
462 Switch sw = networkGraph.getSwitch(swEvent.getDpid());
463 if (sw == null) {
464 log.warn("Switch {} already removed, ignoring", swEvent);
465 return;
466 }
467
468 //
469 // Remove all Ports on the Switch
470 //
471 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
472 for (Port port : sw.getPorts()) {
473 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
474 port, swEvent);
475 PortEvent portEvent = new PortEvent(port.getDpid(),
476 port.getNumber());
477 portsToRemove.add(portEvent);
478 }
479 for (PortEvent portEvent : portsToRemove)
480 removePort(portEvent);
481
482 networkGraph.removeSwitch(swEvent.getDpid());
483 }
484
485 private void addPort(PortEvent portEvent) {
486 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
487 if (sw == null) {
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800488 // Reordered event: delay the event in local cache
489 ByteBuffer id = ByteBuffer.wrap(portEvent.getID());
490 reorderedAddedPortEvents.put(id, portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800491 return;
492 }
493 SwitchImpl switchImpl = getSwitchImpl(sw);
494
495 Port port = sw.getPort(portEvent.getNumber());
496 if (port == null) {
497 port = new PortImpl(networkGraph, sw, portEvent.getNumber());
498 switchImpl.addPort(port);
499 } else {
500 // TODO: Update the port attributes
501 }
502 }
503
504 private void removePort(PortEvent portEvent) {
505 Switch sw = networkGraph.getSwitch(portEvent.getDpid());
506 if (sw == null) {
507 log.warn("Parent Switch for Port {} already removed, ignoring",
508 portEvent);
509 return;
510 }
511
512 Port port = sw.getPort(portEvent.getNumber());
513 if (port == null) {
514 log.warn("Port {} already removed, ignoring", portEvent);
515 return;
516 }
517
518 //
519 // Remove all Devices attached to the Port
520 //
521 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
522 for (Device device : port.getDevices()) {
523 log.debug("Removing Device {} on Port {}", device, portEvent);
524 DeviceEvent deviceEvent = new DeviceEvent(device.getMacAddress());
525 SwitchPort switchPort = new SwitchPort(port.getSwitch().getDpid(),
526 port.getNumber());
527 deviceEvent.addAttachmentPoint(switchPort);
528 devicesToRemove.add(deviceEvent);
529 }
530 for (DeviceEvent deviceEvent : devicesToRemove)
531 removeDevice(deviceEvent);
532
533 //
534 // Remove all Links connected to the Port
535 //
536 Set<Link> links = new HashSet<>();
537 links.add(port.getOutgoingLink());
538 links.add(port.getIncomingLink());
539 ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
540 for (Link link : links) {
541 if (link == null)
542 continue;
543 log.debug("Removing Link {} on Port {}", link, portEvent);
544 LinkEvent linkEvent = new LinkEvent(link.getSrcSwitch().getDpid(),
545 link.getSrcPort().getNumber(),
546 link.getDstSwitch().getDpid(),
547 link.getDstPort().getNumber());
548 linksToRemove.add(linkEvent);
549 }
550 for (LinkEvent linkEvent : linksToRemove)
551 removeLink(linkEvent);
552
553 // Remove the Port from the Switch
554 SwitchImpl switchImpl = getSwitchImpl(sw);
555 switchImpl.removePort(port);
556 }
557
558 private void addLink(LinkEvent linkEvent) {
559 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
560 linkEvent.getSrc().number);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800561 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
562 linkEvent.getDst().number);
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800563 if ((srcPort == null) || (dstPort == null)) {
564 // Reordered event: delay the event in local cache
565 ByteBuffer id = ByteBuffer.wrap(linkEvent.getID());
566 reorderedAddedLinkEvents.put(id, linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800567 return;
568 }
569
570 // Get the Link instance from the Destination Port Incoming Link
571 Link link = dstPort.getIncomingLink();
572 assert(link == srcPort.getOutgoingLink());
573 if (link == null) {
574 link = new LinkImpl(networkGraph, srcPort, dstPort);
575 PortImpl srcPortImpl = getPortImpl(srcPort);
576 PortImpl dstPortImpl = getPortImpl(dstPort);
577 srcPortImpl.setOutgoingLink(link);
578 dstPortImpl.setIncomingLink(link);
579
580 // Remove all Devices attached to the Ports
581 ArrayList<DeviceEvent> devicesToRemove = new ArrayList<>();
582 ArrayList<Port> ports = new ArrayList<>();
583 ports.add(srcPort);
584 ports.add(dstPort);
585 for (Port port : ports) {
586 for (Device device : port.getDevices()) {
587 log.error("Device {} on Port {} should have been removed prior to adding Link {}",
588 device, port, linkEvent);
589 DeviceEvent deviceEvent =
590 new DeviceEvent(device.getMacAddress());
591 SwitchPort switchPort =
592 new SwitchPort(port.getSwitch().getDpid(),
593 port.getNumber());
594 deviceEvent.addAttachmentPoint(switchPort);
595 devicesToRemove.add(deviceEvent);
596 }
597 }
598 for (DeviceEvent deviceEvent : devicesToRemove)
599 removeDevice(deviceEvent);
600 } else {
601 // TODO: Update the link attributes
602 }
603 }
604
605 private void removeLink(LinkEvent linkEvent) {
606 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
607 linkEvent.getSrc().number);
608 if (srcPort == null) {
609 log.warn("Src Port for Link {} already removed, ignoring",
610 linkEvent);
611 return;
612 }
613
614 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
615 linkEvent.getDst().number);
616 if (dstPort == null) {
617 log.warn("Dst Port for Link {} already removed, ignoring",
618 linkEvent);
619 return;
620 }
621
622 //
623 // Remove the Link instance from the Destination Port Incoming Link
624 // and the Source Port Outgoing Link.
625 //
626 Link link = dstPort.getIncomingLink();
627 if (link == null) {
628 log.warn("Link {} already removed on destination Port", linkEvent);
629 }
630 link = srcPort.getOutgoingLink();
631 if (link == null) {
632 log.warn("Link {} already removed on src Port", linkEvent);
633 }
634 getPortImpl(dstPort).setIncomingLink(null);
635 getPortImpl(srcPort).setOutgoingLink(null);
636 }
637
638 // TODO: Device-related work is incomplete
639 private void addDevice(DeviceEvent deviceEvent) {
640 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
641 if (device == null) {
642 device = new DeviceImpl(networkGraph, deviceEvent.getMac());
643 }
644 DeviceImpl deviceImpl = getDeviceImpl(device);
645
646 // Update the IP addresses
647 for (InetAddress ipAddr : deviceEvent.getIpAddresses())
648 deviceImpl.addIpAddress(ipAddr);
649
650 // Process each attachment point
651 boolean attachmentFound = false;
652 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
653 // Attached Ports must exist
654 Port port = networkGraph.getPort(swp.dpid, swp.number);
655 if (port == null) {
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800656 // Reordered event: delay the event in local cache
657 ByteBuffer id = ByteBuffer.wrap(deviceEvent.getID());
658 reorderedAddedDeviceEvents.put(id, deviceEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800659 continue;
660 }
661 // Attached Ports must not have Link
662 if (port.getOutgoingLink() != null ||
663 port.getIncomingLink() != null) {
664 log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
665 port.getOutgoingLink(),
666 port.getIncomingLink());
667 continue;
668 }
669
670 // Add Device <-> Port attachment
671 PortImpl portImpl = getPortImpl(port);
672 portImpl.addDevice(device);
673 deviceImpl.addAttachmentPoint(port);
674 attachmentFound = true;
675 }
676
677 // Update the device in the Network Graph
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800678 if (attachmentFound)
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800679 networkGraph.putDevice(device);
680 }
681
682 private void removeDevice(DeviceEvent deviceEvent) {
683 Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
684 if (device == null) {
685 log.warn("Device {} already removed, ignoring", deviceEvent);
686 return;
687 }
688 DeviceImpl deviceImpl = getDeviceImpl(device);
689
690 // Process each attachment point
691 for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
692 // Attached Ports must exist
693 Port port = networkGraph.getPort(swp.dpid, swp.number);
694 if (port == null) {
695 log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
696 continue;
697 }
698
699 // Remove Device <-> Port attachment
700 PortImpl portImpl = getPortImpl(port);
701 portImpl.removeDevice(device);
702 deviceImpl.removeAttachmentPoint(port);
703 }
704 networkGraph.removeDevice(device);
705 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800706
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800707 /**
708 *
709 * @param swEvent
710 * @return true if ready to accept event.
711 */
712 private boolean prepareForAddSwitchEvent(SwitchEvent swEvent) {
713 // No show stopping precondition
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800714 return true;
715 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800716
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800717 private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvent) {
718 // No show stopping precondition
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800719 return true;
720 }
Yuta HIGUCHI71e7a052014-02-17 22:14:15 -0800721
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800722 private boolean prepareForAddPortEvent(PortEvent portEvent) {
723 // Parent Switch must exist
724 if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
725 log.warn("Dropping add port event because switch doesn't exist: {}",
726 portEvent);
727 return false;
728 }
729 // Prep: None
730 return true;
731 }
732
733 private boolean prepareForRemovePortEvent(PortEvent portEvent) {
734 Port port = networkGraph.getPort(portEvent.getDpid(),
735 portEvent.getNumber());
736 if (port == null) {
737 log.debug("Port already removed? {}", portEvent);
738 // let it pass
739 return true;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800740 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800741
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800742 // Prep: Remove Link and Device Attachment
743 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
744 for (Device device : port.getDevices()) {
745 log.debug("Removing Device {} on Port {}", device, portEvent);
746 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
747 devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
748 port.getNumber()));
749 deviceEvents.add(devEvent);
750 }
751 for (DeviceEvent devEvent : deviceEvents) {
752 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800753 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800754 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800755
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800756 Set<Link> links = new HashSet<>();
757 links.add(port.getOutgoingLink());
758 links.add(port.getIncomingLink());
759 for (Link link : links) {
760 if (link == null) {
761 continue;
762 }
763 log.debug("Removing Link {} on Port {}", link, portEvent);
764 LinkEvent linkEvent =
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800765 new LinkEvent(link.getSrcSwitch().getDpid(),
766 link.getSrcPort().getNumber(),
767 link.getDstSwitch().getDpid(),
768 link.getDstPort().getNumber());
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800769 // calling Discovery API to wipe from DB, etc.
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800770
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800771 // Call internal remove Link, which will check
772 // ownership of DST dpid and modify DB only if it is the owner
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800773 removeLinkDiscoveryEvent(linkEvent, true);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800774 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800775 return true;
776 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800777
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800778 private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
779 // Src/Dst Port must exist
780 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
781 linkEvent.getSrc().number);
782 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
783 linkEvent.getDst().number);
784 if (srcPort == null || dstPort == null) {
Jonathan Hart0a4846e2014-02-18 11:03:40 -0800785 log.warn("Dropping add link event because port doesn't exist: {}",
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800786 linkEvent);
787 return false;
Jonathan Hart22eb9882014-02-11 15:52:59 -0800788 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800789
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800790 // Prep: remove Device attachment on both Ports
791 ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
792 for (Device device : srcPort.getDevices()) {
793 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
794 devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
795 deviceEvents.add(devEvent);
796 }
797 for (Device device : dstPort.getDevices()) {
798 DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
799 devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
800 dstPort.getNumber()));
801 deviceEvents.add(devEvent);
802 }
803 for (DeviceEvent devEvent : deviceEvents) {
804 // calling Discovery API to wipe from DB, etc.
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800805 removeDeviceDiscoveryEvent(devEvent);
Jonathan Hart22eb9882014-02-11 15:52:59 -0800806 }
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -0800807
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800808 return true;
809 }
Yuta HIGUCHId02e9282014-02-12 09:24:41 -0800810
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800811 private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
812 // Src/Dst Port must exist
813 Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
814 linkEvent.getSrc().number);
815 Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
816 linkEvent.getDst().number);
817 if (srcPort == null || dstPort == null) {
818 log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
819 return false;
820 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800821
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800822 Link link = srcPort.getOutgoingLink();
823
824 // Link is already gone, or different Link exist in memory
825 // XXX Check if we should reject or just accept these cases.
826 // it should be harmless to remove the Link on event from DB anyways
827 if (link == null ||
Pavlin Radoslavov7c8f69a2014-02-19 19:01:45 -0800828 !link.getDstPort().getNumber().equals(linkEvent.getDst().number)
829 || !link.getDstSwitch().getDpid().equals(linkEvent.getDst().dpid)) {
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800830 log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
831 return false;
832 }
833 // Prep: None
834 return true;
835 }
836
837 /**
838 *
839 * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
840 * @return false if this event should be dropped.
841 */
842 private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
843 boolean preconditionBroken = false;
844 ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
845 for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
846 // Attached Ports must exist
847 Port port = networkGraph.getPort(swp.dpid, swp.number);
848 if (port == null) {
849 preconditionBroken = true;
850 failedSwitchPort.add(swp);
851 continue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800852 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800853 // Attached Ports must not have Link
854 if (port.getOutgoingLink() != null ||
855 port.getIncomingLink() != null) {
856 preconditionBroken = true;
857 failedSwitchPort.add(swp);
858 continue;
859 }
860 }
861
862 // Rewriting event to exclude failed attachmentPoint
863 // XXX Assumption behind this is that inapplicable device event should
864 // be dropped, not deferred. If we decide to defer Device event,
865 // rewriting can become a problem
866 List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
867 attachmentPoints.removeAll(failedSwitchPort);
868 deviceEvent.setAttachmentPoints(attachmentPoints);
869
870 if (deviceEvent.getAttachmentPoints().isEmpty() &&
871 deviceEvent.getIpAddresses().isEmpty()) {
872 // return false to represent: Nothing left to do for this event.
873 // Caller should drop event
874 return false;
875 }
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -0800876
877 // Should we return false to tell caller that the event was trimmed?
878 // if ( preconditionBroken ) {
879 // return false;
880 // }
881
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800882 return true;
883 }
884
885 private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
886 // No show stopping precondition?
887 // Prep: none
888 return true;
889 }
890
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800891 private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
892 for (INetworkGraphListener listener : this.networkGraphListeners) {
893 // TODO Should copy before handing them over to listener
894 listener.putSwitchEvent(switchEvent);
895 }
896 }
897
898 private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
899 for (INetworkGraphListener listener : this.networkGraphListeners) {
900 // TODO Should copy before handing them over to listener
901 listener.removeSwitchEvent(switchEvent);
902 }
903 }
904
905 private void dispatchPutPortEvent(PortEvent portEvent) {
906 for (INetworkGraphListener listener : this.networkGraphListeners) {
907 // TODO Should copy before handing them over to listener
908 listener.putPortEvent(portEvent);
909 }
910 }
911
912 private void dispatchRemovePortEvent(PortEvent portEvent) {
913 for (INetworkGraphListener listener : this.networkGraphListeners) {
914 // TODO Should copy before handing them over to listener
915 listener.removePortEvent(portEvent);
916 }
917 }
918
919 private void dispatchPutLinkEvent(LinkEvent linkEvent) {
920 for (INetworkGraphListener listener : this.networkGraphListeners) {
921 // TODO Should copy before handing them over to listener
922 listener.putLinkEvent(linkEvent);
923 }
924 }
925
926 private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
927 for (INetworkGraphListener listener : this.networkGraphListeners) {
928 // TODO Should copy before handing them over to listener
929 listener.removeLinkEvent(linkEvent);
930 }
931 }
932
933 private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
934 for (INetworkGraphListener listener : this.networkGraphListeners) {
935 // TODO Should copy before handing them over to listener
936 listener.putDeviceEvent(deviceEvent);;
937 }
938 }
939
940 private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
941 for (INetworkGraphListener listener : this.networkGraphListeners) {
942 // TODO Should copy before handing them over to listener
943 listener.removeDeviceEvent(deviceEvent);
944 }
945 }
946
947 private SwitchImpl getSwitchImpl(Switch sw) {
948 if (sw instanceof SwitchImpl) {
949 return (SwitchImpl) sw;
950 }
951 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
952 }
953
954 private PortImpl getPortImpl(Port p) {
955 if (p instanceof PortImpl) {
956 return (PortImpl) p;
957 }
958 throw new ClassCastException("PortImpl expected, but found: " + p);
959 }
960
961 private LinkImpl getLinkImpl(Link l) {
962 if (l instanceof LinkImpl) {
963 return (LinkImpl) l;
964 }
965 throw new ClassCastException("LinkImpl expected, but found: " + l);
966 }
967
968 private DeviceImpl getDeviceImpl(Device d) {
969 if (d instanceof DeviceImpl) {
970 return (DeviceImpl) d;
971 }
972 throw new ClassCastException("DeviceImpl expected, but found: " + d);
973 }
974
975 @Deprecated
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800976 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
977 Collection<EventEntry<TopologyEvent>> collection =
978 new LinkedList<EventEntry<TopologyEvent>>();
979
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800980 // XXX May need to clear whole topology first, depending on
981 // how we initially subscribe to replication events
982
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800983 // Add all active switches
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800984 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
985 if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
986 continue;
987 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800988
989 SwitchEvent switchEvent = new SwitchEvent(sw.getDpid());
990 TopologyEvent topologyEvent = new TopologyEvent(switchEvent);
991 EventEntry<TopologyEvent> eventEntry =
992 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
993 topologyEvent);
994 collection.add(eventEntry);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -0800995 }
996
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800997 // Add all active ports
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800998 for (RCPort p : RCPort.getAllPorts()) {
999 if (p.getStatus() != RCPort.STATUS.ACTIVE) {
1000 continue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001001 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001002
1003 PortEvent portEvent = new PortEvent(p.getDpid(), p.getNumber());
1004 TopologyEvent topologyEvent = new TopologyEvent(portEvent);
1005 EventEntry<TopologyEvent> eventEntry =
1006 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1007 topologyEvent);
1008 collection.add(eventEntry);
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001009 }
1010
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001011 // TODO Is Device going to be in DB? If so, read from DB.
1012 // for (RCDevice d : RCDevice.getAllDevices()) {
1013 // DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
1014 // for (byte[] portId : d.getAllPortIds() ) {
1015 // devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
1016 // }
1017 // }
1018
1019 for (RCLink l : RCLink.getAllLinks()) {
1020 // check if src/dst switch/port exist before triggering event
1021 Port srcPort = networkGraph.getPort(l.getSrc().dpid,
1022 l.getSrc().number);
1023 Port dstPort = networkGraph.getPort(l.getDst().dpid,
1024 l.getDst().number);
1025 if (srcPort == null || dstPort == null) {
1026 continue;
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001027 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001028
1029 LinkEvent linkEvent = new LinkEvent(l.getSrc().dpid,
1030 l.getSrc().number,
1031 l.getDst().dpid,
1032 l.getDst().number);
1033 TopologyEvent topologyEvent = new TopologyEvent(linkEvent);
1034 EventEntry<TopologyEvent> eventEntry =
1035 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1036 topologyEvent);
1037 collection.add(eventEntry);
Yuta HIGUCHI76df2472014-02-12 22:36:51 -08001038 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001039
1040 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001041 }
Pavlin Radoslavov50cd1482014-02-19 16:57:03 -08001042
1043 @Deprecated
1044 private void removeLinkDiscoveryEvent(LinkEvent linkEvent,
1045 boolean dstCheckBeforeDBmodify) {
1046 if (prepareForRemoveLinkEvent(linkEvent)) {
1047 if (dstCheckBeforeDBmodify) {
1048 // write to DB only if it is owner of the dst dpid
1049 // XXX this will cause link remove events to be dropped
1050 // if the dst switch just disconnected
1051 if (registryService.hasControl(linkEvent.getDst().dpid)) {
1052 datastore.removeLink(linkEvent);
1053 }
1054 } else {
1055 datastore.removeLink(linkEvent);
1056 }
1057 removeLink(linkEvent);
1058 // Send out notification
1059 eventChannel.removeEntry(linkEvent.getID());
1060 }
1061 // TODO handle invariant violation
1062 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001063}