blob: 6c900033e7dbc537628cccfc761b62777dc477ec [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;
10import net.floodlightcontroller.core.IOFSwitch;
11import net.floodlightcontroller.core.module.FloodlightModuleContext;
12import net.floodlightcontroller.core.module.FloodlightModuleException;
13import net.floodlightcontroller.core.module.IFloodlightModule;
14import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart369875b2014-02-13 10:00:31 -080015import net.floodlightcontroller.core.util.SingletonTask;
16import net.floodlightcontroller.threadpool.IThreadPoolService;
Jonathan Hart23701d12014-04-03 10:45:48 -070017import net.onrc.onos.core.devicemanager.IOnosDeviceListener;
18import net.onrc.onos.core.devicemanager.IOnosDeviceService;
19import net.onrc.onos.core.devicemanager.OnosDevice;
20import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryListener;
21import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
Jonathan Hart51f6f5b2014-04-03 10:32:10 -070022import net.onrc.onos.core.main.IOFSwitchPortListener;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070023import net.onrc.onos.core.registry.IControllerRegistryService;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070024import net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback;
Jonathan Harta99ec672014-04-03 11:30:34 -070025import net.onrc.onos.core.registry.RegistryException;
Jonathan Hart472062d2014-04-03 10:56:48 -070026import net.onrc.onos.core.topology.PortEvent.SwitchPort;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080027
28import org.openflow.protocol.OFPhysicalPort;
Jonathan Hart369875b2014-02-13 10:00:31 -080029import org.openflow.util.HexString;
Toshio Koide2f570c12014-02-06 16:55:32 -080030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080032
Jonathan Hart88770672014-04-02 18:08:30 -070033/**
Jonathan Harte37e4e22014-05-13 19:12:02 -070034 * The TopologyPublisher subscribes to topology network events from the
35 * discovery modules. These events are reformatted and relayed to the in-memory
36 * topology instance.
Jonathan Hart88770672014-04-02 18:08:30 -070037 */
Jonathan Harte37e4e22014-05-13 19:12:02 -070038public class TopologyPublisher implements /*IOFSwitchListener,*/
Ray Milkey269ffb92014-04-03 14:43:30 -070039 IOFSwitchPortListener,
40 ILinkDiscoveryListener,
41 IFloodlightModule,
42 IOnosDeviceListener {
Jonathan Hart88770672014-04-02 18:08:30 -070043 private static final Logger log =
Jonathan Harte37e4e22014-05-13 19:12:02 -070044 LoggerFactory.getLogger(TopologyPublisher.class);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080045
Jonathan Hart88770672014-04-02 18:08:30 -070046 private IFloodlightProviderService floodlightProvider;
47 private ILinkDiscoveryService linkDiscovery;
48 private IControllerRegistryService registryService;
Jonathan Harte37e4e22014-05-13 19:12:02 -070049 private ITopologyService topologyService;
Toshio Koide2f570c12014-02-06 16:55:32 -080050
Jonathan Hart88770672014-04-02 18:08:30 -070051 private IOnosDeviceService onosDeviceService;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070052
Jonathan Harte37e4e22014-05-13 19:12:02 -070053 private Topology topology;
54 private TopologyDiscoveryInterface topologyDiscoveryInterface;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070055
Jonathan Hart88770672014-04-02 18:08:30 -070056 private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
57 private boolean cleanupEnabled = true;
58 private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
59 private SingletonTask cleanupTask;
Toshio Koide2f570c12014-02-06 16:55:32 -080060
Jonathan Hart369875b2014-02-13 10:00:31 -080061 /**
Jonathan Harte37e4e22014-05-13 19:12:02 -070062 * Cleanup old switches from the topology. Old switches are those
Jonathan Hart88770672014-04-02 18:08:30 -070063 * which have no controller in the registry.
Jonathan Hart369875b2014-02-13 10:00:31 -080064 */
65 private class SwitchCleanup implements ControlChangeCallback, Runnable {
66 @Override
67 public void run() {
68 String old = Thread.currentThread().getName();
69 Thread.currentThread().setName("SwitchCleanup@" + old);
Jonathan Hartb3e1b052014-04-02 16:01:12 -070070
Jonathan Hart369875b2014-02-13 10:00:31 -080071 try {
Jonathan Hart88770672014-04-02 18:08:30 -070072 if (log.isTraceEnabled()) {
73 log.trace("Running cleanup thread");
74 }
Jonathan Hart369875b2014-02-13 10:00:31 -080075 switchCleanup();
Jonathan Hart369875b2014-02-13 10:00:31 -080076 } finally {
77 cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
Jonathan Hart88770672014-04-02 18:08:30 -070078 TimeUnit.SECONDS);
Jonathan Hart369875b2014-02-13 10:00:31 -080079 Thread.currentThread().setName(old);
80 }
81 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -070082
Jonathan Hart88770672014-04-02 18:08:30 -070083 /**
84 * First half of the switch cleanup operation. This method will attempt
85 * to get control of any switch it sees without a controller via the
86 * registry.
87 */
Jonathan Hart369875b2014-02-13 10:00:31 -080088 private void switchCleanup() {
Jonathan Harte37e4e22014-05-13 19:12:02 -070089 Iterable<Switch> switches = topology.getSwitches();
Jonathan Hart369875b2014-02-13 10:00:31 -080090
Jonathan Hart88770672014-04-02 18:08:30 -070091 if (log.isTraceEnabled()) {
92 log.trace("Checking for inactive switches");
93 }
94 // For each switch check if a controller exists in controller registry
Ray Milkey269ffb92014-04-03 14:43:30 -070095 for (Switch sw : switches) {
Jonathan Hart88770672014-04-02 18:08:30 -070096 try {
97 String controller =
98 registryService.getControllerForSwitch(sw.getDpid());
99 if (controller == null) {
100 log.debug("Requesting control to set switch {} INACTIVE",
101 HexString.toHexString(sw.getDpid()));
102 registryService.requestControl(sw.getDpid(), this);
103 }
104 } catch (RegistryException e) {
105 log.error("Caught RegistryException in cleanup thread", e);
106 }
107 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800108 }
109
Jonathan Hart88770672014-04-02 18:08:30 -0700110 /**
111 * Second half of the switch cleanup operation. If the registry grants
112 * control of a switch, we can be sure no other instance is writing
Jonathan Harte37e4e22014-05-13 19:12:02 -0700113 * this switch to the topology, so we can remove it now.
Ray Milkey269ffb92014-04-03 14:43:30 -0700114 *
115 * @param dpid the dpid of the switch we requested control for
Jonathan Hart88770672014-04-02 18:08:30 -0700116 * @param hasControl whether we got control or not
117 */
118 @Override
119 public void controlChanged(long dpid, boolean hasControl) {
120 if (hasControl) {
121 log.debug("Got control to set switch {} INACTIVE",
122 HexString.toHexString(dpid));
Jonathan Harte02cf542014-04-02 16:24:44 -0700123
Jonathan Hart88770672014-04-02 18:08:30 -0700124 SwitchEvent switchEvent = new SwitchEvent(dpid);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700125 topologyDiscoveryInterface.
Jonathan Hart88770672014-04-02 18:08:30 -0700126 removeSwitchDiscoveryEvent(switchEvent);
127 registryService.releaseControl(dpid);
128 }
129 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800130 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800131
Jonathan Hart88770672014-04-02 18:08:30 -0700132 @Override
133 public void linkDiscoveryUpdate(LDUpdate update) {
134 LinkEvent linkEvent = new LinkEvent(update.getSrc(),
135 (long) update.getSrcPort(), update.getDst(),
136 (long) update.getDstPort());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700137
Jonathan Hart88770672014-04-02 18:08:30 -0700138 switch (update.getOperation()) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700139 case LINK_ADDED:
Jonathan Harte37e4e22014-05-13 19:12:02 -0700140 topologyDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700141 break;
142 case LINK_UPDATED:
143 // We don't use the LINK_UPDATED event (unsure what it means)
144 break;
145 case LINK_REMOVED:
Jonathan Harte37e4e22014-05-13 19:12:02 -0700146 topologyDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
Ray Milkey269ffb92014-04-03 14:43:30 -0700147 break;
148 default:
149 break;
Jonathan Hart88770672014-04-02 18:08:30 -0700150 }
151 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800152
Jonathan Hart88770672014-04-02 18:08:30 -0700153 @Override
154 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
155 PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
Jonathan Harte37e4e22014-05-13 19:12:02 -0700156 topologyDiscoveryInterface.putPortDiscoveryEvent(portEvent);
Pavlin Radoslavov7d21c0a2014-04-10 10:32:59 -0700157 linkDiscovery.removeFromSuppressLLDPs(switchId, port.getPortNumber());
Jonathan Hart88770672014-04-02 18:08:30 -0700158 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800159
Jonathan Hart88770672014-04-02 18:08:30 -0700160 @Override
161 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
162 PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
Jonathan Harte37e4e22014-05-13 19:12:02 -0700163 topologyDiscoveryInterface.removePortDiscoveryEvent(portEvent);
Jonathan Hart88770672014-04-02 18:08:30 -0700164 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800165
Jonathan Hart88770672014-04-02 18:08:30 -0700166 @Override
167 public void addedSwitch(IOFSwitch sw) {
168 // TODO Not very robust
169 if (!registryService.hasControl(sw.getId())) {
170 return;
171 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800172
Jonathan Hart88770672014-04-02 18:08:30 -0700173 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700174
Jonathan Hart88770672014-04-02 18:08:30 -0700175 List<PortEvent> portEvents = new ArrayList<PortEvent>();
176 for (OFPhysicalPort port : sw.getPorts()) {
177 portEvents.add(new PortEvent(sw.getId(), (long) port.getPortNumber()));
178 }
Jonathan Harte37e4e22014-05-13 19:12:02 -0700179 topologyDiscoveryInterface
Ray Milkey269ffb92014-04-03 14:43:30 -0700180 .putSwitchDiscoveryEvent(switchEvent, portEvents);
Toshio Koide2f570c12014-02-06 16:55:32 -0800181
Jonathan Hart88770672014-04-02 18:08:30 -0700182 for (OFPhysicalPort port : sw.getPorts()) {
183 // Allow links to be discovered on this port now that it's
184 // in the database
Pavlin Radoslavov7d21c0a2014-04-10 10:32:59 -0700185 linkDiscovery.removeFromSuppressLLDPs(sw.getId(), port.getPortNumber());
Jonathan Hart88770672014-04-02 18:08:30 -0700186 }
187 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800188
Jonathan Hart88770672014-04-02 18:08:30 -0700189 @Override
190 public void removedSwitch(IOFSwitch sw) {
191 // We don't use this event - switch remove is done by cleanup thread
192 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800193
Jonathan Hart88770672014-04-02 18:08:30 -0700194 @Override
195 public void switchPortChanged(Long switchId) {
196 // We don't use this event
197 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800198
Jonathan Hart88770672014-04-02 18:08:30 -0700199 @Override
200 public String getName() {
201 // TODO Auto-generated method stub
202 return null;
203 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800204
Jonathan Hart88770672014-04-02 18:08:30 -0700205 /* *****************
206 * IFloodlightModule
207 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800208
Jonathan Hart88770672014-04-02 18:08:30 -0700209 @Override
210 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
211 return null;
212 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800213
Jonathan Hart88770672014-04-02 18:08:30 -0700214 @Override
215 public Map<Class<? extends IFloodlightService>, IFloodlightService>
216 getServiceImpls() {
217 return null;
218 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800219
Jonathan Hart88770672014-04-02 18:08:30 -0700220 @Override
221 public Collection<Class<? extends IFloodlightService>>
Ray Milkey269ffb92014-04-03 14:43:30 -0700222 getModuleDependencies() {
Jonathan Hart88770672014-04-02 18:08:30 -0700223 Collection<Class<? extends IFloodlightService>> l =
224 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800225 l.add(IFloodlightProviderService.class);
226 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800227 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800228 l.add(IControllerRegistryService.class);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700229 l.add(ITopologyService.class);
Jonathan Hartebbe6a62014-04-02 16:10:25 -0700230 l.add(IOnosDeviceService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800231 return l;
Jonathan Hart88770672014-04-02 18:08:30 -0700232 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800233
Jonathan Hart88770672014-04-02 18:08:30 -0700234 @Override
235 public void init(FloodlightModuleContext context)
236 throws FloodlightModuleException {
237 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
238 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
239 registryService = context.getServiceImpl(IControllerRegistryService.class);
240 onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800241
Jonathan Harte37e4e22014-05-13 19:12:02 -0700242 topologyService = context.getServiceImpl(ITopologyService.class);
Jonathan Hart88770672014-04-02 18:08:30 -0700243 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800244
Jonathan Hart88770672014-04-02 18:08:30 -0700245 @Override
246 public void startUp(FloodlightModuleContext context) {
247 floodlightProvider.addOFSwitchListener(this);
248 linkDiscovery.addListener(this);
249 onosDeviceService.addOnosDeviceListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800250
Jonathan Harte37e4e22014-05-13 19:12:02 -0700251 topology = topologyService.getTopology();
252 topologyDiscoveryInterface =
253 topologyService.getTopologyDiscoveryInterface();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700254
Jonathan Hart88770672014-04-02 18:08:30 -0700255 // Run the cleanup thread
256 String enableCleanup =
257 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
258 if (enableCleanup != null
259 && enableCleanup.equalsIgnoreCase("false")) {
260 cleanupEnabled = false;
261 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700262
Jonathan Hart88770672014-04-02 18:08:30 -0700263 log.debug("Cleanup thread is {}enabled", (cleanupEnabled) ? "" : "not ");
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700264
Jonathan Hart88770672014-04-02 18:08:30 -0700265 if (cleanupEnabled) {
266 IThreadPoolService threadPool =
267 context.getServiceImpl(IThreadPoolService.class);
268 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
269 new SwitchCleanup());
270 // Run the cleanup task immediately on startup
271 cleanupTask.reschedule(0, TimeUnit.SECONDS);
272 }
273 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700274
Jonathan Hart88770672014-04-02 18:08:30 -0700275 @Override
276 public void onosDeviceAdded(OnosDevice device) {
277 log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());
TeruUd1c5b652014-03-24 13:58:46 -0700278
Jonathan Hart88770672014-04-02 18:08:30 -0700279 SwitchPort sp = new SwitchPort(device.getSwitchDPID(),
280 (long) device.getSwitchPort());
281 List<SwitchPort> spLists = new ArrayList<SwitchPort>();
282 spLists.add(sp);
283 DeviceEvent event = new DeviceEvent(device.getMacAddress());
284 event.setAttachmentPoints(spLists);
285 event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
Jonathan Hart88770672014-04-02 18:08:30 -0700286 // Does not use vlan info now.
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700287
Jonathan Harte37e4e22014-05-13 19:12:02 -0700288 topologyDiscoveryInterface.putDeviceDiscoveryEvent(event);
Jonathan Hart88770672014-04-02 18:08:30 -0700289 }
TeruUd1c5b652014-03-24 13:58:46 -0700290
Jonathan Hart88770672014-04-02 18:08:30 -0700291 @Override
292 public void onosDeviceRemoved(OnosDevice device) {
293 log.debug("Called onosDeviceRemoved");
294 DeviceEvent event = new DeviceEvent(device.getMacAddress());
Jonathan Harte37e4e22014-05-13 19:12:02 -0700295 topologyDiscoveryInterface.removeDeviceDiscoveryEvent(event);
Jonathan Hart88770672014-04-02 18:08:30 -0700296 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800297}