blob: d2c10fce45e06bebb058b08c3c455061b5da09fd [file] [log] [blame]
Jonathan Hart4b5bbb52014-02-06 10:09:31 -08001package net.onrc.onos.ofcontroller.floodlightlistener;
2
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 Hart4b5bbb52014-02-06 10:09:31 -080017import net.onrc.onos.datagrid.IDatagridService;
18import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
19import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
20import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080021import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
Jonathan Hart22eb9882014-02-11 15:52:59 -080022import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
Jonathan Hart369875b2014-02-13 10:00:31 -080023import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
Jonathan Hart22eb9882014-02-11 15:52:59 -080024import net.onrc.onos.ofcontroller.networkgraph.NetworkGraphDiscoveryInterface;
Jonathan Hart369875b2014-02-13 10:00:31 -080025import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
26import net.onrc.onos.ofcontroller.networkgraph.Switch;
Jonathan Hart22eb9882014-02-11 15:52:59 -080027import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080028import net.onrc.onos.registry.controller.IControllerRegistryService;
Jonathan Hart369875b2014-02-13 10:00:31 -080029import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
30import net.onrc.onos.registry.controller.RegistryException;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080031
32import org.openflow.protocol.OFPhysicalPort;
Jonathan Hart369875b2014-02-13 10:00:31 -080033import org.openflow.util.HexString;
Toshio Koide2f570c12014-02-06 16:55:32 -080034import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080036
37/*
38 * I've created a copy of the NetworkGraphPublisher so I can integrate
39 * the new API with ONOS while still having the old NetworkGraphPublisher
40 * to reference. I've renamed to RCNetworkGraphPublisher.
41 * TODO Remove old NetworkGraphPublisher once the integration of the new
42 * API is complete.
43 * For now, we just write to the database and don't worry about sending
Toshio Koide2f570c12014-02-06 16:55:32 -080044 * notifications.
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080045 * TODO Send notification after each database write
46 */
47public class RCNetworkGraphPublisher implements /*IOFSwitchListener,*/
48 IOFSwitchPortListener,
49 ILinkDiscoveryListener,
50 IFloodlightModule {
Jonathan Hart47016712014-02-07 12:41:35 -080051 private static final Logger log = LoggerFactory.getLogger(RCNetworkGraphPublisher.class);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080052
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080053 private IFloodlightProviderService floodlightProvider;
54 private ILinkDiscoveryService linkDiscovery;
55 private IControllerRegistryService registryService;
56 private IDatagridService datagridService;
57 private INetworkGraphService networkGraphService;
Toshio Koide2f570c12014-02-06 16:55:32 -080058
Jonathan Hart369875b2014-02-13 10:00:31 -080059 private NetworkGraph networkGraph;
Jonathan Hart22eb9882014-02-11 15:52:59 -080060 private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
Jonathan Hart369875b2014-02-13 10:00:31 -080061
62 private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
63 private boolean cleanupEnabled = true;
64 private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
65 private SingletonTask cleanupTask;
Toshio Koide2f570c12014-02-06 16:55:32 -080066
Jonathan Hart369875b2014-02-13 10:00:31 -080067 /**
68 * Cleanup and synch switch state from registry
69 */
70 private class SwitchCleanup implements ControlChangeCallback, Runnable {
71 @Override
72 public void run() {
73 String old = Thread.currentThread().getName();
74 Thread.currentThread().setName("SwitchCleanup@" + old);
75
76 try {
77 log.debug("Running cleanup thread");
78 switchCleanup();
79 }
80 catch (Exception e) {
81 log.error("Error in cleanup thread", e);
82 } finally {
83 cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
84 TimeUnit.SECONDS);
85 Thread.currentThread().setName(old);
86 }
87 }
88
89 private void switchCleanup() {
90 Iterable<Switch> switches = networkGraph.getSwitches();
91
92 log.debug("Checking for inactive switches");
93 // For each switch check if a controller exists in controller registry
94 for (Switch sw: switches) {
95 try {
96 String controller =
97 registryService.getControllerForSwitch(sw.getDpid());
98 if (controller == null) {
99 log.debug("Requesting control to set switch {} INACTIVE",
100 HexString.toHexString(sw.getDpid()));
101 registryService.requestControl(sw.getDpid(), this);
102 }
103 } catch (RegistryException e) {
104 log.error("Caught RegistryException in cleanup thread", e);
105 }
106 }
107 }
108
109 @Override
110 public void controlChanged(long dpid, boolean hasControl) {
111 if (hasControl) {
112 log.debug("Got control to set switch {} INACTIVE", HexString.toHexString(dpid));
113 /*
114 // Get the affected ports
115 List<Short> ports = swStore.getPorts(HexString.toHexString(dpid));
116 // Get the affected links
117 List<Link> links = linkStore.getLinks(HexString.toHexString(dpid));
118 // Get the affected reverse links
119 List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(dpid));
120 links.addAll(reverseLinks);
121 */
122 SwitchEvent switchEvent = new SwitchEvent(dpid);
123 networkGraphDiscoveryInterface.removeSwitchEvent(switchEvent);
124 registryService.releaseControl(dpid);
125
126 // TODO publish UPDATE_SWITCH event here
127 //
128 // NOTE: Here we explicitly send
129 // notification to remove the
130 // switch, because it is inactive
131 //
132 /*
133 TopologyElement topologyElement =
134 new TopologyElement(dpid);
135 datagridService.notificationSendTopologyElementRemoved(topologyElement);
136
137 // Publish: remove the affected ports
138 for (Short port : ports) {
139 TopologyElement topologyElementPort =
140 new TopologyElement(dpid, port);
141 datagridService.notificationSendTopologyElementRemoved(topologyElementPort);
142 }
143 // Publish: remove the affected links
144 for (Link link : links) {
145 TopologyElement topologyElementLink =
146 new TopologyElement(link.getSrc(),
147 link.getSrcPort(),
148 link.getDst(),
149 link.getDstPort());
150 datagridService.notificationSendTopologyElementRemoved(topologyElementLink);
151 }
152 */
153 }
154 }
155 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800156
157 @Override
158 public void linkDiscoveryUpdate(LDUpdate update) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800159 LinkEvent linkEvent = new LinkEvent(update.getSrc(),
160 (long)update.getSrcPort(), update.getDst(),
161 (long)update.getDstPort());
162
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800163 switch (update.getOperation()) {
164 case LINK_ADDED:
Jonathan Hart22eb9882014-02-11 15:52:59 -0800165 networkGraphDiscoveryInterface.putLinkEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800166 /*
167 TopologyElement topologyElement =
168 new TopologyElement(update.getSrc(),
169 update.getSrcPort(),
170 update.getDst(),
171 update.getDstPort());
172 datagridService.notificationSendTopologyElementAdded(topologyElement);
173 */
174 break;
175 case LINK_UPDATED:
176 // I don't know what a LINK_UPDATED event is.
177 // We never use it.
178 break;
179 case LINK_REMOVED:
Jonathan Hart22eb9882014-02-11 15:52:59 -0800180 networkGraphDiscoveryInterface.removeLinkEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800181 /*
182 TopologyElement topologyElement =
183 new TopologyElement(update.getSrc(),
184 update.getSrcPort(),
185 update.getDst(),
186 update.getDstPort());
187 datagridService.notificationSendTopologyElementRemoved(topologyElement);
188 */
189 break;
190 default:
191 break;
192 }
193 }
194
195 @Override
196 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
197 // TODO Auto-generated method stub
Toshio Koide2f570c12014-02-06 16:55:32 -0800198
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800199 }
200
201 @Override
202 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
203 // TODO Auto-generated method stub
Toshio Koide2f570c12014-02-06 16:55:32 -0800204
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800205 }
206
207 @Override
208 public void addedSwitch(IOFSwitch sw) {
209 // TODO Not very robust
210 if (!registryService.hasControl(sw.getId())) {
211 return;
212 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800213
Jonathan Hart22eb9882014-02-11 15:52:59 -0800214 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hart369875b2014-02-13 10:00:31 -0800215
216 List<PortEvent> portEvents = new ArrayList<PortEvent>();
217 for (OFPhysicalPort port : sw.getPorts()) {
218 portEvents.add(new PortEvent(sw.getId(), (long)port.getPortNumber()));
219 }
220 switchEvent.setPorts(portEvents);
221
Jonathan Hart22eb9882014-02-11 15:52:59 -0800222 networkGraphDiscoveryInterface.putSwitchEvent(switchEvent);
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 */
230
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());
265 //networkGraphDiscoveryInterface.removeSwitchEvent(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);
Toshio Koide2f570c12014-02-06 16:55:32 -0800315
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800316 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
317 }
318
319 @Override
320 public void startUp(FloodlightModuleContext context) {
321 // TODO enable cleanup thread
322 floodlightProvider.addOFSwitchListener(this);
323 linkDiscovery.addListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800324
Jonathan Hart369875b2014-02-13 10:00:31 -0800325 networkGraph = networkGraphService.getNetworkGraph();
326 networkGraphDiscoveryInterface =
327 networkGraphService.getNetworkGraphDiscoveryInterface();
328
329 // Run the cleanup thread
330 String enableCleanup =
331 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
332 if (enableCleanup != null && enableCleanup.toLowerCase().equals("false")) {
333 cleanupEnabled = false;
334 }
335
336 log.debug("Cleanup thread is {}enabled", (cleanupEnabled)? "" : "not ");
337
338 if (cleanupEnabled) {
339 IThreadPoolService threadPool =
340 context.getServiceImpl(IThreadPoolService.class);
341 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
342 new SwitchCleanup());
343 // Run the cleanup task immediately on startup
344 cleanupTask.reschedule(0, TimeUnit.SECONDS);
345 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800346 }
347}