blob: 88d9475afa7420d728c9af13dc0099d880aadd43 [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;
31import net.onrc.onos.ofcontroller.networkgraph.Switch;
Jonathan Hart22eb9882014-02-11 15:52:59 -080032import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
TeruUd1c5b652014-03-24 13:58:46 -070033import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
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
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080045/*
Pavlin Radoslavovc0aa4bf2014-03-26 18:32:49 -070046 * I've created a copy of the old NetworkGraphPublisher so I can integrate
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080047 * the new API with ONOS while still having the old NetworkGraphPublisher
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070048 * to reference.
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080049 * TODO Remove old NetworkGraphPublisher once the integration of the new
50 * API is complete.
51 * For now, we just write to the database and don't worry about sending
Toshio Koide2f570c12014-02-06 16:55:32 -080052 * notifications.
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080053 * TODO Send notification after each database write
54 */
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070055public class NetworkGraphPublisher implements /*IOFSwitchListener,*/
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080056 IOFSwitchPortListener,
57 ILinkDiscoveryListener,
TeruUd1c5b652014-03-24 13:58:46 -070058 IFloodlightModule,
59 IOnosDeviceListener {
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070060 private static final Logger log = LoggerFactory.getLogger(NetworkGraphPublisher.class);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080061
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080062 private IFloodlightProviderService floodlightProvider;
63 private ILinkDiscoveryService linkDiscovery;
64 private IControllerRegistryService registryService;
65 private IDatagridService datagridService;
66 private INetworkGraphService networkGraphService;
Toshio Koide2f570c12014-02-06 16:55:32 -080067
TeruUd1c5b652014-03-24 13:58:46 -070068 private IOnosDeviceService onosDeviceService;
69
Jonathan Hart369875b2014-02-13 10:00:31 -080070 private NetworkGraph networkGraph;
Jonathan Hart22eb9882014-02-11 15:52:59 -080071 private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
Jonathan Hart369875b2014-02-13 10:00:31 -080072
73 private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
74 private boolean cleanupEnabled = true;
75 private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
76 private SingletonTask cleanupTask;
Toshio Koide2f570c12014-02-06 16:55:32 -080077
Jonathan Hart369875b2014-02-13 10:00:31 -080078 /**
79 * Cleanup and synch switch state from registry
80 */
81 private class SwitchCleanup implements ControlChangeCallback, Runnable {
82 @Override
83 public void run() {
84 String old = Thread.currentThread().getName();
85 Thread.currentThread().setName("SwitchCleanup@" + old);
86
87 try {
88 log.debug("Running cleanup thread");
89 switchCleanup();
90 }
91 catch (Exception e) {
92 log.error("Error in cleanup thread", e);
93 } finally {
94 cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
95 TimeUnit.SECONDS);
96 Thread.currentThread().setName(old);
97 }
98 }
99
100 private void switchCleanup() {
101 Iterable<Switch> switches = networkGraph.getSwitches();
102
103 log.debug("Checking for inactive switches");
104 // For each switch check if a controller exists in controller registry
105 for (Switch sw: switches) {
106 try {
107 String controller =
108 registryService.getControllerForSwitch(sw.getDpid());
109 if (controller == null) {
110 log.debug("Requesting control to set switch {} INACTIVE",
111 HexString.toHexString(sw.getDpid()));
112 registryService.requestControl(sw.getDpid(), this);
113 }
114 } catch (RegistryException e) {
115 log.error("Caught RegistryException in cleanup thread", e);
116 }
117 }
118 }
119
120 @Override
121 public void controlChanged(long dpid, boolean hasControl) {
122 if (hasControl) {
123 log.debug("Got control to set switch {} INACTIVE", HexString.toHexString(dpid));
124 /*
125 // Get the affected ports
126 List<Short> ports = swStore.getPorts(HexString.toHexString(dpid));
127 // Get the affected links
128 List<Link> links = linkStore.getLinks(HexString.toHexString(dpid));
129 // Get the affected reverse links
130 List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(dpid));
131 links.addAll(reverseLinks);
132 */
133 SwitchEvent switchEvent = new SwitchEvent(dpid);
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800134 networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
Jonathan Hart369875b2014-02-13 10:00:31 -0800135 registryService.releaseControl(dpid);
136
137 // TODO publish UPDATE_SWITCH event here
138 //
139 // NOTE: Here we explicitly send
140 // notification to remove the
141 // switch, because it is inactive
142 //
143 /*
144 TopologyElement topologyElement =
145 new TopologyElement(dpid);
146 datagridService.notificationSendTopologyElementRemoved(topologyElement);
147
148 // Publish: remove the affected ports
149 for (Short port : ports) {
150 TopologyElement topologyElementPort =
151 new TopologyElement(dpid, port);
152 datagridService.notificationSendTopologyElementRemoved(topologyElementPort);
153 }
154 // Publish: remove the affected links
155 for (Link link : links) {
156 TopologyElement topologyElementLink =
157 new TopologyElement(link.getSrc(),
158 link.getSrcPort(),
159 link.getDst(),
160 link.getDstPort());
161 datagridService.notificationSendTopologyElementRemoved(topologyElementLink);
162 }
163 */
164 }
165 }
166 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800167
168 @Override
169 public void linkDiscoveryUpdate(LDUpdate update) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800170 LinkEvent linkEvent = new LinkEvent(update.getSrc(),
171 (long)update.getSrcPort(), update.getDst(),
172 (long)update.getDstPort());
173
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800174 switch (update.getOperation()) {
175 case LINK_ADDED:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800176 networkGraphDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800177 /*
178 TopologyElement topologyElement =
179 new TopologyElement(update.getSrc(),
180 update.getSrcPort(),
181 update.getDst(),
182 update.getDstPort());
183 datagridService.notificationSendTopologyElementAdded(topologyElement);
184 */
185 break;
186 case LINK_UPDATED:
187 // I don't know what a LINK_UPDATED event is.
188 // We never use it.
189 break;
190 case LINK_REMOVED:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800191 networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800192 /*
193 TopologyElement topologyElement =
194 new TopologyElement(update.getSrc(),
195 update.getSrcPort(),
196 update.getDst(),
197 update.getDstPort());
198 datagridService.notificationSendTopologyElementRemoved(topologyElement);
199 */
200 break;
201 default:
202 break;
203 }
204 }
205
206 @Override
207 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800208 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800209 networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
Jonathan Hart4c263272014-02-13 17:41:05 -0800210 linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800211 }
212
213 @Override
214 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800215 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800216 networkGraphDiscoveryInterface.removePortDiscoveryEvent(portEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800217 }
218
219 @Override
220 public void addedSwitch(IOFSwitch sw) {
221 // TODO Not very robust
222 if (!registryService.hasControl(sw.getId())) {
223 return;
224 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800225
Jonathan Hart22eb9882014-02-11 15:52:59 -0800226 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hart369875b2014-02-13 10:00:31 -0800227
228 List<PortEvent> portEvents = new ArrayList<PortEvent>();
229 for (OFPhysicalPort port : sw.getPorts()) {
230 portEvents.add(new PortEvent(sw.getId(), (long)port.getPortNumber()));
231 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800232 networkGraphDiscoveryInterface.putSwitchDiscoveryEvent(switchEvent, portEvents);
Toshio Koide2f570c12014-02-06 16:55:32 -0800233
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800234 /*
235 // TODO publish ADD_SWITCH event here
236 TopologyElement topologyElement =
237 new TopologyElement(sw.getId());
238 datagridService.notificationSendTopologyElementAdded(topologyElement);
Jonathan Hart369875b2014-02-13 10:00:31 -0800239 */
240
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800241 // Publish: add the ports
242 // TODO: Add only ports that are UP?
243 for (OFPhysicalPort port : sw.getPorts()) {
Jonathan Hart369875b2014-02-13 10:00:31 -0800244 //TopologyElement topologyElementPort =
245 //new TopologyElement(sw.getId(), port.getPortNumber());
246 //datagridService.notificationSendTopologyElementAdded(topologyElementPort);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800247
248 // Allow links to be discovered on this port now that it's
249 // in the database
250 linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
251 }
252
Jonathan Hart369875b2014-02-13 10:00:31 -0800253 /*
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800254 // Add all links that might be connected already
255 List<Link> links = linkStore.getLinks(HexString.toHexString(sw.getId()));
256 // Add all reverse links as well
257 List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(sw.getId()));
258 links.addAll(reverseLinks);
259
260 // Publish: add the links
261 for (Link link : links) {
262 TopologyElement topologyElementLink =
263 new TopologyElement(link.getSrc(),
264 link.getSrcPort(),
265 link.getDst(),
266 link.getDstPort());
267 datagridService.notificationSendTopologyElementAdded(topologyElementLink);
268 */
269 }
270
271 @Override
272 public void removedSwitch(IOFSwitch sw) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800273 // TODO move to cleanup thread
Jonathan Hart369875b2014-02-13 10:00:31 -0800274 //SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800275 //networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800276 }
277
278 @Override
279 public void switchPortChanged(Long switchId) {
280 // TODO Auto-generated method stub
Toshio Koide2f570c12014-02-06 16:55:32 -0800281
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800282 }
283
284 @Override
285 public String getName() {
286 // TODO Auto-generated method stub
287 return null;
288 }
289
290 /* *****************
291 * IFloodlightModule
292 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800293
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800294 @Override
295 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
296 return null;
297 }
298
299 @Override
Toshio Koide2f570c12014-02-06 16:55:32 -0800300 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800301 getServiceImpls() {
302 return null;
303 }
304
305 @Override
306 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
307 Collection<Class<? extends IFloodlightService>> l =
308 new ArrayList<Class<? extends IFloodlightService>>();
309 l.add(IFloodlightProviderService.class);
310 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800311 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800312 l.add(IControllerRegistryService.class);
313 l.add(IDatagridService.class);
314 l.add(INetworkGraphService.class);
315 return l;
316 }
317
318 @Override
319 public void init(FloodlightModuleContext context)
320 throws FloodlightModuleException {
321 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
322 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
323 registryService = context.getServiceImpl(IControllerRegistryService.class);
324 datagridService = context.getServiceImpl(IDatagridService.class);
TeruUd1c5b652014-03-24 13:58:46 -0700325 onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800326
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800327 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
328 }
329
330 @Override
331 public void startUp(FloodlightModuleContext context) {
332 // TODO enable cleanup thread
333 floodlightProvider.addOFSwitchListener(this);
334 linkDiscovery.addListener(this);
TeruUd1c5b652014-03-24 13:58:46 -0700335 onosDeviceService.addOnosDeviceListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800336
Jonathan Hart369875b2014-02-13 10:00:31 -0800337 networkGraph = networkGraphService.getNetworkGraph();
338 networkGraphDiscoveryInterface =
339 networkGraphService.getNetworkGraphDiscoveryInterface();
340
341 // Run the cleanup thread
342 String enableCleanup =
343 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
344 if (enableCleanup != null && enableCleanup.toLowerCase().equals("false")) {
345 cleanupEnabled = false;
346 }
347
348 log.debug("Cleanup thread is {}enabled", (cleanupEnabled)? "" : "not ");
349
350 if (cleanupEnabled) {
351 IThreadPoolService threadPool =
352 context.getServiceImpl(IThreadPoolService.class);
353 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
354 new SwitchCleanup());
355 // Run the cleanup task immediately on startup
356 cleanupTask.reschedule(0, TimeUnit.SECONDS);
357 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800358 }
TeruUd1c5b652014-03-24 13:58:46 -0700359
360 @Override
361 public void onosDeviceAdded(OnosDevice device) {
362 log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());
363
364 SwitchPort sp = new SwitchPort(device.getSwitchDPID(), (long)device.getSwitchPort());
365 List<SwitchPort> spLists = new ArrayList<SwitchPort>();
366 spLists.add(sp);
367 DeviceEvent event = new DeviceEvent(device.getMacAddress());
368 event.setAttachmentPoints(spLists);
369 event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
370 if(device.getIpv4Address() != null) {
371 InetAddress ip = InetAddresses.fromInteger(device.getIpv4Address());
372 event.addIpAddress(ip);
373 }
374 //Does not use Vlan info now.
375
376 networkGraphDiscoveryInterface.putDeviceDiscoveryEvent(event);
377 }
378
379 @Override
380 public void onosDeviceRemoved(OnosDevice device) {
381 log.debug("Called onosDeviceRemoved");
382 DeviceEvent event = new DeviceEvent(device.getMacAddress());
383 networkGraphDiscoveryInterface.removeDeviceDiscoveryEvent(event);
384 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800385}