blob: a1d09df996764a89902aede64365a49af77de45a [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) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800197 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
198 networkGraphDiscoveryInterface.putPortEvent(portEvent);
199 linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800200 }
201
202 @Override
203 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800204 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
205 networkGraphDiscoveryInterface.removePortEvent(portEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800206 }
207
208 @Override
209 public void addedSwitch(IOFSwitch sw) {
210 // TODO Not very robust
211 if (!registryService.hasControl(sw.getId())) {
212 return;
213 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800214
Jonathan Hart22eb9882014-02-11 15:52:59 -0800215 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hart369875b2014-02-13 10:00:31 -0800216
217 List<PortEvent> portEvents = new ArrayList<PortEvent>();
218 for (OFPhysicalPort port : sw.getPorts()) {
219 portEvents.add(new PortEvent(sw.getId(), (long)port.getPortNumber()));
220 }
221 switchEvent.setPorts(portEvents);
222
Jonathan Hart22eb9882014-02-11 15:52:59 -0800223 networkGraphDiscoveryInterface.putSwitchEvent(switchEvent);
Toshio Koide2f570c12014-02-06 16:55:32 -0800224
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800225 /*
226 // TODO publish ADD_SWITCH event here
227 TopologyElement topologyElement =
228 new TopologyElement(sw.getId());
229 datagridService.notificationSendTopologyElementAdded(topologyElement);
Jonathan Hart369875b2014-02-13 10:00:31 -0800230 */
231
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800232 // Publish: add the ports
233 // TODO: Add only ports that are UP?
234 for (OFPhysicalPort port : sw.getPorts()) {
Jonathan Hart369875b2014-02-13 10:00:31 -0800235 //TopologyElement topologyElementPort =
236 //new TopologyElement(sw.getId(), port.getPortNumber());
237 //datagridService.notificationSendTopologyElementAdded(topologyElementPort);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800238
239 // Allow links to be discovered on this port now that it's
240 // in the database
241 linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
242 }
243
Jonathan Hart369875b2014-02-13 10:00:31 -0800244 /*
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800245 // Add all links that might be connected already
246 List<Link> links = linkStore.getLinks(HexString.toHexString(sw.getId()));
247 // Add all reverse links as well
248 List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(sw.getId()));
249 links.addAll(reverseLinks);
250
251 // Publish: add the links
252 for (Link link : links) {
253 TopologyElement topologyElementLink =
254 new TopologyElement(link.getSrc(),
255 link.getSrcPort(),
256 link.getDst(),
257 link.getDstPort());
258 datagridService.notificationSendTopologyElementAdded(topologyElementLink);
259 */
260 }
261
262 @Override
263 public void removedSwitch(IOFSwitch sw) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800264 // TODO move to cleanup thread
Jonathan Hart369875b2014-02-13 10:00:31 -0800265 //SwitchEvent switchEvent = new SwitchEvent(sw.getId());
266 //networkGraphDiscoveryInterface.removeSwitchEvent(switchEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800267 }
268
269 @Override
270 public void switchPortChanged(Long switchId) {
271 // TODO Auto-generated method stub
Toshio Koide2f570c12014-02-06 16:55:32 -0800272
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800273 }
274
275 @Override
276 public String getName() {
277 // TODO Auto-generated method stub
278 return null;
279 }
280
281 /* *****************
282 * IFloodlightModule
283 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800284
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800285 @Override
286 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
287 return null;
288 }
289
290 @Override
Toshio Koide2f570c12014-02-06 16:55:32 -0800291 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800292 getServiceImpls() {
293 return null;
294 }
295
296 @Override
297 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
298 Collection<Class<? extends IFloodlightService>> l =
299 new ArrayList<Class<? extends IFloodlightService>>();
300 l.add(IFloodlightProviderService.class);
301 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800302 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800303 l.add(IControllerRegistryService.class);
304 l.add(IDatagridService.class);
305 l.add(INetworkGraphService.class);
306 return l;
307 }
308
309 @Override
310 public void init(FloodlightModuleContext context)
311 throws FloodlightModuleException {
312 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
313 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
314 registryService = context.getServiceImpl(IControllerRegistryService.class);
315 datagridService = context.getServiceImpl(IDatagridService.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);
Toshio Koide2f570c12014-02-06 16:55:32 -0800325
Jonathan Hart369875b2014-02-13 10:00:31 -0800326 networkGraph = networkGraphService.getNetworkGraph();
327 networkGraphDiscoveryInterface =
328 networkGraphService.getNetworkGraphDiscoveryInterface();
329
330 // Run the cleanup thread
331 String enableCleanup =
332 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
333 if (enableCleanup != null && enableCleanup.toLowerCase().equals("false")) {
334 cleanupEnabled = false;
335 }
336
337 log.debug("Cleanup thread is {}enabled", (cleanupEnabled)? "" : "not ");
338
339 if (cleanupEnabled) {
340 IThreadPoolService threadPool =
341 context.getServiceImpl(IThreadPoolService.class);
342 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
343 new SwitchCleanup());
344 // Run the cleanup task immediately on startup
345 cleanupTask.reschedule(0, TimeUnit.SECONDS);
346 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800347 }
348}