blob: bddc74bf0d99708884d917bb28a2d3523c529796 [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.ofcontroller.core.IOFSwitchPortListener;
TeruUd1c5b652014-03-24 13:58:46 -070019import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceListener;
20import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceService;
21import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080022import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
23import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
TeruUd1c5b652014-03-24 13:58:46 -070024import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080025import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
Jonathan Hart22eb9882014-02-11 15:52:59 -080026import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
Jonathan Hart369875b2014-02-13 10:00:31 -080027import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
Jonathan Hart22eb9882014-02-11 15:52:59 -080028import net.onrc.onos.ofcontroller.networkgraph.NetworkGraphDiscoveryInterface;
Jonathan Hart369875b2014-02-13 10:00:31 -080029import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070030import net.onrc.onos.ofcontroller.networkgraph.PortEvent.SwitchPort;
Jonathan Hart369875b2014-02-13 10:00:31 -080031import net.onrc.onos.ofcontroller.networkgraph.Switch;
Jonathan Hart22eb9882014-02-11 15:52:59 -080032import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080033import net.onrc.onos.registry.controller.IControllerRegistryService;
Jonathan Hart369875b2014-02-13 10:00:31 -080034import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
35import net.onrc.onos.registry.controller.RegistryException;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080036
37import org.openflow.protocol.OFPhysicalPort;
Jonathan Hart369875b2014-02-13 10:00:31 -080038import org.openflow.util.HexString;
Toshio Koide2f570c12014-02-06 16:55:32 -080039import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080041
TeruUd1c5b652014-03-24 13:58:46 -070042import com.google.common.net.InetAddresses;
43
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070044public class NetworkGraphPublisher implements /*IOFSwitchListener,*/
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080045 IOFSwitchPortListener,
46 ILinkDiscoveryListener,
TeruUd1c5b652014-03-24 13:58:46 -070047 IFloodlightModule,
48 IOnosDeviceListener {
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070049 private static final Logger log = LoggerFactory.getLogger(NetworkGraphPublisher.class);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080050
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080051 private IFloodlightProviderService floodlightProvider;
52 private ILinkDiscoveryService linkDiscovery;
53 private IControllerRegistryService registryService;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080054 private INetworkGraphService networkGraphService;
Toshio Koide2f570c12014-02-06 16:55:32 -080055
TeruUd1c5b652014-03-24 13:58:46 -070056 private IOnosDeviceService onosDeviceService;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070057
Jonathan Hart369875b2014-02-13 10:00:31 -080058 private NetworkGraph networkGraph;
Jonathan Hart22eb9882014-02-11 15:52:59 -080059 private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070060
Jonathan Hart369875b2014-02-13 10:00:31 -080061 private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
62 private boolean cleanupEnabled = true;
63 private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
64 private SingletonTask cleanupTask;
Toshio Koide2f570c12014-02-06 16:55:32 -080065
Jonathan Hart369875b2014-02-13 10:00:31 -080066 /**
67 * Cleanup and synch switch state from registry
68 */
69 private class SwitchCleanup implements ControlChangeCallback, Runnable {
70 @Override
71 public void run() {
72 String old = Thread.currentThread().getName();
73 Thread.currentThread().setName("SwitchCleanup@" + old);
Jonathan Hartb3e1b052014-04-02 16:01:12 -070074
Jonathan Hart369875b2014-02-13 10:00:31 -080075 try {
76 log.debug("Running cleanup thread");
77 switchCleanup();
78 }
79 catch (Exception e) {
80 log.error("Error in cleanup thread", e);
81 } finally {
82 cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
83 TimeUnit.SECONDS);
84 Thread.currentThread().setName(old);
85 }
86 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -070087
Jonathan Hart369875b2014-02-13 10:00:31 -080088 private void switchCleanup() {
89 Iterable<Switch> switches = networkGraph.getSwitches();
90
91 log.debug("Checking for inactive switches");
92 // For each switch check if a controller exists in controller registry
93 for (Switch sw: switches) {
94 try {
Jonathan Hartb3e1b052014-04-02 16:01:12 -070095 String controller =
Jonathan Hart369875b2014-02-13 10:00:31 -080096 registryService.getControllerForSwitch(sw.getDpid());
97 if (controller == null) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -070098 log.debug("Requesting control to set switch {} INACTIVE",
Jonathan Hart369875b2014-02-13 10:00:31 -080099 HexString.toHexString(sw.getDpid()));
100 registryService.requestControl(sw.getDpid(), this);
101 }
102 } catch (RegistryException e) {
103 log.error("Caught RegistryException in cleanup thread", e);
104 }
105 }
106 }
107
108 @Override
109 public void controlChanged(long dpid, boolean hasControl) {
110 if (hasControl) {
111 log.debug("Got control to set switch {} INACTIVE", HexString.toHexString(dpid));
Jonathan Harte02cf542014-04-02 16:24:44 -0700112
Jonathan Hart369875b2014-02-13 10:00:31 -0800113 SwitchEvent switchEvent = new SwitchEvent(dpid);
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800114 networkGraphDiscoveryInterface.removeSwitchDiscoveryEvent(switchEvent);
Jonathan Hart369875b2014-02-13 10:00:31 -0800115 registryService.releaseControl(dpid);
Jonathan Hart369875b2014-02-13 10:00:31 -0800116 }
117 }
118 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800119
120 @Override
121 public void linkDiscoveryUpdate(LDUpdate update) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700122 LinkEvent linkEvent = new LinkEvent(update.getSrc(),
123 (long)update.getSrcPort(), update.getDst(),
Jonathan Hart22eb9882014-02-11 15:52:59 -0800124 (long)update.getDstPort());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700125
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800126 switch (update.getOperation()) {
127 case LINK_ADDED:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800128 networkGraphDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800129 break;
130 case LINK_UPDATED:
Jonathan Harte02cf542014-04-02 16:24:44 -0700131 // We don't use the LINK_UPDATED event (unsure what it means)
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800132 break;
133 case LINK_REMOVED:
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800134 networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800135 break;
136 default:
137 break;
138 }
139 }
140
141 @Override
142 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800143 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800144 networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
Jonathan Hart4c263272014-02-13 17:41:05 -0800145 linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800146 }
147
148 @Override
149 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
Jonathan Hart4c263272014-02-13 17:41:05 -0800150 PortEvent portEvent = new PortEvent(switchId, (long)port.getPortNumber());
Pavlin Radoslavov6ea84a42014-02-19 15:50:01 -0800151 networkGraphDiscoveryInterface.removePortDiscoveryEvent(portEvent);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800152 }
153
154 @Override
155 public void addedSwitch(IOFSwitch sw) {
156 // TODO Not very robust
157 if (!registryService.hasControl(sw.getId())) {
158 return;
159 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800160
Jonathan Hart22eb9882014-02-11 15:52:59 -0800161 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700162
Jonathan Hart369875b2014-02-13 10:00:31 -0800163 List<PortEvent> portEvents = new ArrayList<PortEvent>();
164 for (OFPhysicalPort port : sw.getPorts()) {
165 portEvents.add(new PortEvent(sw.getId(), (long)port.getPortNumber()));
166 }
Jonathan Harte02cf542014-04-02 16:24:44 -0700167 networkGraphDiscoveryInterface
168 .putSwitchDiscoveryEvent(switchEvent, portEvents);
Toshio Koide2f570c12014-02-06 16:55:32 -0800169
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800170 for (OFPhysicalPort port : sw.getPorts()) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800171 // Allow links to be discovered on this port now that it's
172 // in the database
173 linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
174 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800175 }
176
177 @Override
178 public void removedSwitch(IOFSwitch sw) {
Jonathan Harte02cf542014-04-02 16:24:44 -0700179 // We don't use this event - switch remove is done by cleanup thread
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800180 }
181
182 @Override
183 public void switchPortChanged(Long switchId) {
Jonathan Harte02cf542014-04-02 16:24:44 -0700184 // We don't use this event
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800185 }
186
187 @Override
188 public String getName() {
189 // TODO Auto-generated method stub
190 return null;
191 }
192
193 /* *****************
194 * IFloodlightModule
195 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800196
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800197 @Override
198 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
199 return null;
200 }
201
202 @Override
Toshio Koide2f570c12014-02-06 16:55:32 -0800203 public Map<Class<? extends IFloodlightService>, IFloodlightService>
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800204 getServiceImpls() {
205 return null;
206 }
207
208 @Override
209 public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
210 Collection<Class<? extends IFloodlightService>> l =
211 new ArrayList<Class<? extends IFloodlightService>>();
212 l.add(IFloodlightProviderService.class);
213 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800214 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800215 l.add(IControllerRegistryService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800216 l.add(INetworkGraphService.class);
Jonathan Hartebbe6a62014-04-02 16:10:25 -0700217 l.add(IOnosDeviceService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800218 return l;
219 }
220
221 @Override
222 public void init(FloodlightModuleContext context)
223 throws FloodlightModuleException {
224 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
225 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
226 registryService = context.getServiceImpl(IControllerRegistryService.class);
TeruUd1c5b652014-03-24 13:58:46 -0700227 onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800228
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800229 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
230 }
231
232 @Override
233 public void startUp(FloodlightModuleContext context) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800234 floodlightProvider.addOFSwitchListener(this);
235 linkDiscovery.addListener(this);
TeruUd1c5b652014-03-24 13:58:46 -0700236 onosDeviceService.addOnosDeviceListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800237
Jonathan Hart369875b2014-02-13 10:00:31 -0800238 networkGraph = networkGraphService.getNetworkGraph();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700239 networkGraphDiscoveryInterface =
Jonathan Hart369875b2014-02-13 10:00:31 -0800240 networkGraphService.getNetworkGraphDiscoveryInterface();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700241
Jonathan Hart369875b2014-02-13 10:00:31 -0800242 // Run the cleanup thread
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700243 String enableCleanup =
Jonathan Hart369875b2014-02-13 10:00:31 -0800244 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
245 if (enableCleanup != null && enableCleanup.toLowerCase().equals("false")) {
246 cleanupEnabled = false;
247 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700248
Jonathan Hart369875b2014-02-13 10:00:31 -0800249 log.debug("Cleanup thread is {}enabled", (cleanupEnabled)? "" : "not ");
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700250
Jonathan Hart369875b2014-02-13 10:00:31 -0800251 if (cleanupEnabled) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700252 IThreadPoolService threadPool =
Jonathan Hart369875b2014-02-13 10:00:31 -0800253 context.getServiceImpl(IThreadPoolService.class);
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700254 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
Jonathan Hart369875b2014-02-13 10:00:31 -0800255 new SwitchCleanup());
256 // Run the cleanup task immediately on startup
257 cleanupTask.reschedule(0, TimeUnit.SECONDS);
258 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800259 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700260
TeruUd1c5b652014-03-24 13:58:46 -0700261 @Override
262 public void onosDeviceAdded(OnosDevice device) {
263 log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());
264
265 SwitchPort sp = new SwitchPort(device.getSwitchDPID(), (long)device.getSwitchPort());
266 List<SwitchPort> spLists = new ArrayList<SwitchPort>();
267 spLists.add(sp);
268 DeviceEvent event = new DeviceEvent(device.getMacAddress());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700269 event.setAttachmentPoints(spLists);
TeruUd1c5b652014-03-24 13:58:46 -0700270 event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
271 if(device.getIpv4Address() != null) {
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700272 InetAddress ip = InetAddresses.fromInteger(device.getIpv4Address());
TeruUd1c5b652014-03-24 13:58:46 -0700273 event.addIpAddress(ip);
274 }
Jonathan Harte02cf542014-04-02 16:24:44 -0700275 // Does not use vlan info now.
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700276
277 networkGraphDiscoveryInterface.putDeviceDiscoveryEvent(event);
TeruUd1c5b652014-03-24 13:58:46 -0700278 }
279
280 @Override
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700281 public void onosDeviceRemoved(OnosDevice device) {
TeruUd1c5b652014-03-24 13:58:46 -0700282 log.debug("Called onosDeviceRemoved");
283 DeviceEvent event = new DeviceEvent(device.getMacAddress());
284 networkGraphDiscoveryInterface.removeDeviceDiscoveryEvent(event);
285 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800286}