blob: 57e8b6ec75a075421742ea02f9b7b4ca8463286d [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;
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -070073 private Kryo kryo = KryoFactory.newKryoObject();
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -070074 private TopologyEventPreprocessor eventPreprocessor;
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -070075 private CopyOnWriteArrayList<ITopologyListener> topologyListeners =
76 new CopyOnWriteArrayList<>();
Pavlin Radoslavov054cd592014-08-07 20:57:16 -070077 private CopyOnWriteArrayList<ITopologyListener> newTopologyListeners =
78 new CopyOnWriteArrayList<>();
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080079
Pavlin Radoslavov706add22014-02-20 12:15:59 -080080 //
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070081 // Metrics
82 //
83 private static final MetricsComponent METRICS_COMPONENT =
84 OnosMetrics.registerComponent("Topology");
85 private static final MetricsFeature METRICS_FEATURE_EVENT_NOTIFICATION =
86 METRICS_COMPONENT.registerFeature("EventNotification");
87 //
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -070088 // Timestamp of the last Topology event (ms from the Epoch)
89 private volatile long lastEventTimestampEpochMs = 0;
90 private final Gauge<Long> gaugeLastEventTimestampEpochMs =
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070091 OnosMetrics.registerMetric(METRICS_COMPONENT,
92 METRICS_FEATURE_EVENT_NOTIFICATION,
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -070093 "LastEventTimestamp.EpochMs",
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070094 new Gauge<Long>() {
95 @Override
96 public Long getValue() {
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -070097 return lastEventTimestampEpochMs;
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -070098 }
99 });
100 // Rate of the Topology events published to the Topology listeners
101 private final Meter listenerEventRate =
102 OnosMetrics.createMeter(METRICS_COMPONENT,
103 METRICS_FEATURE_EVENT_NOTIFICATION,
104 "ListenerEventRate");
105
106 //
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800107 // Local state for keeping track of locally discovered events so we can
108 // cleanup properly when a Switch or Port is removed.
109 //
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700110 // We keep all Port, (incoming) Link and Host events per Switch DPID:
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800111 // - If a switch goes down, we remove all corresponding Port, Link and
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700112 // Host events.
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800113 // - If a port on a switch goes down, we remove all corresponding Link
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700114 // and Host events discovered by this instance.
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700115 //
116 // How to handle side-effect of remote events.
117 // - Remote Port Down event -> Link Down
118 // Not handled. (XXX Shouldn't it be removed from discovered.. Map)
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700119 // - Remote Host Added -> lose ownership of Host)
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700120 // Not handled. (XXX Shouldn't it be removed from discovered.. Map)
121 //
122 // XXX Domain knowledge based invariant maintenance should be moved to
123 // driver module, since the invariant may be different on optical, etc.
124 //
125 // What happens on leadership change?
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700126 // - Probably should: remove from discovered.. Maps, but not send DELETE
127 // events
128 // XXX Switch/Port can be rediscovered by new leader, but Link, Host?
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700129 // - Current: There is no way to recognize leadership change?
130 // ZookeeperRegistry.requestControl(long, ControlChangeCallback)
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700131 // is the only way to register listener, and it allows only one
132 // listener, which is already used by Controller class.
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700133 //
134 // FIXME Replace with concurrent variant.
135 // #removeSwitchDiscoveryEvent(SwitchEvent) runs in different thread.
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800136 //
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700137 private Map<Dpid, Map<ByteBuffer, PortEvent>> discoveredAddedPortEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700138 new HashMap<>();
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700139 private Map<Dpid, Map<ByteBuffer, LinkEvent>> discoveredAddedLinkEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700140 new HashMap<>();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700141 private Map<Dpid, Map<ByteBuffer, HostEvent>> discoveredAddedHostEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700142 new HashMap<>();
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800143
144 //
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700145 // Local state for keeping the last ADD Mastership Event entries.
146 // TODO: In the future, we might have to keep this state somewhere else.
147 //
148 private Map<ByteBuffer, MastershipEvent> lastAddMastershipEvents =
149 new HashMap<>();
150
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.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800174 */
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700175 public TopologyManager(IControllerRegistryService registryService) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700176 datastore = new TopologyDatastore();
Ray Milkey269ffb92014-04-03 14:43:30 -0700177 this.registryService = registryService;
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700178 this.eventPreprocessor =
179 new TopologyEventPreprocessor(registryService);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800180 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800181
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800182 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700183 * Get the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800184 *
Jonathan Harte37e4e22014-05-13 19:12:02 -0700185 * @return the Topology.
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800186 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700187 Topology getTopology() {
188 return topology;
Pavlin Radoslavov6d224ee2014-02-18 16:43:15 -0800189 }
190
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800191 /**
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800192 * Event handler class.
193 */
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -0700194 class EventHandler extends Thread implements
Ray Milkey269ffb92014-04-03 14:43:30 -0700195 IEventChannelListener<byte[], TopologyEvent> {
196 private BlockingQueue<EventEntry<TopologyEvent>> topologyEvents =
197 new LinkedBlockingQueue<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800198
Ray Milkey269ffb92014-04-03 14:43:30 -0700199 /**
200 * Startup processing.
201 */
202 private void startup() {
203 //
204 // TODO: Read all state from the database:
205 //
206 // Collection<EventEntry<TopologyEvent>> collection =
207 // readWholeTopologyFromDB();
208 //
209 // For now, as a shortcut we read it from the datagrid
210 //
Ray Milkey5df613b2014-04-15 10:50:56 -0700211 Collection<TopologyEvent> allTopologyEvents =
Ray Milkey269ffb92014-04-03 14:43:30 -0700212 eventChannel.getAllEntries();
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700213 List<EventEntry<TopologyEvent>> events =
214 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800215
Ray Milkey5df613b2014-04-15 10:50:56 -0700216 for (TopologyEvent topologyEvent : allTopologyEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700217 EventEntry<TopologyEvent> eventEntry =
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700218 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
219 topologyEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700220 events.add(eventEntry);
Ray Milkey269ffb92014-04-03 14:43:30 -0700221 }
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700222 processEvents(events);
Ray Milkey269ffb92014-04-03 14:43:30 -0700223 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800224
Ray Milkey269ffb92014-04-03 14:43:30 -0700225 /**
226 * Run the thread.
227 */
228 @Override
229 public void run() {
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700230 List<EventEntry<TopologyEvent>> events =
231 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800232
Ray Milkey269ffb92014-04-03 14:43:30 -0700233 this.setName("TopologyManager.EventHandler " + this.getId());
234 startup();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800235
Ray Milkey269ffb92014-04-03 14:43:30 -0700236 //
237 // The main loop
238 //
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700239 while (true) {
240 try {
241 EventEntry<TopologyEvent> eventEntry =
242 topologyEvents.take();
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700243 events.add(eventEntry);
244 topologyEvents.drainTo(events);
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800245
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700246 processEvents(events);
247 events.clear();
Pavlin Radoslavov8e881a42014-06-24 16:58:07 -0700248 } catch (Exception exception) {
249 log.debug("Exception processing Topology Events: ",
250 exception);
Ray Milkey269ffb92014-04-03 14:43:30 -0700251 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700252 }
253 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800254
Ray Milkey269ffb92014-04-03 14:43:30 -0700255 /**
256 * Process all topology events.
257 *
258 * @param events the events to process.
259 */
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700260 private void processEvents(List<EventEntry<TopologyEvent>> events) {
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700261 //
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700262 // Process pending (new) listeners
263 //
264 processPendingListeners();
265
266 //
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700267 // Pre-process the events
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700268 //
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700269 events = eventPreprocessor.processEvents(events);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -0800270
Ray Milkey269ffb92014-04-03 14:43:30 -0700271 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700272 // Lock the topology while it is modified
Ray Milkey269ffb92014-04-03 14:43:30 -0700273 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700274 topology.acquireWriteLock();
Pavlin Radoslavov8ffb8bf2014-02-20 15:34:26 -0800275
Ray Milkey269ffb92014-04-03 14:43:30 -0700276 try {
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700277 // Apply the events
Ray Milkey269ffb92014-04-03 14:43:30 -0700278 //
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700279 // NOTE: The events are suppose to be in the proper order
280 // to naturally build and update the topology.
Ray Milkey269ffb92014-04-03 14:43:30 -0700281 //
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700282 for (EventEntry<TopologyEvent> event : events) {
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700283 // Ignore NO-OP events
284 if (event.isNoop()) {
285 continue;
286 }
287
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700288 TopologyEvent topologyEvent = event.eventData();
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800289
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700290 // Get the event itself
291 MastershipEvent mastershipEvent =
292 topologyEvent.getMastershipEvent();
293 SwitchEvent switchEvent = topologyEvent.getSwitchEvent();
294 PortEvent portEvent = topologyEvent.getPortEvent();
295 LinkEvent linkEvent = topologyEvent.getLinkEvent();
296 HostEvent hostEvent = topologyEvent.getHostEvent();
297 boolean wasAdded = false;
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800298
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700299 //
300 // Extract the events
301 //
302 switch (event.eventType()) {
303 case ENTRY_ADD:
304 if (mastershipEvent != null) {
305 wasAdded = addMastershipEvent(mastershipEvent);
306 }
307 if (switchEvent != null) {
308 wasAdded = addSwitch(switchEvent);
309 }
310 if (portEvent != null) {
311 wasAdded = addPort(portEvent);
312 }
313 if (linkEvent != null) {
314 wasAdded = addLink(linkEvent);
315 }
316 if (hostEvent != null) {
317 wasAdded = addHost(hostEvent);
318 }
319 // If the item wasn't added, probably it was reordered
320 if (!wasAdded) {
321 ByteBuffer id = topologyEvent.getIDasByteBuffer();
322 eventPreprocessor.reorderedEvents.put(id, topologyEvent);
323 }
324 break;
325 case ENTRY_REMOVE:
326 if (mastershipEvent != null) {
327 removeMastershipEvent(mastershipEvent);
328 }
329 if (switchEvent != null) {
330 removeSwitch(switchEvent);
331 }
332 if (portEvent != null) {
333 removePort(portEvent);
334 }
335 if (linkEvent != null) {
336 removeLink(linkEvent);
337 }
338 if (hostEvent != null) {
339 removeHost(hostEvent);
340 }
341 break;
342 default:
343 log.error("Unknown topology event {}",
344 event.eventType());
345 }
346 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700347 } finally {
348 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700349 // Topology modifications completed: Release the lock
Ray Milkey269ffb92014-04-03 14:43:30 -0700350 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700351 topology.releaseWriteLock();
Ray Milkey269ffb92014-04-03 14:43:30 -0700352 }
Yuta HIGUCHI3aca81a2014-02-23 12:41:19 -0800353
Ray Milkey269ffb92014-04-03 14:43:30 -0700354 //
355 // Dispatch the Topology Notification Events to the applications
356 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700357 dispatchTopologyEvents();
Ray Milkey269ffb92014-04-03 14:43:30 -0700358 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800359
Ray Milkey269ffb92014-04-03 14:43:30 -0700360 /**
361 * Receive a notification that an entry is added.
362 *
363 * @param value the value for the entry.
364 */
365 @Override
366 public void entryAdded(TopologyEvent value) {
367 EventEntry<TopologyEvent> eventEntry =
368 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
369 value);
370 topologyEvents.add(eventEntry);
371 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800372
Ray Milkey269ffb92014-04-03 14:43:30 -0700373 /**
374 * Receive a notification that an entry is removed.
375 *
376 * @param value the value for the entry.
377 */
378 @Override
379 public void entryRemoved(TopologyEvent value) {
380 EventEntry<TopologyEvent> eventEntry =
381 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_REMOVE,
382 value);
383 topologyEvents.add(eventEntry);
384 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800385
Ray Milkey269ffb92014-04-03 14:43:30 -0700386 /**
387 * Receive a notification that an entry is updated.
388 *
389 * @param value the value for the entry.
390 */
391 @Override
392 public void entryUpdated(TopologyEvent value) {
393 // NOTE: The ADD and UPDATE events are processed in same way
394 entryAdded(value);
395 }
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700396
397 /**
398 * Informs the event handler that a new listener has been added,
399 * and that listener expects the first event to be a snapshot of the
400 * current topology.
401 */
402 void listenerAdded() {
403 //
404 // Generate a NO-OP event so the Event Handler processing can be
405 // triggered to generate in-order a snapshot of the current
406 // topology.
407 // TODO: This is a hack.
408 //
409 EventEntry<TopologyEvent> eventEntry = EventEntry.makeNoop();
410 topologyEvents.add(eventEntry);
411 }
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800412 }
413
414 /**
415 * Startup processing.
416 *
417 * @param datagridService the datagrid service to use.
418 */
419 void startup(IDatagridService datagridService) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700420 eventChannel = datagridService.addListener(EVENT_CHANNEL_NAME,
421 eventHandler,
422 byte[].class,
423 TopologyEvent.class);
424 eventHandler.start();
Pavlin Radoslavov721a2e02014-02-14 23:40:14 -0800425 }
426
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800427 /**
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700428 * Adds a listener for topology events.
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700429 *
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700430 * @param listener the listener to add.
431 * @param startFromSnapshot if true, and if the topology is not
432 * empty, the first event should be a snapshot of the current topology.
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700433 */
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700434 void addListener(ITopologyListener listener, boolean startFromSnapshot) {
435 if (startFromSnapshot) {
436 newTopologyListeners.addIfAbsent(listener);
437 eventHandler.listenerAdded();
438 } else {
439 topologyListeners.addIfAbsent(listener);
440 }
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700441 }
442
443 /**
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700444 * Removes a listener for topology events. The listener will no longer
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700445 * receive topology events after this call.
446 *
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700447 * @param listener the listener to remove.
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700448 */
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700449 void removeListener(ITopologyListener listener) {
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700450 topologyListeners.remove(listener);
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700451 newTopologyListeners.remove(listener);
452 }
453
454 /**
455 * Processes pending (new) listeners.
456 * <p>
457 * During the processing, we dispatch Topology Snapshot Events to new
458 * listeners.
459 */
460 private void processPendingListeners() {
461 if (newTopologyListeners.isEmpty()) {
462 return;
463 }
464
465 //
466 // Create the Topology Snapshot Event
467 //
468 TopologyEvents events = null;
469 List<MastershipEvent> mastershipEvents =
470 new ArrayList<>(lastAddMastershipEvents.values());
471 List<SwitchEvent> switchEvents =
472 new ArrayList<>(topology.getAllSwitchEvents());
473 List<PortEvent> portEvents =
474 new ArrayList<>(topology.getAllPortEvents());
475 List<LinkEvent> linkEvents =
476 new ArrayList<>(topology.getAllLinkEvents());
477 List<HostEvent> hostEvents =
478 new ArrayList<>(topology.getAllHostEvents());
479 if (!(mastershipEvents.isEmpty() &&
480 switchEvents.isEmpty() &&
481 portEvents.isEmpty() &&
482 linkEvents.isEmpty() &&
483 hostEvents.isEmpty())) {
484 events = new TopologyEvents(mastershipEvents,
485 switchEvents,
486 portEvents,
487 linkEvents,
488 hostEvents);
489 }
490
491 //
492 // Dispatch Snapshot Event to each new listener, and keep track
493 // of each processed listener.
494 //
495 // NOTE: We deliver the event only if it is not empty.
496 // NOTE: We need to execute the loop so we can properly
497 // move the new listeners together with the older listeners.
498 //
499 List<ITopologyListener> processedListeners = new LinkedList<>();
500 for (ITopologyListener listener : newTopologyListeners) {
501 processedListeners.add(listener);
502 // Move the new listener together with the rest of the listeners
503 topologyListeners.addIfAbsent(listener);
504
505 // Dispatch the event
506 if (events != null) {
507 listener.topologyEvents(events);
508 }
509 }
510 newTopologyListeners.removeAll(processedListeners);
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700511 }
512
513 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -0700514 * Dispatch Topology Events to the listeners.
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800515 */
Jonathan Harte37e4e22014-05-13 19:12:02 -0700516 private void dispatchTopologyEvents() {
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700517 if (apiAddedMastershipEvents.isEmpty() &&
518 apiRemovedMastershipEvents.isEmpty() &&
519 apiAddedSwitchEvents.isEmpty() &&
Ray Milkey269ffb92014-04-03 14:43:30 -0700520 apiRemovedSwitchEvents.isEmpty() &&
521 apiAddedPortEvents.isEmpty() &&
522 apiRemovedPortEvents.isEmpty() &&
523 apiAddedLinkEvents.isEmpty() &&
524 apiRemovedLinkEvents.isEmpty() &&
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700525 apiAddedHostEvents.isEmpty() &&
526 apiRemovedHostEvents.isEmpty()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700527 return; // No events to dispatch
528 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800529
Ray Milkey269ffb92014-04-03 14:43:30 -0700530 if (log.isDebugEnabled()) {
531 //
532 // Debug statements
533 // TODO: Those statements should be removed in the future
534 //
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700535 for (MastershipEvent mastershipEvent : apiAddedMastershipEvents) {
536 log.debug("Dispatch Topology Event: ADDED {}",
537 mastershipEvent);
538 }
539 for (MastershipEvent mastershipEvent : apiRemovedMastershipEvents) {
540 log.debug("Dispatch Topology Event: REMOVED {}",
541 mastershipEvent);
542 }
Ray Milkeyb29e6262014-04-09 16:02:14 -0700543 for (SwitchEvent switchEvent : apiAddedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700544 log.debug("Dispatch Topology Event: ADDED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700545 }
546 for (SwitchEvent switchEvent : apiRemovedSwitchEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700547 log.debug("Dispatch Topology Event: REMOVED {}", switchEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700548 }
549 for (PortEvent portEvent : apiAddedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700550 log.debug("Dispatch Topology Event: ADDED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700551 }
552 for (PortEvent portEvent : apiRemovedPortEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700553 log.debug("Dispatch Topology Event: REMOVED {}", portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700554 }
555 for (LinkEvent linkEvent : apiAddedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700556 log.debug("Dispatch Topology Event: ADDED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700557 }
558 for (LinkEvent linkEvent : apiRemovedLinkEvents) {
Jonathan Harte37e4e22014-05-13 19:12:02 -0700559 log.debug("Dispatch Topology Event: REMOVED {}", linkEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700560 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700561 for (HostEvent hostEvent : apiAddedHostEvents) {
562 log.debug("Dispatch Topology Event: ADDED {}", hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700563 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700564 for (HostEvent hostEvent : apiRemovedHostEvents) {
565 log.debug("Dispatch Topology Event: REMOVED {}", hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700566 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700567 }
adminbc181552014-02-21 18:36:42 -0800568
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700569 //
570 // Update the metrics
571 //
572 long totalEvents =
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700573 apiAddedMastershipEvents.size() + apiRemovedMastershipEvents.size() +
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700574 apiAddedSwitchEvents.size() + apiRemovedSwitchEvents.size() +
575 apiAddedPortEvents.size() + apiRemovedPortEvents.size() +
576 apiAddedLinkEvents.size() + apiRemovedLinkEvents.size() +
577 apiAddedHostEvents.size() + apiRemovedHostEvents.size();
578 this.listenerEventRate.mark(totalEvents);
Pavlin Radoslavovc49917c2014-07-23 12:16:29 -0700579 this.lastEventTimestampEpochMs = System.currentTimeMillis();
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700580
581 //
Pavlin Radoslavov054cd592014-08-07 20:57:16 -0700582 // Allocate the events to deliver.
583 //
584 // TODO: We could avoid the extra list allocation and copy
585 // by using directly the original list. However, during
586 // the cleanup below, we should create new LinkedList objects
587 // instead of using clear()
588 //
589 TopologyEvents events = new TopologyEvents(
590 new ArrayList<>(apiAddedMastershipEvents),
591 new ArrayList<>(apiRemovedMastershipEvents),
592 new ArrayList<>(apiAddedSwitchEvents),
593 new ArrayList<>(apiRemovedSwitchEvents),
594 new ArrayList<>(apiAddedPortEvents),
595 new ArrayList<>(apiRemovedPortEvents),
596 new ArrayList<>(apiAddedLinkEvents),
597 new ArrayList<>(apiRemovedLinkEvents),
598 new ArrayList<>(apiAddedHostEvents),
599 new ArrayList<>(apiRemovedHostEvents));
600
601 //
Ray Milkey269ffb92014-04-03 14:43:30 -0700602 // Deliver the events
Pavlin Radoslavovd4f40372014-07-18 16:58:40 -0700603 //
Jonathan Harte37e4e22014-05-13 19:12:02 -0700604 for (ITopologyListener listener : this.topologyListeners) {
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700605 listener.topologyEvents(events);
Ray Milkey269ffb92014-04-03 14:43:30 -0700606 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800607
Ray Milkey269ffb92014-04-03 14:43:30 -0700608 //
609 // Cleanup
610 //
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700611 apiAddedMastershipEvents.clear();
612 apiRemovedMastershipEvents.clear();
Ray Milkey269ffb92014-04-03 14:43:30 -0700613 apiAddedSwitchEvents.clear();
614 apiRemovedSwitchEvents.clear();
615 apiAddedPortEvents.clear();
616 apiRemovedPortEvents.clear();
617 apiAddedLinkEvents.clear();
618 apiRemovedLinkEvents.clear();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700619 apiAddedHostEvents.clear();
620 apiRemovedHostEvents.clear();
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -0800621 }
622
623 /**
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700624 * Mastership updated event.
625 *
626 * @param mastershipEvent the mastership event.
627 */
628 @Override
629 public void putSwitchMastershipEvent(MastershipEvent mastershipEvent) {
630 // Send out notification
631 TopologyEvent topologyEvent =
632 new TopologyEvent(mastershipEvent,
633 registryService.getOnosInstanceId());
634 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
635 }
636
637 /**
638 * Mastership removed event.
639 *
640 * @param mastershipEvent the mastership event.
641 */
642 @Override
643 public void removeSwitchMastershipEvent(MastershipEvent mastershipEvent) {
644 // Send out notification
Pavlin Radoslavovbb17de22014-08-06 15:34:37 -0700645 TopologyEvent topologyEvent =
646 new TopologyEvent(mastershipEvent,
647 registryService.getOnosInstanceId());
648 eventChannel.removeEntry(topologyEvent.getID());
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700649 }
650
651 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800652 * Switch discovered event.
653 *
654 * @param switchEvent the switch event.
Ray Milkey269ffb92014-04-03 14:43:30 -0700655 * @param portEvents the corresponding port events for the switch.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800656 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800657 @Override
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800658 public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
Ray Milkey269ffb92014-04-03 14:43:30 -0700659 Collection<PortEvent> portEvents) {
660 if (datastore.addSwitch(switchEvent, portEvents)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700661 log.debug("Sending add switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700662 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700663 TopologyEvent topologyEvent =
664 new TopologyEvent(switchEvent,
665 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700666 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800667
Ray Milkey269ffb92014-04-03 14:43:30 -0700668 // Send out notification for each port
669 for (PortEvent portEvent : portEvents) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700670 log.debug("Sending add port: {}", portEvent);
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700671 topologyEvent =
672 new TopologyEvent(portEvent,
673 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700674 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
675 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800676
Ray Milkey269ffb92014-04-03 14:43:30 -0700677 //
678 // Keep track of the added ports
679 //
680 // Get the old Port Events
681 Map<ByteBuffer, PortEvent> oldPortEvents =
682 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700683 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700684 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700685 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800686
Ray Milkey269ffb92014-04-03 14:43:30 -0700687 // Store the new Port Events in the local cache
688 Map<ByteBuffer, PortEvent> newPortEvents = new HashMap<>();
689 for (PortEvent portEvent : portEvents) {
690 ByteBuffer id = portEvent.getIDasByteBuffer();
691 newPortEvents.put(id, portEvent);
692 }
693 discoveredAddedPortEvents.put(switchEvent.getDpid(),
694 newPortEvents);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800695
Ray Milkey269ffb92014-04-03 14:43:30 -0700696 //
697 // Extract the removed ports
698 //
699 List<PortEvent> removedPortEvents = new LinkedList<>();
700 for (Map.Entry<ByteBuffer, PortEvent> entry : oldPortEvents.entrySet()) {
701 ByteBuffer key = entry.getKey();
702 PortEvent portEvent = entry.getValue();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700703 if (!newPortEvents.containsKey(key)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700704 removedPortEvents.add(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700705 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700706 }
707
708 // Cleanup old removed ports
Ray Milkeyb29e6262014-04-09 16:02:14 -0700709 for (PortEvent portEvent : removedPortEvents) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700710 removePortDiscoveryEvent(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700711 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700712 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800713 }
714
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800715 /**
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -0700716 * {@inheritDoc}
717 * <p/>
718 * Called by {@link TopologyPublisher.SwitchCleanup} thread.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800719 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800720 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800721 public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
Pavlin Radoslavovbb17de22014-08-06 15:34:37 -0700722 TopologyEvent topologyEvent;
723
Ray Milkey269ffb92014-04-03 14:43:30 -0700724 // Get the old Port Events
725 Map<ByteBuffer, PortEvent> oldPortEvents =
726 discoveredAddedPortEvents.get(switchEvent.getDpid());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700727 if (oldPortEvents == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700728 oldPortEvents = new HashMap<>();
Ray Milkeyb29e6262014-04-09 16:02:14 -0700729 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800730
Ray Milkey269ffb92014-04-03 14:43:30 -0700731 if (datastore.deactivateSwitch(switchEvent, oldPortEvents.values())) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700732 log.debug("Sending remove switch: {}", switchEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700733 // Send out notification
Pavlin Radoslavovbb17de22014-08-06 15:34:37 -0700734 topologyEvent =
735 new TopologyEvent(switchEvent,
736 registryService.getOnosInstanceId());
737 eventChannel.removeEntry(topologyEvent.getID());
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800738
Ray Milkey269ffb92014-04-03 14:43:30 -0700739 //
740 // Send out notification for each port.
741 //
742 // NOTE: We don't use removePortDiscoveryEvent() for the cleanup,
743 // because it will attempt to remove the port from the database,
744 // and the deactiveSwitch() call above already removed all ports.
745 //
Ray Milkeyb29e6262014-04-09 16:02:14 -0700746 for (PortEvent portEvent : oldPortEvents.values()) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700747 log.debug("Sending remove port:", portEvent);
Pavlin Radoslavovbb17de22014-08-06 15:34:37 -0700748 topologyEvent =
749 new TopologyEvent(portEvent,
750 registryService.getOnosInstanceId());
751 eventChannel.removeEntry(topologyEvent.getID());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700752 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700753 discoveredAddedPortEvents.remove(switchEvent.getDpid());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800754
Ray Milkey269ffb92014-04-03 14:43:30 -0700755 // Cleanup for each link
756 Map<ByteBuffer, LinkEvent> oldLinkEvents =
757 discoveredAddedLinkEvents.get(switchEvent.getDpid());
758 if (oldLinkEvents != null) {
759 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
760 removeLinkDiscoveryEvent(linkEvent);
761 }
762 discoveredAddedLinkEvents.remove(switchEvent.getDpid());
763 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800764
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700765 // Cleanup for each host
766 Map<ByteBuffer, HostEvent> oldHostEvents =
767 discoveredAddedHostEvents.get(switchEvent.getDpid());
768 if (oldHostEvents != null) {
769 for (HostEvent hostEvent : new ArrayList<>(oldHostEvents.values())) {
770 removeHostDiscoveryEvent(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700771 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700772 discoveredAddedHostEvents.remove(switchEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -0700773 }
774 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800775 }
776
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800777 /**
778 * Port discovered event.
779 *
780 * @param portEvent the port event.
781 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800782 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800783 public void putPortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700784 if (datastore.addPort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700785 log.debug("Sending add port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700786 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700787 TopologyEvent topologyEvent =
788 new TopologyEvent(portEvent,
789 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700790 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800791
Ray Milkey269ffb92014-04-03 14:43:30 -0700792 // Store the new Port Event in the local cache
793 Map<ByteBuffer, PortEvent> oldPortEvents =
794 discoveredAddedPortEvents.get(portEvent.getDpid());
795 if (oldPortEvents == null) {
796 oldPortEvents = new HashMap<>();
797 discoveredAddedPortEvents.put(portEvent.getDpid(),
798 oldPortEvents);
799 }
800 ByteBuffer id = portEvent.getIDasByteBuffer();
801 oldPortEvents.put(id, portEvent);
802 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800803 }
804
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800805 /**
806 * Port removed event.
807 *
808 * @param portEvent the port event.
809 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800810 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800811 public void removePortDiscoveryEvent(PortEvent portEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700812 if (datastore.deactivatePort(portEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700813 log.debug("Sending remove port: {}", portEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700814 // Send out notification
Pavlin Radoslavovbb17de22014-08-06 15:34:37 -0700815 TopologyEvent topologyEvent =
816 new TopologyEvent(portEvent,
817 registryService.getOnosInstanceId());
818 eventChannel.removeEntry(topologyEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800819
Ray Milkey269ffb92014-04-03 14:43:30 -0700820 // Cleanup the Port Event from the local cache
821 Map<ByteBuffer, PortEvent> oldPortEvents =
822 discoveredAddedPortEvents.get(portEvent.getDpid());
823 if (oldPortEvents != null) {
824 ByteBuffer id = portEvent.getIDasByteBuffer();
825 oldPortEvents.remove(id);
826 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800827
Ray Milkey269ffb92014-04-03 14:43:30 -0700828 // Cleanup for the incoming link
829 Map<ByteBuffer, LinkEvent> oldLinkEvents =
830 discoveredAddedLinkEvents.get(portEvent.getDpid());
831 if (oldLinkEvents != null) {
832 for (LinkEvent linkEvent : new ArrayList<>(oldLinkEvents.values())) {
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700833 if (linkEvent.getDst().equals(portEvent.getSwitchPort())) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700834 removeLinkDiscoveryEvent(linkEvent);
835 // XXX If we change our model to allow multiple Link on
836 // a Port, this loop must be fixed to allow continuing.
837 break;
838 }
839 }
840 }
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800841
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700842 // Cleanup for the connected hosts
Ray Milkey269ffb92014-04-03 14:43:30 -0700843 // TODO: The implementation below is probably wrong
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700844 List<HostEvent> removedHostEvents = new LinkedList<>();
845 Map<ByteBuffer, HostEvent> oldHostEvents =
846 discoveredAddedHostEvents.get(portEvent.getDpid());
847 if (oldHostEvents != null) {
848 for (HostEvent hostEvent : new ArrayList<>(oldHostEvents.values())) {
849 for (SwitchPort swp : hostEvent.getAttachmentPoints()) {
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700850 if (swp.equals(portEvent.getSwitchPort())) {
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700851 removedHostEvents.add(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700852 }
853 }
854 }
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700855 for (HostEvent hostEvent : removedHostEvents) {
856 removeHostDiscoveryEvent(hostEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700857 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700858 }
859 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800860 }
861
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800862 /**
863 * Link discovered event.
864 *
865 * @param linkEvent the link event.
866 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800867 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800868 public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700869 if (datastore.addLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700870 log.debug("Sending add link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700871 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700872 TopologyEvent topologyEvent =
873 new TopologyEvent(linkEvent,
874 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700875 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800876
Ray Milkey269ffb92014-04-03 14:43:30 -0700877 // Store the new Link Event in the local cache
878 Map<ByteBuffer, LinkEvent> oldLinkEvents =
879 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
880 if (oldLinkEvents == null) {
881 oldLinkEvents = new HashMap<>();
882 discoveredAddedLinkEvents.put(linkEvent.getDst().getDpid(),
883 oldLinkEvents);
884 }
885 ByteBuffer id = linkEvent.getIDasByteBuffer();
886 oldLinkEvents.put(id, linkEvent);
887 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800888 }
889
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800890 /**
891 * Link removed event.
892 *
893 * @param linkEvent the link event.
894 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800895 @Override
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800896 public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700897 if (datastore.removeLink(linkEvent)) {
Jonathan Hart92c819f2014-05-30 10:53:30 -0700898 log.debug("Sending remove link: {}", linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700899 // Send out notification
Pavlin Radoslavovbb17de22014-08-06 15:34:37 -0700900 TopologyEvent topologyEvent =
901 new TopologyEvent(linkEvent,
902 registryService.getOnosInstanceId());
903 eventChannel.removeEntry(topologyEvent.getID());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800904
Ray Milkey269ffb92014-04-03 14:43:30 -0700905 // Cleanup the Link Event from the local cache
906 Map<ByteBuffer, LinkEvent> oldLinkEvents =
907 discoveredAddedLinkEvents.get(linkEvent.getDst().getDpid());
908 if (oldLinkEvents != null) {
909 ByteBuffer id = linkEvent.getIDasByteBuffer();
910 oldLinkEvents.remove(id);
911 }
912 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800913 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800914
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800915 /**
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700916 * Host discovered event.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800917 *
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700918 * @param hostEvent the host event.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800919 */
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800920 @Override
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700921 public void putHostDiscoveryEvent(HostEvent hostEvent) {
922 if (datastore.addHost(hostEvent)) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700923 // Send out notification
Pavlin Radoslavova5637c02014-07-30 15:55:11 -0700924 TopologyEvent topologyEvent =
925 new TopologyEvent(hostEvent,
926 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -0700927 eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700928 log.debug("Put the host info into the cache of the topology. mac {}",
929 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
Pavlin Radoslavovbb17de22014-08-06 15:34:37 -0700956 TopologyEvent topologyEvent =
957 new TopologyEvent(hostEvent,
958 registryService.getOnosInstanceId());
959 eventChannel.removeEntry(topologyEvent.getID());
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700960 log.debug("Remove the host info into the cache of the topology. mac {}",
961 hostEvent.getMac());
Pavlin Radoslavov26d83402014-02-20 15:24:30 -0800962
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700963 // Cleanup the Host Event from the local cache
Ray Milkey269ffb92014-04-03 14:43:30 -0700964 // TODO: The implementation below is probably wrong
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700965 ByteBuffer id = ByteBuffer.wrap(hostEvent.getID());
966 for (SwitchPort swp : hostEvent.getAttachmentPoints()) {
967 Map<ByteBuffer, HostEvent> oldHostEvents =
968 discoveredAddedHostEvents.get(swp.getDpid());
969 if (oldHostEvents != null) {
970 oldHostEvents.remove(id);
Ray Milkey269ffb92014-04-03 14:43:30 -0700971 }
972 }
973 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -0800974 }
Jonathan Hart22eb9882014-02-11 15:52:59 -0800975
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -0700976 //
977 // Methods to update topology replica
978 //
979
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -0800980 /**
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700981 * Adds Switch Mastership event.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700982 *
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700983 * @param mastershipEvent the MastershipEvent to process.
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700984 * @return true if the item was successfully added, otherwise false.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700985 */
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700986 @GuardedBy("topology.writeLock")
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700987 private boolean addMastershipEvent(MastershipEvent mastershipEvent) {
988 log.debug("Added Mastership event {}", mastershipEvent);
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -0700989 lastAddMastershipEvents.put(mastershipEvent.getIDasByteBuffer(),
990 mastershipEvent);
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700991 apiAddedMastershipEvents.add(mastershipEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700992 return true;
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700993 }
994
995 /**
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -0700996 * Removes Switch Mastership event.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700997 *
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -0700998 * @param mastershipEvent the MastershipEvent to process.
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700999 */
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -07001000 @GuardedBy("topology.writeLock")
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001001 private void removeMastershipEvent(MastershipEvent mastershipEvent) {
1002 log.debug("Removed Mastership event {}", mastershipEvent);
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -07001003 lastAddMastershipEvents.remove(mastershipEvent.getIDasByteBuffer());
Pavlin Radoslavovcac157d2014-07-31 13:54:08 -07001004 apiRemovedMastershipEvents.add(mastershipEvent);
Pavlin Radoslavov695f8952014-07-23 16:57:01 -07001005 }
1006
1007 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001008 * Adds a switch to the topology replica.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001009 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001010 * @param switchEvent the SwitchEvent with the switch to add.
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001011 * @return true if the item was successfully added, otherwise false.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001012 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001013 @GuardedBy("topology.writeLock")
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001014 private boolean addSwitch(SwitchEvent switchEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001015 if (log.isDebugEnabled()) {
1016 SwitchEvent sw = topology.getSwitchEvent(switchEvent.getDpid());
1017 if (sw != null) {
1018 log.debug("Update {}", switchEvent);
1019 } else {
1020 log.debug("Added {}", switchEvent);
1021 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001022 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001023 topology.putSwitch(switchEvent.freeze());
Ray Milkey269ffb92014-04-03 14:43:30 -07001024 apiAddedSwitchEvents.add(switchEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001025 return true;
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001026 }
1027
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001028 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001029 * Removes a switch from the topology replica.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001030 * <p/>
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001031 * It will call {@link #removePort(PortEvent)} for each ports on this
1032 * switch.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001033 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001034 * @param switchEvent the SwitchEvent with the switch to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001035 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001036 @GuardedBy("topology.writeLock")
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001037 private void removeSwitch(SwitchEvent switchEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001038 final Dpid dpid = switchEvent.getDpid();
1039
1040 SwitchEvent swInTopo = topology.getSwitchEvent(dpid);
1041 if (swInTopo == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001042 log.warn("Switch {} already removed, ignoring", switchEvent);
1043 return;
1044 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001045
Ray Milkey269ffb92014-04-03 14:43:30 -07001046 //
1047 // Remove all Ports on the Switch
1048 //
1049 ArrayList<PortEvent> portsToRemove = new ArrayList<>();
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001050 for (Port port : topology.getPorts(dpid)) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001051 log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now.",
1052 port, switchEvent);
Yuta HIGUCHIcd14dda2014-07-24 09:57:22 -07001053 PortEvent portEvent = new PortEvent(port.getSwitchPort());
Ray Milkey269ffb92014-04-03 14:43:30 -07001054 portsToRemove.add(portEvent);
1055 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001056 for (PortEvent portEvent : portsToRemove) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001057 removePort(portEvent);
Ray Milkeyb29e6262014-04-09 16:02:14 -07001058 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001059
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001060 log.debug("Removed {}", swInTopo);
1061 topology.removeSwitch(dpid);
1062 apiRemovedSwitchEvents.add(swInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001063 }
1064
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001065 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001066 * Adds a port to the topology replica.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001067 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001068 * @param portEvent the PortEvent with the port to add.
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001069 * @return true if the item was successfully added, otherwise false.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001070 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001071 @GuardedBy("topology.writeLock")
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001072 private boolean addPort(PortEvent portEvent) {
Jonathan Harte37e4e22014-05-13 19:12:02 -07001073 Switch sw = topology.getSwitch(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -07001074 if (sw == null) {
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001075 // Reordered event
Jonathan Hartf1675202014-05-23 14:59:07 -07001076 log.debug("{} reordered because switch is null", portEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001077 return false;
Ray Milkey269ffb92014-04-03 14:43:30 -07001078 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001079
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001080 if (log.isDebugEnabled()) {
1081 PortEvent port = topology.getPortEvent(portEvent.getSwitchPort());
1082 if (port != null) {
1083 log.debug("Update {}", portEvent);
1084 } else {
1085 log.debug("Added {}", portEvent);
1086 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001087 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001088 topology.putPort(portEvent.freeze());
Ray Milkey269ffb92014-04-03 14:43:30 -07001089 apiAddedPortEvents.add(portEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001090 return true;
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001091 }
1092
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001093 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001094 * Removes a port from the topology replica.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001095 * <p/>
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001096 * It will remove attachment points from each hosts on this port
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001097 * and call {@link #removeLink(LinkEvent)} for each links on this port.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001098 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001099 * @param portEvent the PortEvent with the port to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001100 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001101 @GuardedBy("topology.writeLock")
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001102 private void removePort(PortEvent portEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001103 SwitchEvent sw = topology.getSwitchEvent(portEvent.getDpid());
Ray Milkey269ffb92014-04-03 14:43:30 -07001104 if (sw == null) {
1105 log.warn("Parent Switch for Port {} already removed, ignoring",
1106 portEvent);
1107 return;
1108 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001109
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001110 final SwitchPort switchPort = portEvent.getSwitchPort();
1111 PortEvent portInTopo = topology.getPortEvent(switchPort);
1112 if (portInTopo == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001113 log.warn("Port {} already removed, ignoring", portEvent);
1114 return;
1115 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001116
Ray Milkey269ffb92014-04-03 14:43:30 -07001117 //
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001118 // Remove all Host attachment points bound to this Port
Ray Milkey269ffb92014-04-03 14:43:30 -07001119 //
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001120 List<HostEvent> hostsToUpdate = new ArrayList<>();
1121 for (Host host : topology.getHosts(switchPort)) {
1122 log.debug("Removing Host {} on Port {}", host, portInTopo);
1123 HostEvent hostEvent = topology.getHostEvent(host.getMacAddress());
1124 hostsToUpdate.add(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001125 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001126 for (HostEvent hostEvent : hostsToUpdate) {
1127 HostEvent newHostEvent = new HostEvent(hostEvent);
1128 newHostEvent.removeAttachmentPoint(switchPort);
1129 newHostEvent.freeze();
1130
1131 // TODO should this event be fired inside #addHost?
1132 if (newHostEvent.getAttachmentPoints().isEmpty()) {
1133 // No more attachment point left -> remove Host
1134 removeHost(hostEvent);
1135 } else {
1136 // Update Host
1137 addHost(newHostEvent);
1138 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001139 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001140
Ray Milkey269ffb92014-04-03 14:43:30 -07001141 //
1142 // Remove all Links connected to the Port
1143 //
1144 Set<Link> links = new HashSet<>();
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001145 links.addAll(topology.getOutgoingLinks(switchPort));
1146 links.addAll(topology.getIncomingLinks(switchPort));
Ray Milkey269ffb92014-04-03 14:43:30 -07001147 for (Link link : links) {
Ray Milkeyb29e6262014-04-09 16:02:14 -07001148 if (link == null) {
Ray Milkey269ffb92014-04-03 14:43:30 -07001149 continue;
Ray Milkeyb29e6262014-04-09 16:02:14 -07001150 }
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001151 LinkEvent linkEvent = topology.getLinkEvent(link.getLinkTuple());
1152 if (linkEvent != null) {
1153 log.debug("Removing Link {} on Port {}", link, portInTopo);
1154 removeLink(linkEvent);
1155 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001156 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001157
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001158 // Remove the Port from Topology
1159 log.debug("Removed {}", portInTopo);
1160 topology.removePort(switchPort);
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001161
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001162 apiRemovedPortEvents.add(portInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001163 }
1164
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001165 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001166 * Adds a link to the topology replica.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001167 * <p/>
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001168 * It will remove attachment points from each hosts using the same ports.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001169 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001170 * @param linkEvent the LinkEvent with the link to add.
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001171 * @return true if the item was successfully added, otherwise false.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001172 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001173 @GuardedBy("topology.writeLock")
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001174 private boolean addLink(LinkEvent linkEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001175 PortEvent srcPort = topology.getPortEvent(linkEvent.getSrc());
1176 PortEvent dstPort = topology.getPortEvent(linkEvent.getDst());
Ray Milkey269ffb92014-04-03 14:43:30 -07001177 if ((srcPort == null) || (dstPort == null)) {
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001178 // Reordered event
Jonathan Hartf1675202014-05-23 14:59:07 -07001179 log.debug("{} reordered because {} port is null", linkEvent,
1180 (srcPort == null) ? "src" : "dst");
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001181 return false;
Ray Milkey269ffb92014-04-03 14:43:30 -07001182 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001183
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001184 //
1185 // XXX domain knowledge: Sanity check: Port cannot have both Link and
1186 // Host.
1187 //
1188 // FIXME: Potentially local replica may not be up-to-date yet due to
1189 // Hazelcast delay.
1190 // FIXME: May need to manage local truth and use them instead.
1191 //
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001192 if (topology.getLinkEvent(linkEvent.getLinkTuple()) == null) {
1193 // Only check for existing Host when adding new Link.
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001194 // Remove all Hosts attached to the ports on both ends
1195
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001196 Set<HostEvent> hostsToUpdate =
1197 new TreeSet<>(new Comparator<HostEvent>() {
1198 // Comparison only using ID(=MAC)
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001199 @Override
1200 public int compare(HostEvent o1, HostEvent o2) {
1201 return Long.compare(o1.getMac().toLong(), o2.getMac().toLong());
1202 }
1203 });
1204
1205 List<SwitchPort> portsToCheck = Arrays.asList(
1206 srcPort.getSwitchPort(),
1207 dstPort.getSwitchPort());
1208
1209 // Enumerate Host which needs to be updated by this Link add event
1210 for (SwitchPort port : portsToCheck) {
1211 for (Host host : topology.getHosts(port)) {
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001212 log.error("Host {} on Port {} should have been removed prior to adding Link {}",
1213 host, port, linkEvent);
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001214
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -07001215 HostEvent hostEvent =
1216 topology.getHostEvent(host.getMacAddress());
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001217 hostsToUpdate.add(hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001218 }
1219 }
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001220 // Remove attachment point from them
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001221 for (HostEvent hostEvent : hostsToUpdate) {
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001222 // Remove port from attachment point and update
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001223 HostEvent newHostEvent = new HostEvent(hostEvent);
1224 newHostEvent.removeAttachmentPoint(srcPort.getSwitchPort());
1225 newHostEvent.removeAttachmentPoint(dstPort.getSwitchPort());
1226 newHostEvent.freeze();
1227
1228 // TODO should this event be fired inside #addHost?
1229 if (newHostEvent.getAttachmentPoints().isEmpty()) {
1230 // No more attachment point left -> remove Host
1231 removeHost(hostEvent);
1232 } else {
1233 // Update Host
1234 addHost(newHostEvent);
1235 }
Ray Milkeyb29e6262014-04-09 16:02:14 -07001236 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001237 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001238
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001239 if (log.isDebugEnabled()) {
1240 LinkEvent link = topology.getLinkEvent(linkEvent.getLinkTuple());
1241 if (link != null) {
1242 log.debug("Update {}", linkEvent);
1243 } else {
1244 log.debug("Added {}", linkEvent);
1245 }
1246 }
1247 topology.putLink(linkEvent.freeze());
Ray Milkey269ffb92014-04-03 14:43:30 -07001248 apiAddedLinkEvents.add(linkEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001249 return true;
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001250 }
1251
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001252 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -07001253 * Removes a link from the topology replica.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001254 *
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001255 * @param linkEvent the LinkEvent with the link to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001256 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001257 @GuardedBy("topology.writeLock")
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001258 private void removeLink(LinkEvent linkEvent) {
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -07001259 Port srcPort = topology.getPort(linkEvent.getSrc().getDpid(),
Yuta HIGUCHIb1e2ab72014-06-30 11:01:31 -07001260 linkEvent.getSrc().getPortNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -07001261 if (srcPort == null) {
1262 log.warn("Src Port for Link {} already removed, ignoring",
1263 linkEvent);
1264 return;
1265 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001266
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -07001267 Port dstPort = topology.getPort(linkEvent.getDst().getDpid(),
Yuta HIGUCHIb1e2ab72014-06-30 11:01:31 -07001268 linkEvent.getDst().getPortNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -07001269 if (dstPort == null) {
1270 log.warn("Dst Port for Link {} already removed, ignoring",
1271 linkEvent);
1272 return;
1273 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001274
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001275 LinkEvent linkInTopo = topology.getLinkEvent(linkEvent.getLinkTuple(),
1276 linkEvent.getType());
1277 if (linkInTopo == null) {
1278 log.warn("Link {} already removed, ignoring", linkEvent);
1279 return;
Ray Milkey269ffb92014-04-03 14:43:30 -07001280 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001281
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001282 if (log.isDebugEnabled()) {
1283 // only do sanity check on debug level
1284
1285 Link linkIn = dstPort.getIncomingLink(linkEvent.getType());
1286 if (linkIn == null) {
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -07001287 log.warn("Link {} already removed on destination Port",
1288 linkEvent);
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001289 }
1290 Link linkOut = srcPort.getOutgoingLink(linkEvent.getType());
1291 if (linkOut == null) {
1292 log.warn("Link {} already removed on src Port", linkEvent);
1293 }
Jonathan Hart25bd53e2014-04-30 23:44:09 -07001294 }
Pavlin Radoslavov74986ce2014-02-20 13:17:20 -08001295
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001296 log.debug("Removed {}", linkInTopo);
1297 topology.removeLink(linkEvent.getLinkTuple(), linkEvent.getType());
1298 apiRemovedLinkEvents.add(linkInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001299 }
1300
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001301 /**
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001302 * Adds a host to the topology replica.
Ray Milkey269ffb92014-04-03 14:43:30 -07001303 * <p/>
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001304 * TODO: Host-related work is incomplete.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001305 * TODO: Eventually, we might need to consider reordering
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001306 * or {@link #addLink(LinkEvent)} and {@link #addHost(HostEvent)} events
1307 * on the same port.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001308 *
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001309 * @param hostEvent the HostEvent with the host to add.
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001310 * @return true if the item was successfully added, otherwise false.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001311 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001312 @GuardedBy("topology.writeLock")
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001313 private boolean addHost(HostEvent hostEvent) {
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001314
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001315 // TODO Decide how to handle update scenario.
1316 // If the new HostEvent has less attachment point compared to
1317 // existing HostEvent, what should the event be?
1318 // - AddHostEvent with some attachment point removed? (current behavior)
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001319
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001320 // create unfrozen copy
1321 // for removing attachment points which already has a link
1322 HostEvent modifiedHostEvent = new HostEvent(hostEvent);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001323
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001324 // Verify each attachment point
Ray Milkey269ffb92014-04-03 14:43:30 -07001325 boolean attachmentFound = false;
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001326 for (SwitchPort swp : hostEvent.getAttachmentPoints()) {
1327 // XXX domain knowledge: Port must exist before Host
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001328 // but this knowledge cannot be pushed down to driver.
1329
Ray Milkey269ffb92014-04-03 14:43:30 -07001330 // Attached Ports must exist
Yuta HIGUCHIb1e2ab72014-06-30 11:01:31 -07001331 Port port = topology.getPort(swp.getDpid(), swp.getPortNumber());
Ray Milkey269ffb92014-04-03 14:43:30 -07001332 if (port == null) {
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -07001333 log.debug("{} reordered because port {} was not there",
1334 hostEvent, swp);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001335 // Reordered event
1336 return false; // should not continue if re-applying later
Ray Milkey269ffb92014-04-03 14:43:30 -07001337 }
1338 // Attached Ports must not have Link
1339 if (port.getOutgoingLink() != null ||
1340 port.getIncomingLink() != null) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001341 log.warn("Link (Out:{},In:{}) exist on the attachment point. "
1342 + "Ignoring this attachmentpoint ({}) from {}.",
1343 port.getOutgoingLink(), port.getIncomingLink(),
1344 swp, modifiedHostEvent);
1345 // FIXME Should either reject, reorder this HostEvent,
1346 // or remove attachment point from given HostEvent
1347 // Removing attachment point from given HostEvent for now.
1348 modifiedHostEvent.removeAttachmentPoint(swp);
Ray Milkey269ffb92014-04-03 14:43:30 -07001349 continue;
1350 }
1351
Ray Milkey269ffb92014-04-03 14:43:30 -07001352 attachmentFound = true;
1353 }
1354
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001355 // Update the host in the topology
Ray Milkey269ffb92014-04-03 14:43:30 -07001356 if (attachmentFound) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001357 if (modifiedHostEvent.getAttachmentPoints().isEmpty()) {
1358 log.warn("No valid attachment point left. Ignoring."
Pavlin Radoslavov8a44b782014-08-07 12:53:27 -07001359 + "original: {}, modified: {}",
1360 hostEvent, modifiedHostEvent);
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001361 // TODO Should we call #removeHost to trigger remove event?
1362 // only if this call is update.
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001363 return false;
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001364 }
1365
1366 if (log.isDebugEnabled()) {
1367 HostEvent host = topology.getHostEvent(hostEvent.getMac());
1368 if (host != null) {
1369 log.debug("Update {}", modifiedHostEvent);
1370 } else {
1371 log.debug("Added {}", modifiedHostEvent);
1372 }
1373 }
1374 topology.putHost(modifiedHostEvent.freeze());
1375 apiAddedHostEvents.add(modifiedHostEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001376 return true;
Ray Milkey269ffb92014-04-03 14:43:30 -07001377 }
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001378 return false;
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001379 }
1380
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001381 /**
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001382 * Removes a host from the topology replica.
Ray Milkey269ffb92014-04-03 14:43:30 -07001383 * <p/>
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001384 * TODO: Host-related work is incomplete.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001385 *
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001386 * @param hostEvent the Host Event with the host to remove.
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001387 */
Yuta HIGUCHIbc67a052014-06-30 10:37:09 -07001388 @GuardedBy("topology.writeLock")
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001389 private void removeHost(HostEvent hostEvent) {
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001390
1391 final MACAddress mac = hostEvent.getMac();
1392 HostEvent hostInTopo = topology.getHostEvent(mac);
1393 if (hostInTopo == null) {
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -07001394 log.warn("Host {} already removed, ignoring", hostEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -07001395 return;
1396 }
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001397
Yuta HIGUCHI8b389a72014-07-18 13:50:00 -07001398 log.debug("Removed {}", hostInTopo);
1399 topology.removeHost(mac);
1400 apiRemovedHostEvents.add(hostInTopo);
Pavlin Radoslavov3c9cc552014-02-20 09:58:38 -08001401 }
Jonathan Hart22eb9882014-02-11 15:52:59 -08001402
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001403 /**
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001404 * Read the whole topology from the database.
1405 *
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001406 * @return a list of EventEntry-encapsulated Topology Events for
Pavlin Radoslavov734ff5a2014-02-26 10:20:43 -08001407 * the whole topology.
1408 */
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001409 private List<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
1410 List<EventEntry<TopologyEvent>> events =
Ray Milkey269ffb92014-04-03 14:43:30 -07001411 new LinkedList<EventEntry<TopologyEvent>>();
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001412
Ray Milkey269ffb92014-04-03 14:43:30 -07001413 // XXX May need to clear whole topology first, depending on
1414 // how we initially subscribe to replication events
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001415
Ray Milkey269ffb92014-04-03 14:43:30 -07001416 // Add all active switches
1417 for (KVSwitch sw : KVSwitch.getAllSwitches()) {
1418 if (sw.getStatus() != KVSwitch.STATUS.ACTIVE) {
1419 continue;
1420 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001421
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001422 //
1423 // TODO: Using the local ONOS Instance ID below is incorrect.
1424 // Currently, this code is not used, and it might go away in the
1425 // future.
1426 //
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -07001427 SwitchEvent switchEvent = new SwitchEvent(new Dpid(sw.getDpid()));
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001428 TopologyEvent topologyEvent =
1429 new TopologyEvent(switchEvent,
1430 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -07001431 EventEntry<TopologyEvent> eventEntry =
1432 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1433 topologyEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001434 events.add(eventEntry);
Ray Milkey269ffb92014-04-03 14:43:30 -07001435 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001436
Ray Milkey269ffb92014-04-03 14:43:30 -07001437 // Add all active ports
1438 for (KVPort p : KVPort.getAllPorts()) {
1439 if (p.getStatus() != KVPort.STATUS.ACTIVE) {
1440 continue;
1441 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001442
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001443 //
1444 // TODO: Using the local ONOS Instance ID below is incorrect.
1445 // Currently, this code is not used, and it might go away in the
1446 // future.
1447 //
1448 PortEvent portEvent =
1449 new PortEvent(new Dpid(p.getDpid()),
1450 new PortNumber(p.getNumber().shortValue()));
1451 TopologyEvent topologyEvent =
1452 new TopologyEvent(portEvent,
1453 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -07001454 EventEntry<TopologyEvent> eventEntry =
1455 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1456 topologyEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001457 events.add(eventEntry);
Ray Milkey269ffb92014-04-03 14:43:30 -07001458 }
Yuta HIGUCHIa536e762014-02-17 21:47:28 -08001459
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001460 for (KVDevice d : KVDevice.getAllDevices()) {
1461 //
1462 // TODO: Using the local ONOS Instance ID below is incorrect.
1463 // Currently, this code is not used, and it might go away in the
1464 // future.
1465 //
1466 HostEvent devEvent = new HostEvent(MACAddress.valueOf(d.getMac()));
1467 for (byte[] portId : d.getAllPortIds()) {
1468 devEvent.addAttachmentPoint(
1469 new SwitchPort(KVPort.getDpidFromKey(portId),
1470 KVPort.getNumberFromKey(portId)));
1471 }
1472 }
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001473
Ray Milkey269ffb92014-04-03 14:43:30 -07001474 for (KVLink l : KVLink.getAllLinks()) {
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001475 //
1476 // TODO: Using the local ONOS Instance ID below is incorrect.
1477 // Currently, this code is not used, and it might go away in the
1478 // future.
1479 //
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -07001480 LinkEvent linkEvent = new LinkEvent(
Pavlin Radoslavova5637c02014-07-30 15:55:11 -07001481 new SwitchPort(l.getSrc().dpid, l.getSrc().number),
1482 new SwitchPort(l.getDst().dpid, l.getDst().number));
1483 TopologyEvent topologyEvent =
1484 new TopologyEvent(linkEvent,
1485 registryService.getOnosInstanceId());
Ray Milkey269ffb92014-04-03 14:43:30 -07001486 EventEntry<TopologyEvent> eventEntry =
1487 new EventEntry<TopologyEvent>(EventEntry.Type.ENTRY_ADD,
1488 topologyEvent);
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001489 events.add(eventEntry);
Ray Milkey269ffb92014-04-03 14:43:30 -07001490 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -08001491
Pavlin Radoslavovd7b792e2014-08-01 02:47:47 -07001492 return events;
Pavlin Radoslavovc1cfde52014-02-19 11:35:29 -08001493 }
Jonathan Hart062a2e82014-02-03 09:41:57 -08001494}