blob: 05abc46a7d39696ba04e5b26f9c2decb9d598d8c [file] [log] [blame]
Jonathan Hart472062d2014-04-03 10:56:48 -07001package net.onrc.onos.core.topology;
Jonathan Hart062a2e82014-02-03 09:41:57 -08002
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08003import java.nio.ByteBuffer;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08004import java.util.ArrayList;
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07005import java.util.Arrays;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -08006import java.util.Collection;
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07007import java.util.Comparator;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08008import java.util.HashMap;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -08009import java.util.HashSet;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080010import java.util.LinkedList;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080011import java.util.List;
Pavlin Radoslavov018d5332014-02-19 23:08:35 -080012import java.util.Map;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080013import java.util.Set;
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -070014import java.util.TreeSet;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080015import java.util.concurrent.BlockingQueue;
Yuta HIGUCHIa536e762014-02-17 21:47:28 -080016import java.util.concurrent.CopyOnWriteArrayList;
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080017import java.util.concurrent.LinkedBlockingQueue;
Yuta HIGUCHI8d762e92014-02-12 14:10:25 -080018
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -070019import javax.annotation.concurrent.GuardedBy;
20
TeruU28adcc32014-04-15 17:57:35 -070021import net.floodlightcontroller.util.MACAddress;
Jonathan Hart6df90172014-04-03 10:13:11 -070022import net.onrc.onos.core.datagrid.IDatagridService;
23import net.onrc.onos.core.datagrid.IEventChannel;
24import net.onrc.onos.core.datagrid.IEventChannelListener;
TeruU28adcc32014-04-15 17:57:35 -070025import net.onrc.onos.core.datastore.topology.KVDevice;
Jonathan Hart6df90172014-04-03 10:13:11 -070026import net.onrc.onos.core.datastore.topology.KVLink;
27import net.onrc.onos.core.datastore.topology.KVPort;
28import net.onrc.onos.core.datastore.topology.KVSwitch;
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070029import net.onrc.onos.core.metrics.OnosMetrics;
30import net.onrc.onos.core.metrics.OnosMetrics.MetricsComponent;
31import net.onrc.onos.core.metrics.OnosMetrics.MetricsFeature;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070032import net.onrc.onos.core.registry.IControllerRegistryService;
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -070033import net.onrc.onos.core.util.Dpid;
Jonathan Hart23701d12014-04-03 10:45:48 -070034import net.onrc.onos.core.util.EventEntry;
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -070035import net.onrc.onos.core.util.PortNumber;
Yuta HIGUCHI5c8cbeb2014-06-27 11:13:48 -070036import net.onrc.onos.core.util.SwitchPort;
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -070037import net.onrc.onos.core.util.serializers.KryoFactory;
Yuta HIGUCHI5c8cbeb2014-06-27 11:13:48 -070038
Jonathan Hart062a2e82014-02-03 09:41:57 -080039import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070042import com.codahale.metrics.Gauge;
43import com.codahale.metrics.Meter;
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -070044import com.esotericsoftware.kryo.Kryo;
45
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080046/**
Jonathan Harte37e4e22014-05-13 19:12:02 -070047 * The TopologyManager receives topology updates from the southbound discovery
48 * modules and from other ONOS instances. These updates are processed and
49 * applied to the in-memory topology instance.
Ray Milkey269ffb92014-04-03 14:43:30 -070050 * <p/>
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080051 * - Maintain Invariant/Relationships between Topology Objects.
Ray Milkey269ffb92014-04-03 14:43:30 -070052 * <p/>
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080053 * TODO To be synchronized based on TopologyEvent Notification.
Ray Milkey269ffb92014-04-03 14:43:30 -070054 * <p/>
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080055 * TODO TBD: Caller is expected to maintain parent/child calling order. Parent
Yuta HIGUCHI1c700102014-02-12 16:30:52 -080056 * Object must exist before adding sub component(Add Switch -> Port).
Ray Milkey269ffb92014-04-03 14:43:30 -070057 * <p/>
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080058 * TODO TBD: This class may delay the requested change to handle event
59 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080060 */
Jonathan Harte37e4e22014-05-13 19:12:02 -070061public class TopologyManager implements TopologyDiscoveryInterface {
Jonathan Hart062a2e82014-02-03 09:41:57 -080062
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080063 private static final Logger log = LoggerFactory
Ray Milkey269ffb92014-04-03 14:43:30 -070064 .getLogger(TopologyManager.class);
Yuta HIGUCHIcd922f42014-02-11 18:59:11 -080065
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080066 private IEventChannel<byte[], TopologyEvent> eventChannel;
Jonathan Hart10a7e2b2014-02-21 18:30:08 -080067 public static final String EVENT_CHANNEL_NAME = "onos.topology";
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -080068 private EventHandler eventHandler = new EventHandler();
69
weibitf7c31a42014-06-23 16:51:01 -070070 private TopologyDatastore datastore;
Jonathan Harte37e4e22014-05-13 19:12:02 -070071 private final TopologyImpl topology = new TopologyImpl();
Yuta HIGUCHI170229f2014-02-17 15:47:54 -080072 private final IControllerRegistryService registryService;
Jonathan Harte37e4e22014-05-13 19:12:02 -070073 private CopyOnWriteArrayList<ITopologyListener> topologyListeners;
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -070074 private Kryo kryo = KryoFactory.newKryoObject();
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -070075 private final TopologyEventFilter eventFilter = new TopologyEventFilter();
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080076
Pavlin Radoslavov706add22014-02-20 12:15:59 -080077 //
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070078 // Metrics
79 //
80 private static final MetricsComponent METRICS_COMPONENT =
81 OnosMetrics.registerComponent("Topology");
82 private static final MetricsFeature METRICS_FEATURE_EVENT_NOTIFICATION =
83 METRICS_COMPONENT.registerFeature("EventNotification");
84 //
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -070085 // Timestamp of the last Topology event (ms from the Epoch)
86 private volatile long lastEventTimestampEpochMs = 0;
87 private final Gauge<Long> gaugeLastEventTimestampEpochMs =
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070088 OnosMetrics.registerMetric(METRICS_COMPONENT,
89 METRICS_FEATURE_EVENT_NOTIFICATION,
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -070090 "LastEventTimestamp.EpochMs",
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070091 new Gauge<Long>() {
92 @Override
93 public Long getValue() {
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -070094 return lastEventTimestampEpochMs;
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070095 }
96 });
97 // Rate of the Topology events published to the Topology listeners
98 private final Meter listenerEventRate =
99 OnosMetrics.createMeter(METRICS_COMPONENT,
100 METRICS_FEATURE_EVENT_NOTIFICATION,
101 "ListenerEventRate");
102
103 //
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800104 // Local state for keeping track of reordered events.
105 // NOTE: Switch Events are not affected by the event reordering.
106 //
107 private Map<ByteBuffer, PortEvent> reorderedAddedPortEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700108 new HashMap<ByteBuffer, PortEvent>();
Pavlin Radoslavov706add22014-02-20 12:15:59 -0800109 private Map<ByteBuffer, LinkEvent> reorderedAddedLinkEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700110 new HashMap<ByteBuffer, LinkEvent>();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700111 private Map<ByteBuffer, HostEvent> reorderedAddedHostEvents =
112 new HashMap<ByteBuffer, HostEvent>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800113
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800114 //
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800115 // Local state for keeping track of locally discovered events so we can
116 // cleanup properly when a Switch or Port is removed.
117 //
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700118 // We keep all Port, (incoming) Link and Host events per Switch DPID:
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800119 // - If a switch goes down, we remove all corresponding Port, Link and
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700120 // Host events.
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800121 // - If a port on a switch goes down, we remove all corresponding Link
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700122 // and Host events discovered by this instance.
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700123 //
124 // How to handle side-effect of remote events.
125 // - Remote Port Down event -> Link Down
126 // Not handled. (XXX Shouldn't it be removed from discovered.. Map)
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700127 // - Remote Host Added -> lose ownership of Host)
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700128 // Not handled. (XXX Shouldn't it be removed from discovered.. Map)
129 //
130 // XXX Domain knowledge based invariant maintenance should be moved to
131 // driver module, since the invariant may be different on optical, etc.
132 //
133 // What happens on leadership change?
134 // - Probably should: remove from discovered.. Maps, but not send DELETE events
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700135 // XXX Switch/Port can be rediscovered by new leader, but Link, Host?
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700136 // - Current: There is no way to recognize leadership change?
137 // ZookeeperRegistry.requestControl(long, ControlChangeCallback)
138 // is the only way to register listener, and it allows only 1 listener,
139 // which is already used by Controller class.
140 //
141 // FIXME Replace with concurrent variant.
142 // #removeSwitchDiscoveryEvent(SwitchEvent) runs in different thread.
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800143 //
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700144 private Map<Dpid, Map<ByteBuffer, PortEvent>> discoveredAddedPortEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700145 new HashMap<>();
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700146 private Map<Dpid, Map<ByteBuffer, LinkEvent>> discoveredAddedLinkEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700147 new HashMap<>();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700148 private Map<Dpid, Map<ByteBuffer, HostEvent>> discoveredAddedHostEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700149 new HashMap<>();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800150
151 //
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800152 // Local state for keeping track of the application event notifications
153 //
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700154 // - Queue of events, which will be dispatched to local listeners
155 // on next notification.
Yuta HIGUCHI703696c2014-06-25 20:36:45 -0700156
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700157 private List<MastershipEvent> apiAddedMastershipEvents =
158 new LinkedList<>();
159 private List<MastershipEvent> apiRemovedMastershipEvents =
160 new LinkedList<>();
Yuta HIGUCHI703696c2014-06-25 20:36:45 -0700161 private List<SwitchEvent> apiAddedSwitchEvents = new LinkedList<>();
162 private List<SwitchEvent> apiRemovedSwitchEvents = new LinkedList<>();
163 private List<PortEvent> apiAddedPortEvents = new LinkedList<>();
164 private List<PortEvent> apiRemovedPortEvents = new LinkedList<>();
165 private List<LinkEvent> apiAddedLinkEvents = new LinkedList<>();
166 private List<LinkEvent> apiRemovedLinkEvents = new LinkedList<>();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700167 private List<HostEvent> apiAddedHostEvents = new LinkedList<>();
168 private List<HostEvent> apiRemovedHostEvents = new LinkedList<>();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800169
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800170 /**
171 * Constructor.
172 *
Jonathan Harte37e4e22014-05-13 19:12:02 -0700173 * @param registryService the Registry Service to use.
174 * @param topologyListeners the collection of topology listeners to use.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800175 */
176 public TopologyManager(IControllerRegistryService registryService,
Jonathan Harte37e4e22014-05-13 19:12:02 -0700177 CopyOnWriteArrayList<ITopologyListener> topologyListeners) {
178 datastore = new TopologyDatastore();
Ray Milkey269ffb92014-04-03 14:43:30 -0700179 this.registryService = registryService;
Jonathan Harte37e4e22014-05-13 19:12:02 -0700180 this.topologyListeners = topologyListeners;
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800181 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800182
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800183 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700184 * Get the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800185 *
Jonathan Harte37e4e22014-05-13 19:12:02 -0700186 * @return the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800187 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700188 Topology getTopology() {
189 return topology;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -0800190 }
191
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800192 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800193 * Event handler class.
194 */
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -0700195 class EventHandler extends Thread implements
Ray Milkey269ffb92014-04-03 14:43:30 -0700196 IEventChannelListener<byte[], TopologyEvent> {
197 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
198 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800199
Ray Milkey269ffb92014-04-03 14:43:30 -0700200 /**
201 * Startup processing.
202 */
203 private void startup() {
204 //
205 // TODO: Read all state from the database:
206 //
207 // Collection<EventEntry<TopologyEvent>> collection =
208 // readWholeTopologyFromDB();
209 //
210 // For now, as a shortcut we read it from the datagrid
211 //
Ray Milkey5df613b2014-04-15 10:50:56 -0700212 Collection<TopologyEvent> allTopologyEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700213 eventChannel.getAllEntries();
214 Collection<EventEntry<TopologyEvent>> collection =
215 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800216
Ray Milkey5df613b2014-04-15 10:50:56 -0700217 for (TopologyEvent topologyEvent : allTopologyEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700218 EventEntry<TopologyEvent> eventEntry =
219 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
220 topologyEvent);
221 collection.add(eventEntry);
222 }
223 processEvents(collection);
224 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800225
Ray Milkey269ffb92014-04-03 14:43:30 -0700226 /**
227 * Run the thread.
228 */
229 @Override
230 public void run() {
231 Collection<EventEntry<TopologyEvent>> collection =
232 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800233
Ray Milkey269ffb92014-04-03 14:43:30 -0700234 this.setName("TopologyManager.EventHandler " + this.getId());
235 startup();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800236
Ray Milkey269ffb92014-04-03 14:43:30 -0700237 //
238 // The main loop
239 //
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700240 while (true) {
241 try {
242 EventEntry<TopologyEvent> eventEntry =
243 topologyEvents.take();
Ray Milkey269ffb92014-04-03 14:43:30 -0700244 collection.add(eventEntry);
245 topologyEvents.drainTo(collection);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800246
Ray Milkey269ffb92014-04-03 14:43:30 -0700247 processEvents(collection);
248 collection.clear();
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700249 } catch (Exception exception) {
250 log.debug("Exception processing Topology Events: ",
251 exception);
Ray Milkey269ffb92014-04-03 14:43:30 -0700252 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700253 }
254 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800255
Ray Milkey269ffb92014-04-03 14:43:30 -0700256 /**
257 * Process all topology events.
258 *
259 * @param events the events to process.
260 */
261 private void processEvents(Collection<EventEntry<TopologyEvent>> events) {
262 // Local state for computing the final set of events
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700263 Map<ByteBuffer, MastershipEvent> addedMastershipEvents =
264 new HashMap<>();
265 Map<ByteBuffer, MastershipEvent> removedMastershipEvents =
266 new HashMap<>();
Ray Milkey269ffb92014-04-03 14:43:30 -0700267 Map<ByteBuffer, SwitchEvent> addedSwitchEvents = new HashMap<>();
268 Map<ByteBuffer, SwitchEvent> removedSwitchEvents = new HashMap<>();
269 Map<ByteBuffer, PortEvent> addedPortEvents = new HashMap<>();
270 Map<ByteBuffer, PortEvent> removedPortEvents = new HashMap<>();
271 Map<ByteBuffer, LinkEvent> addedLinkEvents = new HashMap<>();
272 Map<ByteBuffer, LinkEvent> removedLinkEvents = new HashMap<>();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700273 Map<ByteBuffer, HostEvent> addedHostEvents = new HashMap<>();
274 Map<ByteBuffer, HostEvent> removedHostEvents = new HashMap<>();
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700275
276 //
277 // Filter the events
278 //
279 events = eventFilter.filterEvents(events);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800280
Ray Milkey269ffb92014-04-03 14:43:30 -0700281 //
282 // Classify and suppress matching events
283 //
284 for (EventEntry<TopologyEvent> event : events) {
285 TopologyEvent topologyEvent = event.eventData();
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700286 MastershipEvent mastershipEvent = topologyEvent.getMastershipEvent();
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700287 SwitchEvent switchEvent = topologyEvent.getSwitchEvent();
288 PortEvent portEvent = topologyEvent.getPortEvent();
289 LinkEvent linkEvent = topologyEvent.getLinkEvent();
290 HostEvent hostEvent = topologyEvent.getHostEvent();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800291
Ray Milkey269ffb92014-04-03 14:43:30 -0700292 //
293 // Extract the events
294 //
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -0700295 // FIXME Following event squashing logic based only on ID
296 // potentially lose attribute change.
Ray Milkey269ffb92014-04-03 14:43:30 -0700297 switch (event.eventType()) {
298 case ENTRY_ADD:
299 log.debug("Topology event ENTRY_ADD: {}", topologyEvent);
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700300 if (mastershipEvent != null) {
301 ByteBuffer id = mastershipEvent.getIDasByteBuffer();
302 addedMastershipEvents.put(id, mastershipEvent);
303 removedMastershipEvents.remove(id);
304 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700305 if (switchEvent != null) {
306 ByteBuffer id = switchEvent.getIDasByteBuffer();
307 addedSwitchEvents.put(id, switchEvent);
308 removedSwitchEvents.remove(id);
309 // Switch Events are not affected by event reordering
310 }
311 if (portEvent != null) {
312 ByteBuffer id = portEvent.getIDasByteBuffer();
313 addedPortEvents.put(id, portEvent);
314 removedPortEvents.remove(id);
315 reorderedAddedPortEvents.remove(id);
316 }
317 if (linkEvent != null) {
318 ByteBuffer id = linkEvent.getIDasByteBuffer();
319 addedLinkEvents.put(id, linkEvent);
320 removedLinkEvents.remove(id);
321 reorderedAddedLinkEvents.remove(id);
322 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700323 if (hostEvent != null) {
324 ByteBuffer id = hostEvent.getIDasByteBuffer();
325 addedHostEvents.put(id, hostEvent);
326 removedHostEvents.remove(id);
327 reorderedAddedHostEvents.remove(id);
Ray Milkey269ffb92014-04-03 14:43:30 -0700328 }
329 break;
330 case ENTRY_REMOVE:
331 log.debug("Topology event ENTRY_REMOVE: {}", topologyEvent);
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700332 if (mastershipEvent != null) {
333 ByteBuffer id = mastershipEvent.getIDasByteBuffer();
334 addedMastershipEvents.remove(id);
335 removedMastershipEvents.put(id, mastershipEvent);
336 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700337 if (switchEvent != null) {
338 ByteBuffer id = switchEvent.getIDasByteBuffer();
339 addedSwitchEvents.remove(id);
340 removedSwitchEvents.put(id, switchEvent);
341 // Switch Events are not affected by event reordering
342 }
343 if (portEvent != null) {
344 ByteBuffer id = portEvent.getIDasByteBuffer();
345 addedPortEvents.remove(id);
346 removedPortEvents.put(id, portEvent);
347 reorderedAddedPortEvents.remove(id);
348 }
349 if (linkEvent != null) {
350 ByteBuffer id = linkEvent.getIDasByteBuffer();
351 addedLinkEvents.remove(id);
352 removedLinkEvents.put(id, linkEvent);
353 reorderedAddedLinkEvents.remove(id);
354 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700355 if (hostEvent != null) {
356 ByteBuffer id = hostEvent.getIDasByteBuffer();
357 addedHostEvents.remove(id);
358 removedHostEvents.put(id, hostEvent);
359 reorderedAddedHostEvents.remove(id);
Ray Milkey269ffb92014-04-03 14:43:30 -0700360 }
361 break;
Ray Milkey0b122ed2014-04-14 10:06:03 -0700362 default:
363 log.error("Unknown topology event {}",
364 event.eventType());
Ray Milkey269ffb92014-04-03 14:43:30 -0700365 }
366 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800367
Ray Milkey269ffb92014-04-03 14:43:30 -0700368 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700369 // Lock the topology while it is modified
Ray Milkey269ffb92014-04-03 14:43:30 -0700370 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700371 topology.acquireWriteLock();
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800372
Ray Milkey269ffb92014-04-03 14:43:30 -0700373 try {
374 //
375 // Apply the classified events.
376 //
377 // Apply the "add" events in the proper order:
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700378 // mastership, switch, port, link, host
Ray Milkey269ffb92014-04-03 14:43:30 -0700379 //
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700380 // TODO: Currently, the Mastership events are not used,
381 // so their processing ordering is not important (undefined).
382 //
383 for (MastershipEvent mastershipEvent :
384 addedMastershipEvents.values()) {
385 processAddedMastershipEvent(mastershipEvent);
386 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700387 for (SwitchEvent switchEvent : addedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700388 addSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700389 }
390 for (PortEvent portEvent : addedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700391 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700392 }
393 for (LinkEvent linkEvent : addedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700394 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700395 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700396 for (HostEvent hostEvent : addedHostEvents.values()) {
397 addHost(hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700398 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700399 //
400 // Apply the "remove" events in the reverse order:
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700401 // host, link, port, switch, mastership
Ray Milkey269ffb92014-04-03 14:43:30 -0700402 //
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700403 for (HostEvent hostEvent : removedHostEvents.values()) {
404 removeHost(hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700405 }
406 for (LinkEvent linkEvent : removedLinkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700407 removeLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700408 }
409 for (PortEvent portEvent : removedPortEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700410 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700411 }
412 for (SwitchEvent switchEvent : removedSwitchEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700413 removeSwitch(switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700414 }
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700415 for (MastershipEvent mastershipEvent :
416 removedMastershipEvents.values()) {
417 processRemovedMastershipEvent(mastershipEvent);
418 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800419
Ray Milkey269ffb92014-04-03 14:43:30 -0700420 //
421 // Apply reordered events
422 //
423 applyReorderedEvents(!addedSwitchEvents.isEmpty(),
424 !addedPortEvents.isEmpty());
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800425
Ray Milkey269ffb92014-04-03 14:43:30 -0700426 } finally {
427 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700428 // Topology modifications completed: Release the lock
Ray Milkey269ffb92014-04-03 14:43:30 -0700429 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700430 topology.releaseWriteLock();
Ray Milkey269ffb92014-04-03 14:43:30 -0700431 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800432
Ray Milkey269ffb92014-04-03 14:43:30 -0700433 //
434 // Dispatch the Topology Notification Events to the applications
435 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700436 dispatchTopologyEvents();
Ray Milkey269ffb92014-04-03 14:43:30 -0700437 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800438
Ray Milkey269ffb92014-04-03 14:43:30 -0700439 /**
440 * Receive a notification that an entry is added.
441 *
442 * @param value the value for the entry.
443 */
444 @Override
445 public void entryAdded(TopologyEvent value) {
446 EventEntry<TopologyEvent> eventEntry =
447 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
448 value);
449 topologyEvents.add(eventEntry);
450 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800451
Ray Milkey269ffb92014-04-03 14:43:30 -0700452 /**
453 * Receive a notification that an entry is removed.
454 *
455 * @param value the value for the entry.
456 */
457 @Override
458 public void entryRemoved(TopologyEvent value) {
459 EventEntry<TopologyEvent> eventEntry =
460 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
461 value);
462 topologyEvents.add(eventEntry);
463 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800464
Ray Milkey269ffb92014-04-03 14:43:30 -0700465 /**
466 * Receive a notification that an entry is updated.
467 *
468 * @param value the value for the entry.
469 */
470 @Override
471 public void entryUpdated(TopologyEvent value) {
472 // NOTE: The ADD and UPDATE events are processed in same way
473 entryAdded(value);
474 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800475 }
476
477 /**
478 * Startup processing.
479 *
480 * @param datagridService the datagrid service to use.
481 */
482 void startup(IDatagridService datagridService) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700483 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
484 eventHandler,
485 byte[].class,
486 TopologyEvent.class);
487 eventHandler.start();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800488 }
489
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800490 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700491 * Dispatch Topology Events to the listeners.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800492 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700493 private void dispatchTopologyEvents() {
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700494 if (apiAddedMastershipEvents.isEmpty() &&
495 apiRemovedMastershipEvents.isEmpty() &&
496 apiAddedSwitchEvents.isEmpty() &&
Ray Milkey269ffb92014-04-03 14:43:30 -0700497 apiRemovedSwitchEvents.isEmpty() &&
498 apiAddedPortEvents.isEmpty() &&
499 apiRemovedPortEvents.isEmpty() &&
500 apiAddedLinkEvents.isEmpty() &&
501 apiRemovedLinkEvents.isEmpty() &&
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700502 apiAddedHostEvents.isEmpty() &&
503 apiRemovedHostEvents.isEmpty()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700504 return; // No events to dispatch
505 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800506
Ray Milkey269ffb92014-04-03 14:43:30 -0700507 if (log.isDebugEnabled()) {
508 //
509 // Debug statements
510 // TODO: Those statements should be removed in the future
511 //
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700512 for (MastershipEvent mastershipEvent : apiAddedMastershipEvents) {
513 log.debug("Dispatch Topology Event: ADDED {}",
514 mastershipEvent);
515 }
516 for (MastershipEvent mastershipEvent : apiRemovedMastershipEvents) {
517 log.debug("Dispatch Topology Event: REMOVED {}",
518 mastershipEvent);
519 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700520 for (SwitchEvent switchEvent : apiAddedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700521 log.debug("Dispatch Topology Event: ADDED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700522 }
523 for (SwitchEvent switchEvent : apiRemovedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700524 log.debug("Dispatch Topology Event: REMOVED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700525 }
526 for (PortEvent portEvent : apiAddedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700527 log.debug("Dispatch Topology Event: ADDED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700528 }
529 for (PortEvent portEvent : apiRemovedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700530 log.debug("Dispatch Topology Event: REMOVED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700531 }
532 for (LinkEvent linkEvent : apiAddedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700533 log.debug("Dispatch Topology Event: ADDED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700534 }
535 for (LinkEvent linkEvent : apiRemovedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700536 log.debug("Dispatch Topology Event: REMOVED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700537 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700538 for (HostEvent hostEvent : apiAddedHostEvents) {
539 log.debug("Dispatch Topology Event: ADDED {}", hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700540 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700541 for (HostEvent hostEvent : apiRemovedHostEvents) {
542 log.debug("Dispatch Topology Event: REMOVED {}", hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700543 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700544 }
adminbc181552014-02-21 18:36:42 -0800545
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700546 //
547 // Update the metrics
548 //
549 long totalEvents =
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700550 apiAddedMastershipEvents.size() + apiRemovedMastershipEvents.size() +
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700551 apiAddedSwitchEvents.size() + apiRemovedSwitchEvents.size() +
552 apiAddedPortEvents.size() + apiRemovedPortEvents.size() +
553 apiAddedLinkEvents.size() + apiRemovedLinkEvents.size() +
554 apiAddedHostEvents.size() + apiRemovedHostEvents.size();
555 this.listenerEventRate.mark(totalEvents);
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -0700556 this.lastEventTimestampEpochMs = System.currentTimeMillis();
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700557
558 //
Ray Milkey269ffb92014-04-03 14:43:30 -0700559 // Deliver the events
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700560 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700561 for (ITopologyListener listener : this.topologyListeners) {
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700562 TopologyEvents events =
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700563 new TopologyEvents(kryo.copy(apiAddedMastershipEvents),
564 kryo.copy(apiRemovedMastershipEvents),
565 kryo.copy(apiAddedSwitchEvents),
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700566 kryo.copy(apiRemovedSwitchEvents),
567 kryo.copy(apiAddedPortEvents),
568 kryo.copy(apiRemovedPortEvents),
569 kryo.copy(apiAddedLinkEvents),
570 kryo.copy(apiRemovedLinkEvents),
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700571 kryo.copy(apiAddedHostEvents),
572 kryo.copy(apiRemovedHostEvents));
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700573 listener.topologyEvents(events);
Ray Milkey269ffb92014-04-03 14:43:30 -0700574 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800575
Ray Milkey269ffb92014-04-03 14:43:30 -0700576 //
577 // Cleanup
578 //
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700579 apiAddedMastershipEvents.clear();
580 apiRemovedMastershipEvents.clear();
Ray Milkey269ffb92014-04-03 14:43:30 -0700581 apiAddedSwitchEvents.clear();
582 apiRemovedSwitchEvents.clear();
583 apiAddedPortEvents.clear();
584 apiRemovedPortEvents.clear();
585 apiAddedLinkEvents.clear();
586 apiRemovedLinkEvents.clear();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700587 apiAddedHostEvents.clear();
588 apiRemovedHostEvents.clear();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800589 }
590
591 /**
592 * Apply reordered events.
593 *
594 * @param hasAddedSwitchEvents true if there were Added Switch Events.
Ray Milkey269ffb92014-04-03 14:43:30 -0700595 * @param hasAddedPortEvents true if there were Added Port Events.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800596 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700597 @GuardedBy("topology.writeLock")
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800598 private void applyReorderedEvents(boolean hasAddedSwitchEvents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700599 boolean hasAddedPortEvents) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700600 if (!(hasAddedSwitchEvents || hasAddedPortEvents)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700601 return; // Nothing to do
Ray Milkeyb29e6262014-04-09 16:02:14 -0700602 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800603
Ray Milkey269ffb92014-04-03 14:43:30 -0700604 //
605 // Try to apply the reordered events.
606 //
607 // NOTE: For simplicity we try to apply all events of a particular
608 // type if any "parent" type event was processed:
609 // - Apply reordered Port Events if Switches were added
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700610 // - Apply reordered Link and Host Events if Switches or Ports
Ray Milkey269ffb92014-04-03 14:43:30 -0700611 // were added
612 //
adminbc181552014-02-21 18:36:42 -0800613
Ray Milkey269ffb92014-04-03 14:43:30 -0700614 //
615 // Apply reordered Port Events if Switches were added
616 //
617 if (hasAddedSwitchEvents) {
618 Map<ByteBuffer, PortEvent> portEvents = reorderedAddedPortEvents;
619 reorderedAddedPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700620 for (PortEvent portEvent : portEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700621 addPort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700622 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700623 }
624 //
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700625 // Apply reordered Link and Host Events if Switches or Ports
Ray Milkey269ffb92014-04-03 14:43:30 -0700626 // were added.
627 //
628 Map<ByteBuffer, LinkEvent> linkEvents = reorderedAddedLinkEvents;
629 reorderedAddedLinkEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700630 for (LinkEvent linkEvent : linkEvents.values()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700631 addLink(linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700632 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700633 //
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700634 Map<ByteBuffer, HostEvent> hostEvents = reorderedAddedHostEvents;
635 reorderedAddedHostEvents = new HashMap<>();
636 for (HostEvent hostEvent : hostEvents.values()) {
637 addHost(hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700638 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800639 }
640
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800641 /**
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700642 * Mastership updated event.
643 *
644 * @param mastershipEvent the mastership event.
645 */
646 @Override
647 public void putSwitchMastershipEvent(MastershipEvent mastershipEvent) {
648 // Send out notification
649 TopologyEvent topologyEvent =
650 new TopologyEvent(mastershipEvent,
651 registryService.getOnosInstanceId());
652 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
653 }
654
655 /**
656 * Mastership removed event.
657 *
658 * @param mastershipEvent the mastership event.
659 */
660 @Override
661 public void removeSwitchMastershipEvent(MastershipEvent mastershipEvent) {
662 // Send out notification
663 eventChannel.removeEntry(mastershipEvent.getID());
664 }
665
666 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800667 * Switch discovered event.
668 *
669 * @param switchEvent the switch event.
Ray Milkey269ffb92014-04-03 14:43:30 -0700670 * @param portEvents the corresponding port events for the switch.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800671 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800672 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800673 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
Ray Milkey269ffb92014-04-03 14:43:30 -0700674 Collection<PortEvent> portEvents) {
675 if (datastore.addSwitch(switchEvent, portEvents)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700676 log.debug("Sending add switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700677 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700678 TopologyEvent topologyEvent =
679 new TopologyEvent(switchEvent,
680 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700681 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800682
Ray Milkey269ffb92014-04-03 14:43:30 -0700683 // Send out notification for each port
684 for (PortEvent portEvent : portEvents) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700685 log.debug("Sending add port: {}", portEvent);
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700686 topologyEvent =
687 new TopologyEvent(portEvent,
688 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700689 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
690 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800691
Ray Milkey269ffb92014-04-03 14:43:30 -0700692 //
693 // Keep track of the added ports
694 //
695 // Get the old Port Events
696 Map<ByteBuffer, PortEvent> oldPortEvents =
697 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700698 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700699 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700700 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800701
Ray Milkey269ffb92014-04-03 14:43:30 -0700702 // Store the new Port Events in the local cache
703 Map<ByteBuffer, PortEvent> newPortEvents = new HashMap<>();
704 for (PortEvent portEvent : portEvents) {
705 ByteBuffer id = portEvent.getIDasByteBuffer();
706 newPortEvents.put(id, portEvent);
707 }
708 discoveredAddedPortEvents.put(switchEvent.getDpid(),
709 newPortEvents);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800710
Ray Milkey269ffb92014-04-03 14:43:30 -0700711 //
712 // Extract the removed ports
713 //
714 List<PortEvent> removedPortEvents = new LinkedList<>();
715 for (Map.Entry<ByteBuffer, PortEvent> entry : oldPortEvents.entrySet()) {
716 ByteBuffer key = entry.getKey();
717 PortEvent portEvent = entry.getValue();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700718 if (!newPortEvents.containsKey(key)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700719 removedPortEvents.add(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700720 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700721 }
722
723 // Cleanup old removed ports
Ray Milkeyb29e6262014-04-09 16:02:14 -0700724 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700725 removePortDiscoveryEvent(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700726 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700727 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800728 }
729
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800730 /**
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700731 * {@inheritDoc}
732 * <p/>
733 * Called by {@link TopologyPublisher.SwitchCleanup} thread.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800734 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800735 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800736 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700737 // Get the old Port Events
738 Map<ByteBuffer, PortEvent> oldPortEvents =
739 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700740 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700741 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700742 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800743
Ray Milkey269ffb92014-04-03 14:43:30 -0700744 if (datastore.deactivateSwitch(switchEvent, oldPortEvents.values())) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700745 log.debug("Sending remove switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700746 // Send out notification
747 eventChannel.removeEntry(switchEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800748
Ray Milkey269ffb92014-04-03 14:43:30 -0700749 //
750 // Send out notification for each port.
751 //
752 // NOTE: We don't use removePortDiscoveryEvent() for the cleanup,
753 // because it will attempt to remove the port from the database,
754 // and the deactiveSwitch() call above already removed all ports.
755 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700756 for (PortEvent portEvent : oldPortEvents.values()) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700757 log.debug("Sending remove port:", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700758 eventChannel.removeEntry(portEvent.getID());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700759 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700760 discoveredAddedPortEvents.remove(switchEvent.getDpid());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800761
Ray Milkey269ffb92014-04-03 14:43:30 -0700762 // Cleanup for each link
763 Map<ByteBuffer, LinkEvent> oldLinkEvents =
764 discoveredAddedLinkEvents.get(switchEvent.getDpid());
765 if (oldLinkEvents != null) {
766 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
767 removeLinkDiscoveryEvent(linkEvent);
768 }
769 discoveredAddedLinkEvents.remove(switchEvent.getDpid());
770 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800771
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700772 // Cleanup for each host
773 Map<ByteBuffer, HostEvent> oldHostEvents =
774 discoveredAddedHostEvents.get(switchEvent.getDpid());
775 if (oldHostEvents != null) {
776 for (HostEvent hostEvent : new ArrayList<>(oldHostEvents.values())) {
777 removeHostDiscoveryEvent(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700778 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700779 discoveredAddedHostEvents.remove(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700780 }
781 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800782 }
783
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800784 /**
785 * Port discovered event.
786 *
787 * @param portEvent the port event.
788 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800789 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800790 public void putPortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700791 if (datastore.addPort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700792 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700793 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700794 TopologyEvent topologyEvent =
795 new TopologyEvent(portEvent,
796 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700797 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800798
Ray Milkey269ffb92014-04-03 14:43:30 -0700799 // Store the new Port Event in the local cache
800 Map<ByteBuffer, PortEvent> oldPortEvents =
801 discoveredAddedPortEvents.get(portEvent.getDpid());
802 if (oldPortEvents == null) {
803 oldPortEvents = new HashMap<>();
804 discoveredAddedPortEvents.put(portEvent.getDpid(),
805 oldPortEvents);
806 }
807 ByteBuffer id = portEvent.getIDasByteBuffer();
808 oldPortEvents.put(id, portEvent);
809 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800810 }
811
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800812 /**
813 * Port removed event.
814 *
815 * @param portEvent the port event.
816 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800817 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800818 public void removePortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700819 if (datastore.deactivatePort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700820 log.debug("Sending remove port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700821 // Send out notification
822 eventChannel.removeEntry(portEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800823
Ray Milkey269ffb92014-04-03 14:43:30 -0700824 // Cleanup the Port Event from the local cache
825 Map<ByteBuffer, PortEvent> oldPortEvents =
826 discoveredAddedPortEvents.get(portEvent.getDpid());
827 if (oldPortEvents != null) {
828 ByteBuffer id = portEvent.getIDasByteBuffer();
829 oldPortEvents.remove(id);
830 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800831
Ray Milkey269ffb92014-04-03 14:43:30 -0700832 // Cleanup for the incoming link
833 Map<ByteBuffer, LinkEvent> oldLinkEvents =
834 discoveredAddedLinkEvents.get(portEvent.getDpid());
835 if (oldLinkEvents != null) {
836 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700837 if (linkEvent.getDst().equals(portEvent.getSwitchPort())) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700838 removeLinkDiscoveryEvent(linkEvent);
839 // XXX If we change our model to allow multiple Link on
840 // a Port, this loop must be fixed to allow continuing.
841 break;
842 }
843 }
844 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800845
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700846 // Cleanup for the connected hosts
Ray Milkey269ffb92014-04-03 14:43:30 -0700847 // TODO: The implementation below is probably wrong
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700848 List<HostEvent> removedHostEvents = new LinkedList<>();
849 Map<ByteBuffer, HostEvent> oldHostEvents =
850 discoveredAddedHostEvents.get(portEvent.getDpid());
851 if (oldHostEvents != null) {
852 for (HostEvent hostEvent : new ArrayList<>(oldHostEvents.values())) {
853 for (SwitchPort swp : hostEvent.getAttachmentPoints()) {
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700854 if (swp.equals(portEvent.getSwitchPort())) {
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700855 removedHostEvents.add(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700856 }
857 }
858 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700859 for (HostEvent hostEvent : removedHostEvents) {
860 removeHostDiscoveryEvent(hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700861 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700862 }
863 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800864 }
865
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800866 /**
867 * Link discovered event.
868 *
869 * @param linkEvent the link event.
870 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800871 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800872 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700873 if (datastore.addLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700874 log.debug("Sending add link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700875 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700876 TopologyEvent topologyEvent =
877 new TopologyEvent(linkEvent,
878 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700879 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800880
Ray Milkey269ffb92014-04-03 14:43:30 -0700881 // Store the new Link Event in the local cache
882 Map<ByteBuffer, LinkEvent> oldLinkEvents =
883 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
884 if (oldLinkEvents == null) {
885 oldLinkEvents = new HashMap<>();
886 discoveredAddedLinkEvents.put(linkEvent.getDst().getDpid(),
887 oldLinkEvents);
888 }
889 ByteBuffer id = linkEvent.getIDasByteBuffer();
890 oldLinkEvents.put(id, linkEvent);
891 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800892 }
893
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800894 /**
895 * Link removed event.
896 *
897 * @param linkEvent the link event.
898 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800899 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800900 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700901 if (datastore.removeLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700902 log.debug("Sending remove link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700903 // Send out notification
904 eventChannel.removeEntry(linkEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800905
Ray Milkey269ffb92014-04-03 14:43:30 -0700906 // Cleanup the Link Event from the local cache
907 Map<ByteBuffer, LinkEvent> oldLinkEvents =
908 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
909 if (oldLinkEvents != null) {
910 ByteBuffer id = linkEvent.getIDasByteBuffer();
911 oldLinkEvents.remove(id);
912 }
913 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800914 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800915
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800916 /**
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700917 * Host discovered event.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800918 *
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700919 * @param hostEvent the host event.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800920 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800921 @Override
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700922 public void putHostDiscoveryEvent(HostEvent hostEvent) {
923 if (datastore.addHost(hostEvent)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700924 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700925 TopologyEvent topologyEvent =
926 new TopologyEvent(hostEvent,
927 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700928 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700929 log.debug("Put the host info into the cache of the topology. mac {}", hostEvent.getMac());
Ray Milkey269ffb92014-04-03 14:43:30 -0700930
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700931 // Store the new Host Event in the local cache
Ray Milkey269ffb92014-04-03 14:43:30 -0700932 // TODO: The implementation below is probably wrong
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700933 for (SwitchPort swp : hostEvent.getAttachmentPoints()) {
934 Map<ByteBuffer, HostEvent> oldHostEvents =
935 discoveredAddedHostEvents.get(swp.getDpid());
936 if (oldHostEvents == null) {
937 oldHostEvents = new HashMap<>();
938 discoveredAddedHostEvents.put(swp.getDpid(),
939 oldHostEvents);
Ray Milkey269ffb92014-04-03 14:43:30 -0700940 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700941 ByteBuffer id = hostEvent.getIDasByteBuffer();
942 oldHostEvents.put(id, hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700943 }
944 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800945 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800946
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800947 /**
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700948 * Host removed event.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800949 *
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700950 * @param hostEvent the host event.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800951 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800952 @Override
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700953 public void removeHostDiscoveryEvent(HostEvent hostEvent) {
954 if (datastore.removeHost(hostEvent)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700955 // Send out notification
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700956 eventChannel.removeEntry(hostEvent.getID());
957 log.debug("Remove the host info into the cache of the topology. mac {}", hostEvent.getMac());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800958
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700959 // Cleanup the Host Event from the local cache
Ray Milkey269ffb92014-04-03 14:43:30 -0700960 // TODO: The implementation below is probably wrong
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700961 ByteBuffer id = ByteBuffer.wrap(hostEvent.getID());
962 for (SwitchPort swp : hostEvent.getAttachmentPoints()) {
963 Map<ByteBuffer, HostEvent> oldHostEvents =
964 discoveredAddedHostEvents.get(swp.getDpid());
965 if (oldHostEvents != null) {
966 oldHostEvents.remove(id);
Ray Milkey269ffb92014-04-03 14:43:30 -0700967 }
968 }
969 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800970 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800971
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -0700972 //
973 // Methods to update topology replica
974 //
975
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800976 /**
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700977 * Processes added Switch Mastership event.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700978 *
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700979 * @param mastershipEvent the MastershipEvent to process.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700980 */
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700981 @GuardedBy("topology.writeLock")
982 private void processAddedMastershipEvent(MastershipEvent mastershipEvent) {
983 log.debug("Processing added Mastership event {}",
984 mastershipEvent);
985 // TODO: Not implemented/used yet.
986 apiAddedMastershipEvents.add(mastershipEvent);
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700987 }
988
989 /**
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700990 * Processes removed Switch Mastership event.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700991 *
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700992 * @param mastershipEvent the MastershipEvent to process.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700993 */
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700994 @GuardedBy("topology.writeLock")
995 private void processRemovedMastershipEvent(MastershipEvent mastershipEvent) {
996 log.debug("Processing removed Mastership event {}",
997 mastershipEvent);
998 // TODO: Not implemented/used yet.
999 apiRemovedMastershipEvents.add(mastershipEvent);
Pavlin Radoslavov695f8952014-07-23 16:57:01 -07001000 }
1001
1002 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001003 * Adds a switch to the topology replica.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001004 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001005 * @param switchEvent the SwitchEvent with the switch to add.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001006 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001007 @GuardedBy("topology.writeLock")
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001008 private void addSwitch(SwitchEvent switchEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001009 if (log.isDebugEnabled()) {
1010 SwitchEvent sw = topology.getSwitchEvent(switchEvent.getDpid());
1011 if (sw != null) {
1012 log.debug("Update {}", switchEvent);
1013 } else {
1014 log.debug("Added {}", switchEvent);
1015 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001016 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001017 topology.putSwitch(switchEvent.freeze());
Ray Milkey269ffb92014-04-03 14:43:30 -07001018 apiAddedSwitchEvents.add(switchEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001019 }
1020
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001021 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001022 * Removes a switch from the topology replica.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001023 * <p/>
1024 * It will call {@link #removePort(PortEvent)} for each ports on this switch.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001025 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001026 * @param switchEvent the SwitchEvent with the switch to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001027 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001028 @GuardedBy("topology.writeLock")
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001029 private void removeSwitch(SwitchEvent switchEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001030 final Dpid dpid = switchEvent.getDpid();
1031
1032 SwitchEvent swInTopo = topology.getSwitchEvent(dpid);
1033 if (swInTopo == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001034 log.warn("Switch {} already removed, ignoring", switchEvent);
1035 return;
1036 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001037
Ray Milkey269ffb92014-04-03 14:43:30 -07001038 //
1039 // Remove all Ports on the Switch
1040 //
1041 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001042 for (Port port : topology.getPorts(dpid)) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001043 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
1044 port, switchEvent);
Yuta HIGUCHIcd14dda2014-07-24 09:57:22 -07001045 PortEvent portEvent = new PortEvent(port.getSwitchPort());
Ray Milkey269ffb92014-04-03 14:43:30 -07001046 portsToRemove.add(portEvent);
1047 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001048 for (PortEvent portEvent : portsToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001049 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -07001050 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001051
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001052 log.debug("Removed {}", swInTopo);
1053 topology.removeSwitch(dpid);
1054 apiRemovedSwitchEvents.add(swInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001055 }
1056
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001057 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001058 * Adds a port to the topology replica.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001059 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001060 * @param portEvent the PortEvent with the port to add.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001061 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001062 @GuardedBy("topology.writeLock")
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001063 private void addPort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001064 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -07001065 if (sw == null) {
Jonathan Hartf1675202014-05-23 14:59:07 -07001066 log.debug("{} reordered because switch is null", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001067 // Reordered event: delay the event in local cache
1068 ByteBuffer id = portEvent.getIDasByteBuffer();
1069 reorderedAddedPortEvents.put(id, portEvent);
1070 return;
1071 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001072
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001073 if (log.isDebugEnabled()) {
1074 PortEvent port = topology.getPortEvent(portEvent.getSwitchPort());
1075 if (port != null) {
1076 log.debug("Update {}", portEvent);
1077 } else {
1078 log.debug("Added {}", portEvent);
1079 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001080 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001081 topology.putPort(portEvent.freeze());
Ray Milkey269ffb92014-04-03 14:43:30 -07001082 apiAddedPortEvents.add(portEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001083 }
1084
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001085 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001086 * Removes a port from the topology replica.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001087 * <p/>
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001088 * It will remove attachment points from each hosts on this port
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001089 * and call {@link #removeLink(LinkEvent)} for each links on this port.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001090 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001091 * @param portEvent the PortEvent with the port to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001092 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001093 @GuardedBy("topology.writeLock")
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001094 private void removePort(PortEvent portEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001095 SwitchEvent sw = topology.getSwitchEvent(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -07001096 if (sw == null) {
1097 log.warn("Parent Switch for Port {} already removed, ignoring",
1098 portEvent);
1099 return;
1100 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001101
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001102 final SwitchPort switchPort = portEvent.getSwitchPort();
1103 PortEvent portInTopo = topology.getPortEvent(switchPort);
1104 if (portInTopo == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001105 log.warn("Port {} already removed, ignoring", portEvent);
1106 return;
1107 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001108
Ray Milkey269ffb92014-04-03 14:43:30 -07001109 //
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001110 // Remove all Host attachment points bound to this Port
Ray Milkey269ffb92014-04-03 14:43:30 -07001111 //
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001112 List<HostEvent> hostsToUpdate = new ArrayList<>();
1113 for (Host host : topology.getHosts(switchPort)) {
1114 log.debug("Removing Host {} on Port {}", host, portInTopo);
1115 HostEvent hostEvent = topology.getHostEvent(host.getMacAddress());
1116 hostsToUpdate.add(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001117 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001118 for (HostEvent hostEvent : hostsToUpdate) {
1119 HostEvent newHostEvent = new HostEvent(hostEvent);
1120 newHostEvent.removeAttachmentPoint(switchPort);
1121 newHostEvent.freeze();
1122
1123 // TODO should this event be fired inside #addHost?
1124 if (newHostEvent.getAttachmentPoints().isEmpty()) {
1125 // No more attachment point left -> remove Host
1126 removeHost(hostEvent);
1127 } else {
1128 // Update Host
1129 addHost(newHostEvent);
1130 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001131 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001132
Ray Milkey269ffb92014-04-03 14:43:30 -07001133 //
1134 // Remove all Links connected to the Port
1135 //
1136 Set<Link> links = new HashSet<>();
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001137 links.addAll(topology.getOutgoingLinks(switchPort));
1138 links.addAll(topology.getIncomingLinks(switchPort));
Ray Milkey269ffb92014-04-03 14:43:30 -07001139 for (Link link : links) {
Ray Milkeyb29e6262014-04-09 16:02:14 -07001140 if (link == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001141 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -07001142 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001143 LinkEvent linkEvent = topology.getLinkEvent(link.getLinkTuple());
1144 if (linkEvent != null) {
1145 log.debug("Removing Link {} on Port {}", link, portInTopo);
1146 removeLink(linkEvent);
1147 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001148 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001149
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001150 // Remove the Port from Topology
1151 log.debug("Removed {}", portInTopo);
1152 topology.removePort(switchPort);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001153
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001154 apiRemovedPortEvents.add(portInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001155 }
1156
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001157 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001158 * Adds a link to the topology replica.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001159 * <p/>
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001160 * It will remove attachment points from each hosts using the same ports.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001161 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001162 * @param linkEvent the LinkEvent with the link to add.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001163 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001164 @GuardedBy("topology.writeLock")
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001165 private void addLink(LinkEvent linkEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001166 PortEvent srcPort = topology.getPortEvent(linkEvent.getSrc());
1167 PortEvent dstPort = topology.getPortEvent(linkEvent.getDst());
Ray Milkey269ffb92014-04-03 14:43:30 -07001168 if ((srcPort == null) || (dstPort == null)) {
Jonathan Hartf1675202014-05-23 14:59:07 -07001169 log.debug("{} reordered because {} port is null", linkEvent,
1170 (srcPort == null) ? "src" : "dst");
1171
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001172 // XXX domain knowledge: port must be present before link.
Ray Milkey269ffb92014-04-03 14:43:30 -07001173 // Reordered event: delay the event in local cache
1174 ByteBuffer id = linkEvent.getIDasByteBuffer();
1175 reorderedAddedLinkEvents.put(id, linkEvent);
1176 return;
1177 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001178
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001179 // XXX domain knowledge: Sanity check: Port cannot have both Link and Host
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001180 // FIXME potentially local replica may not be up-to-date yet due to HZ delay.
1181 // may need to manage local truth and use them instead.
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001182 if (topology.getLinkEvent(linkEvent.getLinkTuple()) == null) {
1183 // Only check for existing Host when adding new Link.
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001184
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001185 // Remove all Hosts attached to the ports on both ends
1186
1187 Set<HostEvent> hostsToUpdate = new TreeSet<>(new Comparator<HostEvent>() {
1188 // comparison only using ID(=MAC)
1189 @Override
1190 public int compare(HostEvent o1, HostEvent o2) {
1191 return Long.compare(o1.getMac().toLong(), o2.getMac().toLong());
1192 }
1193 });
1194
1195 List<SwitchPort> portsToCheck = Arrays.asList(
1196 srcPort.getSwitchPort(),
1197 dstPort.getSwitchPort());
1198
1199 // Enumerate Host which needs to be updated by this Link add event
1200 for (SwitchPort port : portsToCheck) {
1201 for (Host host : topology.getHosts(port)) {
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001202 log.error("Host {} on Port {} should have been removed prior to adding Link {}",
1203 host, port, linkEvent);
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001204
1205 HostEvent hostEvent = topology.getHostEvent(host.getMacAddress());
1206 hostsToUpdate.add(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001207 }
1208 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001209 // remove attachment point from them.
1210 for (HostEvent hostEvent : hostsToUpdate) {
1211 // remove port from attachment point and update
1212 HostEvent newHostEvent = new HostEvent(hostEvent);
1213 newHostEvent.removeAttachmentPoint(srcPort.getSwitchPort());
1214 newHostEvent.removeAttachmentPoint(dstPort.getSwitchPort());
1215 newHostEvent.freeze();
1216
1217 // TODO should this event be fired inside #addHost?
1218 if (newHostEvent.getAttachmentPoints().isEmpty()) {
1219 // No more attachment point left -> remove Host
1220 removeHost(hostEvent);
1221 } else {
1222 // Update Host
1223 addHost(newHostEvent);
1224 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001225 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001226 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001227
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001228 if (log.isDebugEnabled()) {
1229 LinkEvent link = topology.getLinkEvent(linkEvent.getLinkTuple());
1230 if (link != null) {
1231 log.debug("Update {}", linkEvent);
1232 } else {
1233 log.debug("Added {}", linkEvent);
1234 }
1235 }
1236 topology.putLink(linkEvent.freeze());
Ray Milkey269ffb92014-04-03 14:43:30 -07001237 apiAddedLinkEvents.add(linkEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001238 }
1239
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001240 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001241 * Removes a link from the topology replica.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001242 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001243 * @param linkEvent the LinkEvent with the link to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001244 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001245 @GuardedBy("topology.writeLock")
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001246 private void removeLink(LinkEvent linkEvent) {
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -07001247 Port srcPort = topology.getPort(linkEvent.getSrc().getDpid(),
Yuta HIGUCHIb1e2ab72014-06-30 11:01:31 -07001248 linkEvent.getSrc().getPortNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -07001249 if (srcPort == null) {
1250 log.warn("Src Port for Link {} already removed, ignoring",
1251 linkEvent);
1252 return;
1253 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001254
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -07001255 Port dstPort = topology.getPort(linkEvent.getDst().getDpid(),
Yuta HIGUCHIb1e2ab72014-06-30 11:01:31 -07001256 linkEvent.getDst().getPortNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -07001257 if (dstPort == null) {
1258 log.warn("Dst Port for Link {} already removed, ignoring",
1259 linkEvent);
1260 return;
1261 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001262
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001263 LinkEvent linkInTopo = topology.getLinkEvent(linkEvent.getLinkTuple(),
1264 linkEvent.getType());
1265 if (linkInTopo == null) {
1266 log.warn("Link {} already removed, ignoring", linkEvent);
1267 return;
Ray Milkey269ffb92014-04-03 14:43:30 -07001268 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001269
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001270 if (log.isDebugEnabled()) {
1271 // only do sanity check on debug level
1272
1273 Link linkIn = dstPort.getIncomingLink(linkEvent.getType());
1274 if (linkIn == null) {
1275 log.warn("Link {} already removed on destination Port", linkEvent);
1276 }
1277 Link linkOut = srcPort.getOutgoingLink(linkEvent.getType());
1278 if (linkOut == null) {
1279 log.warn("Link {} already removed on src Port", linkEvent);
1280 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001281 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001282
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001283 log.debug("Removed {}", linkInTopo);
1284 topology.removeLink(linkEvent.getLinkTuple(), linkEvent.getType());
1285 apiRemovedLinkEvents.add(linkInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001286 }
1287
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001288 /**
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001289 * Adds a host to the topology replica.
Ray Milkey269ffb92014-04-03 14:43:30 -07001290 * <p/>
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001291 * TODO: Host-related work is incomplete.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001292 * TODO: Eventually, we might need to consider reordering
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001293 * or {@link #addLink(LinkEvent)} and {@link #addHost(HostEvent)} events on the same port.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001294 *
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001295 * @param hostEvent the HostEvent with the host to add.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001296 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001297 @GuardedBy("topology.writeLock")
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001298 private void addHost(HostEvent hostEvent) {
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001299
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001300 // TODO Decide how to handle update scenario.
1301 // If the new HostEvent has less attachment point compared to
1302 // existing HostEvent, what should the event be?
1303 // - AddHostEvent with some attachment point removed? (current behavior)
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001304
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001305 // create unfrozen copy
1306 // for removing attachment points which already has a link
1307 HostEvent modifiedHostEvent = new HostEvent(hostEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001308
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001309 // Verify each attachment point
Ray Milkey269ffb92014-04-03 14:43:30 -07001310 boolean attachmentFound = false;
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001311 for (SwitchPort swp : hostEvent.getAttachmentPoints()) {
1312 // XXX domain knowledge: Port must exist before Host
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001313 // but this knowledge cannot be pushed down to driver.
1314
Ray Milkey269ffb92014-04-03 14:43:30 -07001315 // Attached Ports must exist
Yuta HIGUCHIb1e2ab72014-06-30 11:01:31 -07001316 Port port = topology.getPort(swp.getDpid(), swp.getPortNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -07001317 if (port == null) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001318 log.debug("{} reordered because port {} was not there", hostEvent, swp);
Ray Milkey269ffb92014-04-03 14:43:30 -07001319 // Reordered event: delay the event in local cache
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001320 ByteBuffer id = hostEvent.getIDasByteBuffer();
1321 reorderedAddedHostEvents.put(id, hostEvent);
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001322 return; // should not continue if re-applying later
Ray Milkey269ffb92014-04-03 14:43:30 -07001323 }
1324 // Attached Ports must not have Link
1325 if (port.getOutgoingLink() != null ||
1326 port.getIncomingLink() != null) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001327 log.warn("Link (Out:{},In:{}) exist on the attachment point. "
1328 + "Ignoring this attachmentpoint ({}) from {}.",
1329 port.getOutgoingLink(), port.getIncomingLink(),
1330 swp, modifiedHostEvent);
1331 // FIXME Should either reject, reorder this HostEvent,
1332 // or remove attachment point from given HostEvent
1333 // Removing attachment point from given HostEvent for now.
1334 modifiedHostEvent.removeAttachmentPoint(swp);
Ray Milkey269ffb92014-04-03 14:43:30 -07001335 continue;
1336 }
1337
Ray Milkey269ffb92014-04-03 14:43:30 -07001338 attachmentFound = true;
1339 }
1340
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001341 // Update the host in the topology
Ray Milkey269ffb92014-04-03 14:43:30 -07001342 if (attachmentFound) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001343 if (modifiedHostEvent.getAttachmentPoints().isEmpty()) {
1344 log.warn("No valid attachment point left. Ignoring."
1345 + "original: {}, modified: {}", hostEvent, modifiedHostEvent);
1346 // TODO Should we call #removeHost to trigger remove event?
1347 // only if this call is update.
1348 return;
1349 }
1350
1351 if (log.isDebugEnabled()) {
1352 HostEvent host = topology.getHostEvent(hostEvent.getMac());
1353 if (host != null) {
1354 log.debug("Update {}", modifiedHostEvent);
1355 } else {
1356 log.debug("Added {}", modifiedHostEvent);
1357 }
1358 }
1359 topology.putHost(modifiedHostEvent.freeze());
1360 apiAddedHostEvents.add(modifiedHostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001361 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001362 }
1363
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001364 /**
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001365 * Removes a host from the topology replica.
Ray Milkey269ffb92014-04-03 14:43:30 -07001366 * <p/>
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001367 * TODO: Host-related work is incomplete.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001368 *
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001369 * @param hostEvent the Host Event with the host to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001370 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001371 @GuardedBy("topology.writeLock")
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001372 private void removeHost(HostEvent hostEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001373
1374 final MACAddress mac = hostEvent.getMac();
1375 HostEvent hostInTopo = topology.getHostEvent(mac);
1376 if (hostInTopo == null) {
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001377 log.warn("Host {} already removed, ignoring", hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001378 return;
1379 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001380
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001381 log.debug("Removed {}", hostInTopo);
1382 topology.removeHost(mac);
1383 apiRemovedHostEvents.add(hostInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001384 }
Jonathan Hart22eb9882014-02-11 15:52:59 -08001385
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001386 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001387 * Read the whole topology from the database.
1388 *
1389 * @return a collection of EventEntry-encapsulated Topology Events for
1390 * the whole topology.
1391 */
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001392 private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
Ray Milkey269ffb92014-04-03 14:43:30 -07001393 Collection<EventEntry<TopologyEvent>> collection =
1394 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001395
Ray Milkey269ffb92014-04-03 14:43:30 -07001396 // XXX May need to clear whole topology first, depending on
1397 // how we initially subscribe to replication events
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001398
Ray Milkey269ffb92014-04-03 14:43:30 -07001399 // Add all active switches
1400 for (KVSwitch sw : KVSwitch.getAllSwitches()) {
1401 if (sw.getStatus() != KVSwitch.STATUS.ACTIVE) {
1402 continue;
1403 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001404
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001405 //
1406 // TODO: Using the local ONOS Instance ID below is incorrect.
1407 // Currently, this code is not used, and it might go away in the
1408 // future.
1409 //
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -07001410 SwitchEvent switchEvent = new SwitchEvent(new Dpid(sw.getDpid()));
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001411 TopologyEvent topologyEvent =
1412 new TopologyEvent(switchEvent,
1413 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -07001414 EventEntry<TopologyEvent> eventEntry =
1415 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1416 topologyEvent);
1417 collection.add(eventEntry);
1418 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001419
Ray Milkey269ffb92014-04-03 14:43:30 -07001420 // Add all active ports
1421 for (KVPort p : KVPort.getAllPorts()) {
1422 if (p.getStatus() != KVPort.STATUS.ACTIVE) {
1423 continue;
1424 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001425
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001426 //
1427 // TODO: Using the local ONOS Instance ID below is incorrect.
1428 // Currently, this code is not used, and it might go away in the
1429 // future.
1430 //
1431 PortEvent portEvent =
1432 new PortEvent(new Dpid(p.getDpid()),
1433 new PortNumber(p.getNumber().shortValue()));
1434 TopologyEvent topologyEvent =
1435 new TopologyEvent(portEvent,
1436 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -07001437 EventEntry<TopologyEvent> eventEntry =
1438 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1439 topologyEvent);
1440 collection.add(eventEntry);
1441 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001442
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001443 for (KVDevice d : KVDevice.getAllDevices()) {
1444 //
1445 // TODO: Using the local ONOS Instance ID below is incorrect.
1446 // Currently, this code is not used, and it might go away in the
1447 // future.
1448 //
1449 HostEvent devEvent = new HostEvent(MACAddress.valueOf(d.getMac()));
1450 for (byte[] portId : d.getAllPortIds()) {
1451 devEvent.addAttachmentPoint(
1452 new SwitchPort(KVPort.getDpidFromKey(portId),
1453 KVPort.getNumberFromKey(portId)));
1454 }
1455 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001456
Ray Milkey269ffb92014-04-03 14:43:30 -07001457 for (KVLink l : KVLink.getAllLinks()) {
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001458 //
1459 // TODO: Using the local ONOS Instance ID below is incorrect.
1460 // Currently, this code is not used, and it might go away in the
1461 // future.
1462 //
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -07001463 LinkEvent linkEvent = new LinkEvent(
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001464 new SwitchPort(l.getSrc().dpid, l.getSrc().number),
1465 new SwitchPort(l.getDst().dpid, l.getDst().number));
1466 TopologyEvent topologyEvent =
1467 new TopologyEvent(linkEvent,
1468 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -07001469 EventEntry<TopologyEvent> eventEntry =
1470 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1471 topologyEvent);
1472 collection.add(eventEntry);
1473 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001474
Ray Milkey269ffb92014-04-03 14:43:30 -07001475 return collection;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001476 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001477}