blob: 0727a274d91bc849acc7fb16199507c86169b4b2 [file] [log] [blame]
Jonathan Hart472062d2014-04-03 10:56:48 -07001package net.onrc.onos.core.topology;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08002
TeruUd1c5b652014-03-24 13:58:46 -07003import java.net.InetAddress;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08004import java.util.ArrayList;
5import java.util.Collection;
Jonathan Hart369875b2014-02-13 10:00:31 -08006import java.util.List;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08007import java.util.Map;
Jonathan Hart369875b2014-02-13 10:00:31 -08008import java.util.concurrent.TimeUnit;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08009
10import net.floodlightcontroller.core.IFloodlightProviderService;
11import net.floodlightcontroller.core.IOFSwitch;
12import net.floodlightcontroller.core.module.FloodlightModuleContext;
13import net.floodlightcontroller.core.module.FloodlightModuleException;
14import net.floodlightcontroller.core.module.IFloodlightModule;
15import net.floodlightcontroller.core.module.IFloodlightService;
Jonathan Hart369875b2014-02-13 10:00:31 -080016import net.floodlightcontroller.core.util.SingletonTask;
17import net.floodlightcontroller.threadpool.IThreadPoolService;
Jonathan Hart23701d12014-04-03 10:45:48 -070018import net.onrc.onos.core.devicemanager.IOnosDeviceListener;
19import net.onrc.onos.core.devicemanager.IOnosDeviceService;
20import net.onrc.onos.core.devicemanager.OnosDevice;
21import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryListener;
22import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
Jonathan Hart51f6f5b2014-04-03 10:32:10 -070023import net.onrc.onos.core.main.IOFSwitchPortListener;
Jonathan Hart472062d2014-04-03 10:56:48 -070024import net.onrc.onos.core.topology.PortEvent.SwitchPort;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080025import net.onrc.onos.registry.controller.IControllerRegistryService;
Jonathan Hart369875b2014-02-13 10:00:31 -080026import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
27import net.onrc.onos.registry.controller.RegistryException;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080028
29import org.openflow.protocol.OFPhysicalPort;
Jonathan Hart369875b2014-02-13 10:00:31 -080030import org.openflow.util.HexString;
Toshio Koide2f570c12014-02-06 16:55:32 -080031import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080033
TeruUd1c5b652014-03-24 13:58:46 -070034import com.google.common.net.InetAddresses;
35
Jonathan Hart88770672014-04-02 18:08:30 -070036/**
37 * The NetworkGraphPublisher subscribes to topology network events from the
38 * discovery modules. These events are reformatted and relayed to the topology
39 * part of the network graph
40 *
41 */
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070042public class NetworkGraphPublisher implements /*IOFSwitchListener,*/
Jonathan Hart88770672014-04-02 18:08:30 -070043 IOFSwitchPortListener,
44 ILinkDiscoveryListener,
45 IFloodlightModule,
46 IOnosDeviceListener {
47 private static final Logger log =
48 LoggerFactory.getLogger(NetworkGraphPublisher.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;
53 private INetworkGraphService networkGraphService;
Toshio Koide2f570c12014-02-06 16:55:32 -080054
Jonathan Hart88770672014-04-02 18:08:30 -070055 private IOnosDeviceService onosDeviceService;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070056
Jonathan Hart88770672014-04-02 18:08:30 -070057 private NetworkGraph networkGraph;
58 private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
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 /**
Jonathan Hart88770672014-04-02 18:08:30 -070066 * Cleanup old switches from the network graph. Old switches are those
67 * which have 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 Hart88770672014-04-02 18:08:30 -070093 Iterable<Switch> switches = networkGraph.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 }
98 // For each switch check if a controller exists in controller registry
99 for (Switch sw: switches) {
100 try {
101 String controller =
102 registryService.getControllerForSwitch(sw.getDpid());
103 if (controller == null) {
104 log.debug("Requesting control to set switch {} INACTIVE",
105 HexString.toHexString(sw.getDpid()));
106 registryService.requestControl(sw.getDpid(), this);
107 }
108 } catch (RegistryException e) {
109 log.error("Caught RegistryException in cleanup thread", e);
110 }
111 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800112 }
113
Jonathan Hart88770672014-04-02 18:08:30 -0700114 /**
115 * Second half of the switch cleanup operation. If the registry grants
116 * control of a switch, we can be sure no other instance is writing
117 * this switch to the network graph, so we can remove it now.
118 * @param dpid the dpid of the switch we requested control for
119 * @param hasControl whether we got control or not
120 */
121 @Override
122 public void controlChanged(long dpid, boolean hasControl) {
123 if (hasControl) {
124 log.debug("Got control to set switch {} INACTIVE",
125 HexString.toHexString(dpid));
Jonathan Harte02cf542014-04-02 16:24:44 -0700126
Jonathan Hart88770672014-04-02 18:08:30 -0700127 SwitchEvent switchEvent = new SwitchEvent(dpid);
128 networkGraphDiscoveryInterface.
129 removeSwitchDiscoveryEvent(switchEvent);
130 registryService.releaseControl(dpid);
131 }
132 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800133 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800134
Jonathan Hart88770672014-04-02 18:08:30 -0700135 @Override
136 public void linkDiscoveryUpdate(LDUpdate update) {
137 LinkEvent linkEvent = new LinkEvent(update.getSrc(),
138 (long) update.getSrcPort(), update.getDst(),
139 (long) update.getDstPort());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700140
Jonathan Hart88770672014-04-02 18:08:30 -0700141 switch (update.getOperation()) {
142 case LINK_ADDED:
143 networkGraphDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
144 break;
145 case LINK_UPDATED:
146 // We don't use the LINK_UPDATED event (unsure what it means)
147 break;
148 case LINK_REMOVED:
149 networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
150 break;
151 default:
152 break;
153 }
154 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800155
Jonathan Hart88770672014-04-02 18:08:30 -0700156 @Override
157 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
158 PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
159 networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
160 linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
161 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800162
Jonathan Hart88770672014-04-02 18:08:30 -0700163 @Override
164 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
165 PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
166 networkGraphDiscoveryInterface.removePortDiscoveryEvent(portEvent);
167 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800168
Jonathan Hart88770672014-04-02 18:08:30 -0700169 @Override
170 public void addedSwitch(IOFSwitch sw) {
171 // TODO Not very robust
172 if (!registryService.hasControl(sw.getId())) {
173 return;
174 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800175
Jonathan Hart88770672014-04-02 18:08:30 -0700176 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700177
Jonathan Hart88770672014-04-02 18:08:30 -0700178 List<PortEvent> portEvents = new ArrayList<PortEvent>();
179 for (OFPhysicalPort port : sw.getPorts()) {
180 portEvents.add(new PortEvent(sw.getId(), (long) port.getPortNumber()));
181 }
182 networkGraphDiscoveryInterface
183 .putSwitchDiscoveryEvent(switchEvent, portEvents);
Toshio Koide2f570c12014-02-06 16:55:32 -0800184
Jonathan Hart88770672014-04-02 18:08:30 -0700185 for (OFPhysicalPort port : sw.getPorts()) {
186 // Allow links to be discovered on this port now that it's
187 // in the database
188 linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
189 }
190 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800191
Jonathan Hart88770672014-04-02 18:08:30 -0700192 @Override
193 public void removedSwitch(IOFSwitch sw) {
194 // We don't use this event - switch remove is done by cleanup thread
195 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800196
Jonathan Hart88770672014-04-02 18:08:30 -0700197 @Override
198 public void switchPortChanged(Long switchId) {
199 // We don't use this event
200 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800201
Jonathan Hart88770672014-04-02 18:08:30 -0700202 @Override
203 public String getName() {
204 // TODO Auto-generated method stub
205 return null;
206 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800207
Jonathan Hart88770672014-04-02 18:08:30 -0700208 /* *****************
209 * IFloodlightModule
210 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800211
Jonathan Hart88770672014-04-02 18:08:30 -0700212 @Override
213 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
214 return null;
215 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800216
Jonathan Hart88770672014-04-02 18:08:30 -0700217 @Override
218 public Map<Class<? extends IFloodlightService>, IFloodlightService>
219 getServiceImpls() {
220 return null;
221 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800222
Jonathan Hart88770672014-04-02 18:08:30 -0700223 @Override
224 public Collection<Class<? extends IFloodlightService>>
225 getModuleDependencies() {
226 Collection<Class<? extends IFloodlightService>> l =
227 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800228 l.add(IFloodlightProviderService.class);
229 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800230 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800231 l.add(IControllerRegistryService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800232 l.add(INetworkGraphService.class);
Jonathan Hartebbe6a62014-04-02 16:10:25 -0700233 l.add(IOnosDeviceService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800234 return l;
Jonathan Hart88770672014-04-02 18:08:30 -0700235 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800236
Jonathan Hart88770672014-04-02 18:08:30 -0700237 @Override
238 public void init(FloodlightModuleContext context)
239 throws FloodlightModuleException {
240 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
241 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
242 registryService = context.getServiceImpl(IControllerRegistryService.class);
243 onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800244
Jonathan Hart88770672014-04-02 18:08:30 -0700245 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
246 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800247
Jonathan Hart88770672014-04-02 18:08:30 -0700248 @Override
249 public void startUp(FloodlightModuleContext context) {
250 floodlightProvider.addOFSwitchListener(this);
251 linkDiscovery.addListener(this);
252 onosDeviceService.addOnosDeviceListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800253
Jonathan Hart88770672014-04-02 18:08:30 -0700254 networkGraph = networkGraphService.getNetworkGraph();
255 networkGraphDiscoveryInterface =
256 networkGraphService.getNetworkGraphDiscoveryInterface();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700257
Jonathan Hart88770672014-04-02 18:08:30 -0700258 // Run the cleanup thread
259 String enableCleanup =
260 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
261 if (enableCleanup != null
262 && enableCleanup.equalsIgnoreCase("false")) {
263 cleanupEnabled = false;
264 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700265
Jonathan Hart88770672014-04-02 18:08:30 -0700266 log.debug("Cleanup thread is {}enabled", (cleanupEnabled) ? "" : "not ");
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700267
Jonathan Hart88770672014-04-02 18:08:30 -0700268 if (cleanupEnabled) {
269 IThreadPoolService threadPool =
270 context.getServiceImpl(IThreadPoolService.class);
271 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
272 new SwitchCleanup());
273 // Run the cleanup task immediately on startup
274 cleanupTask.reschedule(0, TimeUnit.SECONDS);
275 }
276 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700277
Jonathan Hart88770672014-04-02 18:08:30 -0700278 @Override
279 public void onosDeviceAdded(OnosDevice device) {
280 log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());
TeruUd1c5b652014-03-24 13:58:46 -0700281
Jonathan Hart88770672014-04-02 18:08:30 -0700282 SwitchPort sp = new SwitchPort(device.getSwitchDPID(),
283 (long) device.getSwitchPort());
284 List<SwitchPort> spLists = new ArrayList<SwitchPort>();
285 spLists.add(sp);
286 DeviceEvent event = new DeviceEvent(device.getMacAddress());
287 event.setAttachmentPoints(spLists);
288 event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
289 if (device.getIpv4Address() != null) {
290 InetAddress ip = InetAddresses.fromInteger(device.getIpv4Address());
291 event.addIpAddress(ip);
292 }
293 // Does not use vlan info now.
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700294
Jonathan Hart88770672014-04-02 18:08:30 -0700295 networkGraphDiscoveryInterface.putDeviceDiscoveryEvent(event);
296 }
TeruUd1c5b652014-03-24 13:58:46 -0700297
Jonathan Hart88770672014-04-02 18:08:30 -0700298 @Override
299 public void onosDeviceRemoved(OnosDevice device) {
300 log.debug("Called onosDeviceRemoved");
301 DeviceEvent event = new DeviceEvent(device.getMacAddress());
302 networkGraphDiscoveryInterface.removeDeviceDiscoveryEvent(event);
303 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800304}