blob: 8b777454ce1733e465874f819d91087f098bbc4f [file] [log] [blame]
Jonathan Hart472062d2014-04-03 10:56:48 -07001package net.onrc.onos.core.topology;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08002
3import java.util.ArrayList;
4import java.util.Collection;
Jonathan Hart369875b2014-02-13 10:00:31 -08005import java.util.List;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08006import java.util.Map;
Jonathan Hart369875b2014-02-13 10:00:31 -08007import java.util.concurrent.TimeUnit;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08008
9import net.floodlightcontroller.core.IFloodlightProviderService;
Pavlin Radoslavov695f8952014-07-23 16:57:01 -070010import net.floodlightcontroller.core.IFloodlightProviderService.Role;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080011import net.floodlightcontroller.core.IOFSwitch;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070012import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
13import net.floodlightcontroller.core.IOFSwitchListener;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080014import net.floodlightcontroller.core.module.FloodlightModuleContext;
15import net.floodlightcontroller.core.module.FloodlightModuleException;
16import net.floodlightcontroller.core.module.IFloodlightModule;
17import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart369875b2014-02-13 10:00:31 -080018import net.floodlightcontroller.core.util.SingletonTask;
19import net.floodlightcontroller.threadpool.IThreadPoolService;
Jonathan Hart03102132014-07-01 23:22:04 -070020import net.onrc.onos.core.hostmanager.Host;
21import net.onrc.onos.core.hostmanager.IHostListener;
22import net.onrc.onos.core.hostmanager.IHostService;
Jonathan Hart23701d12014-04-03 10:45:48 -070023import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryListener;
24import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
Jonathan Hart284e70f2014-07-05 12:32:51 -070025import net.onrc.onos.core.linkdiscovery.Link;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070026import net.onrc.onos.core.registry.IControllerRegistryService;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070027import net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback;
Jonathan Harta99ec672014-04-03 11:30:34 -070028import net.onrc.onos.core.registry.RegistryException;
Yuta HIGUCHI5bbbaca2014-06-09 16:39:08 -070029import net.onrc.onos.core.util.Dpid;
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -070030import net.onrc.onos.core.util.PortNumber;
Yuta HIGUCHI5c8cbeb2014-06-27 11:13:48 -070031import net.onrc.onos.core.util.SwitchPort;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080032
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070033import org.projectfloodlight.openflow.protocol.OFPortDesc;
34import org.projectfloodlight.openflow.util.HexString;
Toshio Koide2f570c12014-02-06 16:55:32 -080035import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080037
Jonathan Hart88770672014-04-02 18:08:30 -070038/**
Jonathan Harte37e4e22014-05-13 19:12:02 -070039 * The TopologyPublisher subscribes to topology network events from the
40 * discovery modules. These events are reformatted and relayed to the in-memory
41 * topology instance.
Jonathan Hart88770672014-04-02 18:08:30 -070042 */
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070043public class TopologyPublisher implements IOFSwitchListener,
Ray Milkey269ffb92014-04-03 14:43:30 -070044 ILinkDiscoveryListener,
45 IFloodlightModule,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070046 IHostListener {
Jonathan Hart88770672014-04-02 18:08:30 -070047 private static final Logger log =
Jonathan Harte37e4e22014-05-13 19:12:02 -070048 LoggerFactory.getLogger(TopologyPublisher.class);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080049
Jonathan Hart88770672014-04-02 18:08:30 -070050 private IFloodlightProviderService floodlightProvider;
51 private ILinkDiscoveryService linkDiscovery;
52 private IControllerRegistryService registryService;
Jonathan Harte37e4e22014-05-13 19:12:02 -070053 private ITopologyService topologyService;
Toshio Koide2f570c12014-02-06 16:55:32 -080054
Jonathan Hart03102132014-07-01 23:22:04 -070055 private IHostService hostService;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070056
Jonathan Harte37e4e22014-05-13 19:12:02 -070057 private Topology topology;
58 private TopologyDiscoveryInterface topologyDiscoveryInterface;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070059
Jonathan Hart88770672014-04-02 18:08:30 -070060 private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
61 private boolean cleanupEnabled = true;
62 private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
63 private SingletonTask cleanupTask;
Toshio Koide2f570c12014-02-06 16:55:32 -080064
Jonathan Hart369875b2014-02-13 10:00:31 -080065 /**
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070066 * Cleanup old switches from the topology. Old switches are those which have
67 * no controller in the registry.
Jonathan Hart369875b2014-02-13 10:00:31 -080068 */
69 private class SwitchCleanup implements ControlChangeCallback, Runnable {
70 @Override
71 public void run() {
72 String old = Thread.currentThread().getName();
73 Thread.currentThread().setName("SwitchCleanup@" + old);
Jonathan Hartb3e1b052014-04-02 16:01:12 -070074
Jonathan Hart369875b2014-02-13 10:00:31 -080075 try {
Jonathan Hart88770672014-04-02 18:08:30 -070076 if (log.isTraceEnabled()) {
77 log.trace("Running cleanup thread");
78 }
Jonathan Hart369875b2014-02-13 10:00:31 -080079 switchCleanup();
Jonathan Hart369875b2014-02-13 10:00:31 -080080 } finally {
81 cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
Jonathan Hart88770672014-04-02 18:08:30 -070082 TimeUnit.SECONDS);
Jonathan Hart369875b2014-02-13 10:00:31 -080083 Thread.currentThread().setName(old);
84 }
85 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -070086
Jonathan Hart88770672014-04-02 18:08:30 -070087 /**
88 * First half of the switch cleanup operation. This method will attempt
89 * to get control of any switch it sees without a controller via the
90 * registry.
91 */
Jonathan Hart369875b2014-02-13 10:00:31 -080092 private void switchCleanup() {
Jonathan Harte37e4e22014-05-13 19:12:02 -070093 Iterable<Switch> switches = topology.getSwitches();
Jonathan Hart369875b2014-02-13 10:00:31 -080094
Jonathan Hart88770672014-04-02 18:08:30 -070095 if (log.isTraceEnabled()) {
96 log.trace("Checking for inactive switches");
97 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070098 // For each switch check if a controller exists in controller
99 // registry
Ray Milkey269ffb92014-04-03 14:43:30 -0700100 for (Switch sw : switches) {
Praseed Balakrishnane82adc62014-08-04 10:59:24 -0700101 // FIXME How to handle case where Switch has never been
102 // registered to ZK
103 if (sw.getConfigState() == ConfigState.CONFIGURED) {
104 continue;
105 }
Jonathan Hart88770672014-04-02 18:08:30 -0700106 try {
107 String controller =
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700108 registryService.getControllerForSwitch(sw.getDpid().value());
Jonathan Hart88770672014-04-02 18:08:30 -0700109 if (controller == null) {
110 log.debug("Requesting control to set switch {} INACTIVE",
Yuta HIGUCHI8f3dfa32014-06-25 00:14:25 -0700111 sw.getDpid());
112 registryService.requestControl(sw.getDpid().value(), this);
Jonathan Hart88770672014-04-02 18:08:30 -0700113 }
114 } catch (RegistryException e) {
115 log.error("Caught RegistryException in cleanup thread", e);
116 }
117 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800118 }
119
Jonathan Hart88770672014-04-02 18:08:30 -0700120 /**
121 * Second half of the switch cleanup operation. If the registry grants
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700122 * control of a switch, we can be sure no other instance is writing this
123 * switch to the topology, so we can remove it now.
124 * <p>
125 * @param dpid the dpid of the switch we requested control for
Jonathan Hart88770672014-04-02 18:08:30 -0700126 * @param hasControl whether we got control or not
127 */
128 @Override
129 public void controlChanged(long dpid, boolean hasControl) {
130 if (hasControl) {
131 log.debug("Got control to set switch {} INACTIVE",
132 HexString.toHexString(dpid));
Jonathan Harte02cf542014-04-02 16:24:44 -0700133
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -0700134 SwitchEvent switchEvent = new SwitchEvent(new Dpid(dpid));
Jonathan Harte37e4e22014-05-13 19:12:02 -0700135 topologyDiscoveryInterface.
Jonathan Hart88770672014-04-02 18:08:30 -0700136 removeSwitchDiscoveryEvent(switchEvent);
137 registryService.releaseControl(dpid);
138 }
139 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800140 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800141
Jonathan Hart88770672014-04-02 18:08:30 -0700142 @Override
Jonathan Hart284e70f2014-07-05 12:32:51 -0700143 public void linkAdded(Link link) {
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700144 LinkEvent linkEvent = new LinkEvent(
Jonathan Hart284e70f2014-07-05 12:32:51 -0700145 new SwitchPort(link.getSrc(), link.getSrcPort()),
146 new SwitchPort(link.getDst(), link.getDstPort()));
147
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700148 // FIXME should be merging, with existing attrs, etc..
149 // TODO define attr name as constant somewhere.
150 // TODO populate appropriate attributes.
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -0700151 linkEvent.createStringAttribute(TopologyElement.TYPE,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700152 TopologyElement.TYPE_PACKET_LAYER);
Praseed Balakrishnan2aa6c0b2014-07-17 11:42:05 -0700153 linkEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
154 ConfigState.NOT_CONFIGURED.toString());
155 linkEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
156 AdminStatus.ACTIVE.toString());
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700157 linkEvent.freeze();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700158
Jonathan Hart284e70f2014-07-05 12:32:51 -0700159 if (!registryService.hasControl(link.getDst())) {
160 // Don't process or send a link event if we're not master for the
161 // destination switch
162 log.debug("Not the master for dst switch {}. Suppressed link add event {}.",
163 link.getDst(), linkEvent);
164 return;
Jonathan Hart88770672014-04-02 18:08:30 -0700165 }
Jonathan Hart284e70f2014-07-05 12:32:51 -0700166 topologyDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
167 }
168
169 @Override
170 public void linkRemoved(Link link) {
171 LinkEvent linkEvent = new LinkEvent(
172 new SwitchPort(link.getSrc(), link.getSrcPort()),
173 new SwitchPort(link.getDst(), link.getDstPort()));
174
175 // FIXME should be merging, with existing attrs, etc..
176 // TODO define attr name as constant somewhere.
177 // TODO populate appropriate attributes.
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -0700178 linkEvent.createStringAttribute(TopologyElement.TYPE,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700179 TopologyElement.TYPE_PACKET_LAYER);
Jonathan Hart284e70f2014-07-05 12:32:51 -0700180 linkEvent.freeze();
181
182 if (!registryService.hasControl(link.getDst())) {
183 // Don't process or send a link event if we're not master for the
184 // destination switch
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700185 log.debug(
186 "Not the master for dst switch {}. Suppressed link remove event {}.",
Jonathan Hart284e70f2014-07-05 12:32:51 -0700187 link.getDst(), linkEvent);
188 return;
189 }
190 topologyDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
Jonathan Hart88770672014-04-02 18:08:30 -0700191 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800192
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700193 /* *****************
194 * IOFSwitchListener
195 * *****************/
196
Jonathan Hart88770672014-04-02 18:08:30 -0700197 @Override
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700198 public void switchActivatedMaster(long swId) {
199 IOFSwitch sw = floodlightProvider.getSwitch(swId);
200 final Dpid dpid = new Dpid(swId);
201 if (sw == null) {
202 log.warn("Added switch not available {} ", dpid);
203 return;
204 }
205
206 controllerRoleChanged(dpid, Role.MASTER);
207
208 SwitchEvent switchEvent = new SwitchEvent(dpid);
209 // FIXME should be merging, with existing attrs, etc..
210 // TODO define attr name as constant somewhere.
211 // TODO populate appropriate attributes.
212 switchEvent.createStringAttribute(TopologyElement.TYPE,
213 TopologyElement.TYPE_PACKET_LAYER);
214 switchEvent.createStringAttribute("ConnectedSince",
215 sw.getConnectedSince().toString());
216 switchEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
217 ConfigState.NOT_CONFIGURED.toString());
218 switchEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
219 AdminStatus.ACTIVE.toString());
220 switchEvent.freeze();
221 // TODO Not very robust
222 if (!registryService.hasControl(swId)) {
223 log.debug("Not the master for switch {}. Suppressed switch add event {}.",
224 dpid, switchEvent);
225 return;
226 }
227 List<PortEvent> portEvents = new ArrayList<PortEvent>();
228 for (OFPortDesc port : sw.getPorts()) {
229 PortEvent portEvent = new PortEvent(dpid,
230 new PortNumber(port.getPortNo().getShortPortNumber()));
231 // FIXME should be merging, with existing attrs, etc..
232 // TODO define attr name as constant somewhere.
233 // TODO populate appropriate attributes.
234 portEvent.createStringAttribute("name", port.getName());
235 portEvent.createStringAttribute(TopologyElement.TYPE,
236 TopologyElement.TYPE_PACKET_LAYER);
237 portEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
238 ConfigState.NOT_CONFIGURED.toString());
239 portEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
240 AdminStatus.ACTIVE.toString());
241
242 portEvent.freeze();
243 portEvents.add(portEvent);
244 }
245 topologyDiscoveryInterface.putSwitchDiscoveryEvent(switchEvent, portEvents);
246
247 for (OFPortDesc port : sw.getPorts()) {
248 // Allow links to be discovered on this port now that it's
249 // in the database
250 linkDiscovery.enableDiscoveryOnPort(sw.getId(),
251 port.getPortNo().getShortPortNumber());
252 }
253 }
254
255 @Override
256 public void switchActivatedEqual(long swId) {
257 final Dpid dpid = new Dpid(swId);
258 controllerRoleChanged(dpid, Role.EQUAL);
259 }
260
261 @Override
262 public void switchMasterToEqual(long swId) {
263 final Dpid dpid = new Dpid(swId);
264 controllerRoleChanged(dpid, Role.EQUAL);
265 }
266
267 @Override
268 public void switchEqualToMaster(long swId) {
269 // for now treat as switchActivatedMaster
270 switchActivatedMaster(swId);
271 }
272
273 @Override
274 public void switchDisconnected(long swId) {
275 final Dpid dpid = new Dpid(swId);
276
277 log.debug("Local switch disconnected: dpid = {} role = {}", dpid);
278
279 Role role = Role.SLAVE; // TODO: Should be Role.UNKNOWN
280
281 MastershipEvent mastershipEvent =
282 new MastershipEvent(dpid, registryService.getOnosInstanceId(),
283 role);
284 // FIXME should be merging, with existing attrs, etc..
285 // TODO define attr name as constant somewhere.
286 // TODO populate appropriate attributes.
287 mastershipEvent.createStringAttribute(TopologyElement.TYPE,
288 TopologyElement.TYPE_ALL_LAYERS);
289 mastershipEvent.freeze();
290 topologyDiscoveryInterface.removeSwitchMastershipEvent(mastershipEvent);
291 }
292
293 @Override
294 public void switchPortChanged(long swId, OFPortDesc port,
295 PortChangeType changeType) {
296 switch (changeType) {
297 case ADD:
298 switchPortAdded(swId, port);
299 break;
300 case DELETE:
301 switchPortRemoved(swId, port);
302 break;
303 case DOWN:
304 case UP:
305 case OTHER_UPDATE:
306 default:
307 // XXX S what is the right set of port change handlers?
308 log.debug("Topology publisher does not handle these port updates: {}",
309 changeType);
310 }
311 }
312
313 private void switchPortAdded(long switchId, OFPortDesc port) {
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700314 final Dpid dpid = new Dpid(switchId);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700315 PortEvent portEvent = new PortEvent(dpid,
316 new PortNumber(port.getPortNo().getShortPortNumber()));
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700317 // FIXME should be merging, with existing attrs, etc..
318 // TODO define attr name as constant somewhere.
319 // TODO populate appropriate attributes.
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -0700320 portEvent.createStringAttribute(TopologyElement.TYPE,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700321 TopologyElement.TYPE_PACKET_LAYER);
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700322 portEvent.createStringAttribute("name", port.getName());
Yuta HIGUCHI5bbbaca2014-06-09 16:39:08 -0700323
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700324 portEvent.freeze();
325
Jonathan Hart67b6cba2014-05-30 22:36:37 -0700326 if (registryService.hasControl(switchId)) {
Jonathan Hart67b6cba2014-05-30 22:36:37 -0700327 topologyDiscoveryInterface.putPortDiscoveryEvent(portEvent);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700328 linkDiscovery.enableDiscoveryOnPort(switchId,
329 port.getPortNo().getShortPortNumber());
Yuta HIGUCHI5bbbaca2014-06-09 16:39:08 -0700330 } else {
331 log.debug("Not the master for switch {}. Suppressed port add event {}.",
332 new Dpid(switchId), portEvent);
Jonathan Hart67b6cba2014-05-30 22:36:37 -0700333 }
Jonathan Hart88770672014-04-02 18:08:30 -0700334 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800335
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700336 private void switchPortRemoved(long switchId, OFPortDesc port) {
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -0700337 final Dpid dpid = new Dpid(switchId);
Yuta HIGUCHI5bbbaca2014-06-09 16:39:08 -0700338
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700339 PortEvent portEvent = new PortEvent(dpid, new PortNumber(
340 port.getPortNo().getShortPortNumber()));
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -0700341 // FIXME should be merging, with existing attrs, etc..
342 // TODO define attr name as constant somewhere.
343 // TODO populate appropriate attributes.
344 portEvent.createStringAttribute(TopologyElement.TYPE,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700345 TopologyElement.TYPE_PACKET_LAYER);
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -0700346 portEvent.createStringAttribute("name", port.getName());
347
348 portEvent.freeze();
349
Jonathan Hart67b6cba2014-05-30 22:36:37 -0700350 if (registryService.hasControl(switchId)) {
Jonathan Hart67b6cba2014-05-30 22:36:37 -0700351 topologyDiscoveryInterface.removePortDiscoveryEvent(portEvent);
Yuta HIGUCHI5bbbaca2014-06-09 16:39:08 -0700352 } else {
353 log.debug("Not the master for switch {}. Suppressed port del event {}.",
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -0700354 dpid, portEvent);
Jonathan Hart67b6cba2014-05-30 22:36:37 -0700355 }
Jonathan Hart88770672014-04-02 18:08:30 -0700356 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800357
Jonathan Hart88770672014-04-02 18:08:30 -0700358 @Override
Jonathan Hart88770672014-04-02 18:08:30 -0700359 public String getName() {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700360 return "topologyPublisher";
Jonathan Hart88770672014-04-02 18:08:30 -0700361 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800362
Jonathan Hart88770672014-04-02 18:08:30 -0700363 /* *****************
364 * IFloodlightModule
365 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800366
Jonathan Hart88770672014-04-02 18:08:30 -0700367 @Override
368 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
369 return null;
370 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800371
Jonathan Hart88770672014-04-02 18:08:30 -0700372 @Override
373 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700374 getServiceImpls() {
Jonathan Hart88770672014-04-02 18:08:30 -0700375 return null;
376 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800377
Jonathan Hart88770672014-04-02 18:08:30 -0700378 @Override
379 public Collection<Class<? extends IFloodlightService>>
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700380 getModuleDependencies() {
Jonathan Hart88770672014-04-02 18:08:30 -0700381 Collection<Class<? extends IFloodlightService>> l =
382 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800383 l.add(IFloodlightProviderService.class);
384 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800385 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800386 l.add(IControllerRegistryService.class);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700387 l.add(ITopologyService.class);
Jonathan Hart03102132014-07-01 23:22:04 -0700388 l.add(IHostService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800389 return l;
Jonathan Hart88770672014-04-02 18:08:30 -0700390 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800391
Jonathan Hart88770672014-04-02 18:08:30 -0700392 @Override
393 public void init(FloodlightModuleContext context)
394 throws FloodlightModuleException {
395 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
396 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
397 registryService = context.getServiceImpl(IControllerRegistryService.class);
Jonathan Hart03102132014-07-01 23:22:04 -0700398 hostService = context.getServiceImpl(IHostService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800399
Jonathan Harte37e4e22014-05-13 19:12:02 -0700400 topologyService = context.getServiceImpl(ITopologyService.class);
Jonathan Hart88770672014-04-02 18:08:30 -0700401 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800402
Jonathan Hart88770672014-04-02 18:08:30 -0700403 @Override
404 public void startUp(FloodlightModuleContext context) {
405 floodlightProvider.addOFSwitchListener(this);
406 linkDiscovery.addListener(this);
Jonathan Hart03102132014-07-01 23:22:04 -0700407 hostService.addHostListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800408
Jonathan Harte37e4e22014-05-13 19:12:02 -0700409 topology = topologyService.getTopology();
410 topologyDiscoveryInterface =
411 topologyService.getTopologyDiscoveryInterface();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700412
Jonathan Hart88770672014-04-02 18:08:30 -0700413 // Run the cleanup thread
414 String enableCleanup =
415 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
416 if (enableCleanup != null
417 && enableCleanup.equalsIgnoreCase("false")) {
418 cleanupEnabled = false;
419 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700420
Jonathan Hart88770672014-04-02 18:08:30 -0700421 log.debug("Cleanup thread is {}enabled", (cleanupEnabled) ? "" : "not ");
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700422
Jonathan Hart88770672014-04-02 18:08:30 -0700423 if (cleanupEnabled) {
424 IThreadPoolService threadPool =
425 context.getServiceImpl(IThreadPoolService.class);
426 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
427 new SwitchCleanup());
428 // Run the cleanup task immediately on startup
429 cleanupTask.reschedule(0, TimeUnit.SECONDS);
430 }
431 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700432
Jonathan Hart88770672014-04-02 18:08:30 -0700433 @Override
Jonathan Hart03102132014-07-01 23:22:04 -0700434 public void hostAdded(Host host) {
435 log.debug("Called onosDeviceAdded mac {}", host.getMacAddress());
TeruUd1c5b652014-03-24 13:58:46 -0700436
Jonathan Hart03102132014-07-01 23:22:04 -0700437 SwitchPort sp = new SwitchPort(host.getSwitchDPID(), host.getSwitchPort());
Jonathan Hart88770672014-04-02 18:08:30 -0700438 List<SwitchPort> spLists = new ArrayList<SwitchPort>();
439 spLists.add(sp);
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700440 HostEvent event = new HostEvent(host.getMacAddress());
Jonathan Hart88770672014-04-02 18:08:30 -0700441 event.setAttachmentPoints(spLists);
Jonathan Hart03102132014-07-01 23:22:04 -0700442 event.setLastSeenTime(host.getLastSeenTimestamp().getTime());
Jonathan Hart88770672014-04-02 18:08:30 -0700443 // Does not use vlan info now.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700444 event.freeze();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700445
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700446 topologyDiscoveryInterface.putHostDiscoveryEvent(event);
Jonathan Hart88770672014-04-02 18:08:30 -0700447 }
TeruUd1c5b652014-03-24 13:58:46 -0700448
Jonathan Hart88770672014-04-02 18:08:30 -0700449 @Override
Jonathan Hart03102132014-07-01 23:22:04 -0700450 public void hostRemoved(Host host) {
Jonathan Hart88770672014-04-02 18:08:30 -0700451 log.debug("Called onosDeviceRemoved");
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700452 HostEvent event = new HostEvent(host.getMacAddress());
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700453 // XXX shouldn't we be setting attachment points?
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700454 event.freeze();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700455 topologyDiscoveryInterface.removeHostDiscoveryEvent(event);
Jonathan Hart88770672014-04-02 18:08:30 -0700456 }
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700457
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700458 private void controllerRoleChanged(Dpid dpid, Role role) {
459 log.debug("Local switch controller mastership role changed: dpid = {} role = {}",
460 dpid, role);
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700461 MastershipEvent mastershipEvent =
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700462 new MastershipEvent(dpid, registryService.getOnosInstanceId(),
463 role);
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700464 // FIXME should be merging, with existing attrs, etc..
465 // TODO define attr name as constant somewhere.
466 // TODO populate appropriate attributes.
467 mastershipEvent.createStringAttribute(TopologyElement.TYPE,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700468 TopologyElement.TYPE_ALL_LAYERS);
Pavlin Radoslavov695f8952014-07-23 16:57:01 -0700469 mastershipEvent.freeze();
470 topologyDiscoveryInterface.putSwitchMastershipEvent(mastershipEvent);
471 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800472}