blob: e0b7c192a652828dc9d27b467ac766feaba5c187 [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/*
Pavlin Radoslavovc0aa4bf2014-03-26 18:32:49 -070038 * I've created a copy of the old NetworkGraphPublisher so I can integrate
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080039 * 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);
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800123 networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
Jonathan Hart369875b2014-02-13 10:00:31 -0800124 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:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800165 networkGraphDiscoveryInterface.putLinkDiscoveryEvent(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:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800180 networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(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());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800198 networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
Jonathan Hart4c263272014-02-13 17:41:05 -0800199 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());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800205 networkGraphDiscoveryInterface.removePortDiscoveryEvent(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 }
Pavlin Radoslavov018d5332014-02-19 23:08:35 -0800221 networkGraphDiscoveryInterface.putSwitchDiscoveryEvent(switchEvent, portEvents);
Toshio Koide2f570c12014-02-06 16:55:32 -0800222
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800223 /*
224 // TODO publish ADD_SWITCH event here
225 TopologyElement topologyElement =
226 new TopologyElement(sw.getId());
227 datagridService.notificationSendTopologyElementAdded(topologyElement);
Jonathan Hart369875b2014-02-13 10:00:31 -0800228 */
229
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800230 // Publish: add the ports
231 // TODO: Add only ports that are UP?
232 for (OFPhysicalPort port : sw.getPorts()) {
Jonathan Hart369875b2014-02-13 10:00:31 -0800233 //TopologyElement topologyElementPort =
234 //new TopologyElement(sw.getId(), port.getPortNumber());
235 //datagridService.notificationSendTopologyElementAdded(topologyElementPort);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800236
237 // Allow links to be discovered on this port now that it's
238 // in the database
239 linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
240 }
241
Jonathan Hart369875b2014-02-13 10:00:31 -0800242 /*
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800243 // Add all links that might be connected already
244 List<Link> links = linkStore.getLinks(HexString.toHexString(sw.getId()));
245 // Add all reverse links as well
246 List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(sw.getId()));
247 links.addAll(reverseLinks);
248
249 // Publish: add the links
250 for (Link link : links) {
251 TopologyElement topologyElementLink =
252 new TopologyElement(link.getSrc(),
253 link.getSrcPort(),
254 link.getDst(),
255 link.getDstPort());
256 datagridService.notificationSendTopologyElementAdded(topologyElementLink);
257 */
258 }
259
260 @Override
261 public void removedSwitch(IOFSwitch sw) {
Jonathan Hart22eb9882014-02-11 15:52:59 -0800262 // TODO move to cleanup thread
Jonathan Hart369875b2014-02-13 10:00:31 -0800263 //SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800264 //networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800265 }
266
267 @Override
268 public void switchPortChanged(Long switchId) {
269 // TODO Auto-generated method stub
Toshio Koide2f570c12014-02-06 16:55:32 -0800270
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800271 }
272
273 @Override
274 public String getName() {
275 // TODO Auto-generated method stub
276 return null;
277 }
278
279 /* *****************
280 * IFloodlightModule
281 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800282
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800283 @Override
284 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
285 return null;
286 }
287
288 @Override
Toshio Koide2f570c12014-02-06 16:55:32 -0800289 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800290 getServiceImpls() {
291 return null;
292 }
293
294 @Override
295 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
296 Collection<Class<? extends IFloodlightService>> l =
297 new ArrayList<Class<? extends IFloodlightService>>();
298 l.add(IFloodlightProviderService.class);
299 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800300 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800301 l.add(IControllerRegistryService.class);
302 l.add(IDatagridService.class);
303 l.add(INetworkGraphService.class);
304 return l;
305 }
306
307 @Override
308 public void init(FloodlightModuleContext context)
309 throws FloodlightModuleException {
310 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
311 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
312 registryService = context.getServiceImpl(IControllerRegistryService.class);
313 datagridService = context.getServiceImpl(IDatagridService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800314
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800315 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
316 }
317
318 @Override
319 public void startUp(FloodlightModuleContext context) {
320 // TODO enable cleanup thread
321 floodlightProvider.addOFSwitchListener(this);
322 linkDiscovery.addListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800323
Jonathan Hart369875b2014-02-13 10:00:31 -0800324 networkGraph = networkGraphService.getNetworkGraph();
325 networkGraphDiscoveryInterface =
326 networkGraphService.getNetworkGraphDiscoveryInterface();
327
328 // Run the cleanup thread
329 String enableCleanup =
330 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
331 if (enableCleanup != null && enableCleanup.toLowerCase().equals("false")) {
332 cleanupEnabled = false;
333 }
334
335 log.debug("Cleanup thread is {}enabled", (cleanupEnabled)? "" : "not ");
336
337 if (cleanupEnabled) {
338 IThreadPoolService threadPool =
339 context.getServiceImpl(IThreadPoolService.class);
340 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
341 new SwitchCleanup());
342 // Run the cleanup task immediately on startup
343 cleanupTask.reschedule(0, TimeUnit.SECONDS);
344 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800345 }
346}