blob: f0a828a4753d69f3de40da2053d97f395c4e5641 [file] [log] [blame]
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08001package net.onrc.onos.ofcontroller.floodlightlistener;
2
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 Hart4b5bbb52014-02-06 10:09:31 -080018import net.onrc.onos.datagrid.IDatagridService;
19import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
TeruUd1c5b652014-03-24 13:58:46 -070020import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceListener;
21import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceService;
22import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080023import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
24import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
TeruUd1c5b652014-03-24 13:58:46 -070025import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080026import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
Jonathan Hart22eb9882014-02-11 15:52:59 -080027import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
Jonathan Hart369875b2014-02-13 10:00:31 -080028import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
Jonathan Hart22eb9882014-02-11 15:52:59 -080029import net.onrc.onos.ofcontroller.networkgraph.NetworkGraphDiscoveryInterface;
Jonathan Hart369875b2014-02-13 10:00:31 -080030import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070031import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Jonathan Hart369875b2014-02-13 10:00:31 -080032import net.onrc.onos.ofcontroller.networkgraph.Switch;
Jonathan Hart22eb9882014-02-11 15:52:59 -080033import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080034import net.onrc.onos.registry.controller.IControllerRegistryService;
Jonathan Hart369875b2014-02-13 10:00:31 -080035import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
36import net.onrc.onos.registry.controller.RegistryException;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080037
38import org.openflow.protocol.OFPhysicalPort;
Jonathan Hart369875b2014-02-13 10:00:31 -080039import org.openflow.util.HexString;
Toshio Koide2f570c12014-02-06 16:55:32 -080040import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080042
TeruUd1c5b652014-03-24 13:58:46 -070043import com.google.common.net.InetAddresses;
44
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070045public class NetworkGraphPublisher implements /*IOFSwitchListener,*/
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080046 IOFSwitchPortListener,
47 ILinkDiscoveryListener,
TeruUd1c5b652014-03-24 13:58:46 -070048 IFloodlightModule,
49 IOnosDeviceListener {
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070050 private static final Logger log = LoggerFactory.getLogger(NetworkGraphPublisher.class);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080051
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080052 private IFloodlightProviderService floodlightProvider;
53 private ILinkDiscoveryService linkDiscovery;
54 private IControllerRegistryService registryService;
55 private IDatagridService datagridService;
56 private INetworkGraphService networkGraphService;
Toshio Koide2f570c12014-02-06 16:55:32 -080057
TeruUd1c5b652014-03-24 13:58:46 -070058 private IOnosDeviceService onosDeviceService;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070059
Jonathan Hart369875b2014-02-13 10:00:31 -080060 private NetworkGraph networkGraph;
Jonathan Hart22eb9882014-02-11 15:52:59 -080061 private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070062
Jonathan Hart369875b2014-02-13 10:00:31 -080063 private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
64 private boolean cleanupEnabled = true;
65 private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
66 private SingletonTask cleanupTask;
Toshio Koide2f570c12014-02-06 16:55:32 -080067
Jonathan Hart369875b2014-02-13 10:00:31 -080068 /**
69 * Cleanup and synch switch state from registry
70 */
71 private class SwitchCleanup implements ControlChangeCallback, Runnable {
72 @Override
73 public void run() {
74 String old = Thread.currentThread().getName();
75 Thread.currentThread().setName("SwitchCleanup@" + old);
Jonathan Hartb3e1b052014-04-02 16:01:12 -070076
Jonathan Hart369875b2014-02-13 10:00:31 -080077 try {
78 log.debug("Running cleanup thread");
79 switchCleanup();
80 }
81 catch (Exception e) {
82 log.error("Error in cleanup thread", e);
83 } finally {
84 cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
85 TimeUnit.SECONDS);
86 Thread.currentThread().setName(old);
87 }
88 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -070089
Jonathan Hart369875b2014-02-13 10:00:31 -080090 private void switchCleanup() {
91 Iterable<Switch> switches = networkGraph.getSwitches();
92
93 log.debug("Checking for inactive switches");
94 // For each switch check if a controller exists in controller registry
95 for (Switch sw: switches) {
96 try {
Jonathan Hartb3e1b052014-04-02 16:01:12 -070097 String controller =
Jonathan Hart369875b2014-02-13 10:00:31 -080098 registryService.getControllerForSwitch(sw.getDpid());
99 if (controller == null) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700100 log.debug("Requesting control to set switch {} INACTIVE",
Jonathan Hart369875b2014-02-13 10:00:31 -0800101 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 }
108 }
109
110 @Override
111 public void controlChanged(long dpid, boolean hasControl) {
112 if (hasControl) {
113 log.debug("Got control to set switch {} INACTIVE", HexString.toHexString(dpid));
114 /*
115 // Get the affected ports
116 List<Short> ports = swStore.getPorts(HexString.toHexString(dpid));
117 // Get the affected links
118 List<Link> links = linkStore.getLinks(HexString.toHexString(dpid));
119 // Get the affected reverse links
120 List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(dpid));
121 links.addAll(reverseLinks);
122 */
123 SwitchEvent switchEvent = new SwitchEvent(dpid);
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800124 networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
Jonathan Hart369875b2014-02-13 10:00:31 -0800125 registryService.releaseControl(dpid);
126
127 // TODO publish UPDATE_SWITCH event here
128 //
129 // NOTE: Here we explicitly send
130 // notification to remove the
131 // switch, because it is inactive
132 //
133 /*
134 TopologyElement topologyElement =
135 new TopologyElement(dpid);
136 datagridService.notificationSendTopologyElementRemoved(topologyElement);
137
138 // Publish: remove the affected ports
139 for (Short port : ports) {
140 TopologyElement topologyElementPort =
141 new TopologyElement(dpid, port);
142 datagridService.notificationSendTopologyElementRemoved(topologyElementPort);
143 }
144 // Publish: remove the affected links
145 for (Link link : links) {
146 TopologyElement topologyElementLink =
147 new TopologyElement(link.getSrc(),
148 link.getSrcPort(),
149 link.getDst(),
150 link.getDstPort());
151 datagridService.notificationSendTopologyElementRemoved(topologyElementLink);
152 }
153 */
154 }
155 }
156 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800157
158 @Override
159 public void linkDiscoveryUpdate(LDUpdate update) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700160 LinkEvent linkEvent = new LinkEvent(update.getSrc(),
161 (long)update.getSrcPort(), update.getDst(),
Jonathan Hart22eb9882014-02-11 15:52:59 -0800162 (long)update.getDstPort());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700163
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800164 switch (update.getOperation()) {
165 case LINK_ADDED:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800166 networkGraphDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800167 /*
168 TopologyElement topologyElement =
169 new TopologyElement(update.getSrc(),
170 update.getSrcPort(),
171 update.getDst(),
172 update.getDstPort());
173 datagridService.notificationSendTopologyElementAdded(topologyElement);
174 */
175 break;
176 case LINK_UPDATED:
177 // I don't know what a LINK_UPDATED event is.
178 // We never use it.
179 break;
180 case LINK_REMOVED:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800181 networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800182 /*
183 TopologyElement topologyElement =
184 new TopologyElement(update.getSrc(),
185 update.getSrcPort(),
186 update.getDst(),
187 update.getDstPort());
188 datagridService.notificationSendTopologyElementRemoved(topologyElement);
189 */
190 break;
191 default:
192 break;
193 }
194 }
195
196 @Override
197 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800198 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800199 networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
Jonathan Hart4c263272014-02-13 17:41:05 -0800200 linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800201 }
202
203 @Override
204 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800205 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800206 networkGraphDiscoveryInterface.removePortDiscoveryEvent(portEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800207 }
208
209 @Override
210 public void addedSwitch(IOFSwitch sw) {
211 // TODO Not very robust
212 if (!registryService.hasControl(sw.getId())) {
213 return;
214 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800215
Jonathan Hart22eb9882014-02-11 15:52:59 -0800216 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700217
Jonathan Hart369875b2014-02-13 10:00:31 -0800218 List<PortEvent> portEvents = new ArrayList<PortEvent>();
219 for (OFPhysicalPort port : sw.getPorts()) {
220 portEvents.add(new PortEvent(sw.getId(), (long)port.getPortNumber()));
221 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800222 networkGraphDiscoveryInterface.putSwitchDiscoveryEvent(switchEvent, portEvents);
Toshio Koide2f570c12014-02-06 16:55:32 -0800223
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800224 /*
225 // TODO publish ADD_SWITCH event here
226 TopologyElement topologyElement =
227 new TopologyElement(sw.getId());
228 datagridService.notificationSendTopologyElementAdded(topologyElement);
Jonathan Hart369875b2014-02-13 10:00:31 -0800229 */
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700230
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800231 // Publish: add the ports
232 // TODO: Add only ports that are UP?
233 for (OFPhysicalPort port : sw.getPorts()) {
Jonathan Hart369875b2014-02-13 10:00:31 -0800234 //TopologyElement topologyElementPort =
235 //new TopologyElement(sw.getId(), port.getPortNumber());
236 //datagridService.notificationSendTopologyElementAdded(topologyElementPort);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800237
238 // Allow links to be discovered on this port now that it's
239 // in the database
240 linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
241 }
242
Jonathan Hart369875b2014-02-13 10:00:31 -0800243 /*
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800244 // Add all links that might be connected already
245 List<Link> links = linkStore.getLinks(HexString.toHexString(sw.getId()));
246 // Add all reverse links as well
247 List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(sw.getId()));
248 links.addAll(reverseLinks);
249
250 // Publish: add the links
251 for (Link link : links) {
252 TopologyElement topologyElementLink =
253 new TopologyElement(link.getSrc(),
254 link.getSrcPort(),
255 link.getDst(),
256 link.getDstPort());
257 datagridService.notificationSendTopologyElementAdded(topologyElementLink);
258 */
259 }
260
261 @Override
262 public void removedSwitch(IOFSwitch sw) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800263 // TODO move to cleanup thread
Jonathan Hart369875b2014-02-13 10:00:31 -0800264 //SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800265 //networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800266 }
267
268 @Override
269 public void switchPortChanged(Long switchId) {
270 // TODO Auto-generated method stub
Toshio Koide2f570c12014-02-06 16:55:32 -0800271
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800272 }
273
274 @Override
275 public String getName() {
276 // TODO Auto-generated method stub
277 return null;
278 }
279
280 /* *****************
281 * IFloodlightModule
282 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800283
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800284 @Override
285 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
286 return null;
287 }
288
289 @Override
Toshio Koide2f570c12014-02-06 16:55:32 -0800290 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800291 getServiceImpls() {
292 return null;
293 }
294
295 @Override
296 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
297 Collection<Class<? extends IFloodlightService>> l =
298 new ArrayList<Class<? extends IFloodlightService>>();
299 l.add(IFloodlightProviderService.class);
300 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800301 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800302 l.add(IControllerRegistryService.class);
303 l.add(IDatagridService.class);
304 l.add(INetworkGraphService.class);
305 return l;
306 }
307
308 @Override
309 public void init(FloodlightModuleContext context)
310 throws FloodlightModuleException {
311 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
312 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
313 registryService = context.getServiceImpl(IControllerRegistryService.class);
314 datagridService = context.getServiceImpl(IDatagridService.class);
TeruUd1c5b652014-03-24 13:58:46 -0700315 onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800316
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800317 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
318 }
319
320 @Override
321 public void startUp(FloodlightModuleContext context) {
322 // TODO enable cleanup thread
323 floodlightProvider.addOFSwitchListener(this);
324 linkDiscovery.addListener(this);
TeruUd1c5b652014-03-24 13:58:46 -0700325 onosDeviceService.addOnosDeviceListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800326
Jonathan Hart369875b2014-02-13 10:00:31 -0800327 networkGraph = networkGraphService.getNetworkGraph();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700328 networkGraphDiscoveryInterface =
Jonathan Hart369875b2014-02-13 10:00:31 -0800329 networkGraphService.getNetworkGraphDiscoveryInterface();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700330
Jonathan Hart369875b2014-02-13 10:00:31 -0800331 // Run the cleanup thread
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700332 String enableCleanup =
Jonathan Hart369875b2014-02-13 10:00:31 -0800333 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
334 if (enableCleanup != null && enableCleanup.toLowerCase().equals("false")) {
335 cleanupEnabled = false;
336 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700337
Jonathan Hart369875b2014-02-13 10:00:31 -0800338 log.debug("Cleanup thread is {}enabled", (cleanupEnabled)? "" : "not ");
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700339
Jonathan Hart369875b2014-02-13 10:00:31 -0800340 if (cleanupEnabled) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700341 IThreadPoolService threadPool =
Jonathan Hart369875b2014-02-13 10:00:31 -0800342 context.getServiceImpl(IThreadPoolService.class);
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700343 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
Jonathan Hart369875b2014-02-13 10:00:31 -0800344 new SwitchCleanup());
345 // Run the cleanup task immediately on startup
346 cleanupTask.reschedule(0, TimeUnit.SECONDS);
347 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800348 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700349
TeruUd1c5b652014-03-24 13:58:46 -0700350 @Override
351 public void onosDeviceAdded(OnosDevice device) {
352 log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());
353
354 SwitchPort sp = new SwitchPort(device.getSwitchDPID(), (long)device.getSwitchPort());
355 List<SwitchPort> spLists = new ArrayList<SwitchPort>();
356 spLists.add(sp);
357 DeviceEvent event = new DeviceEvent(device.getMacAddress());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700358 event.setAttachmentPoints(spLists);
TeruUd1c5b652014-03-24 13:58:46 -0700359 event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
360 if(device.getIpv4Address() != null) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700361 InetAddress ip = InetAddresses.fromInteger(device.getIpv4Address());
TeruUd1c5b652014-03-24 13:58:46 -0700362 event.addIpAddress(ip);
363 }
364 //Does not use Vlan info now.
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700365
366 networkGraphDiscoveryInterface.putDeviceDiscoveryEvent(event);
TeruUd1c5b652014-03-24 13:58:46 -0700367 }
368
369 @Override
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700370 public void onosDeviceRemoved(OnosDevice device) {
TeruUd1c5b652014-03-24 13:58:46 -0700371 log.debug("Called onosDeviceRemoved");
372 DeviceEvent event = new DeviceEvent(device.getMacAddress());
373 networkGraphDiscoveryInterface.removeDeviceDiscoveryEvent(event);
374 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800375}