blob: d71848b153d7803088c993ab778f7d6da1e02476 [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
Jonathan Hart88770672014-04-02 18:08:30 -070044/**
45 * The NetworkGraphPublisher subscribes to topology network events from the
46 * discovery modules. These events are reformatted and relayed to the topology
47 * part of the network graph
48 *
49 */
Pavlin Radoslavov70c2b362014-03-26 18:41:19 -070050public class NetworkGraphPublisher implements /*IOFSwitchListener,*/
Jonathan Hart88770672014-04-02 18:08:30 -070051 IOFSwitchPortListener,
52 ILinkDiscoveryListener,
53 IFloodlightModule,
54 IOnosDeviceListener {
55 private static final Logger log =
56 LoggerFactory.getLogger(NetworkGraphPublisher.class);
Yuta HIGUCHIcb951982014-02-11 13:31:44 -080057
Jonathan Hart88770672014-04-02 18:08:30 -070058 private IFloodlightProviderService floodlightProvider;
59 private ILinkDiscoveryService linkDiscovery;
60 private IControllerRegistryService registryService;
61 private INetworkGraphService networkGraphService;
Toshio Koide2f570c12014-02-06 16:55:32 -080062
Jonathan Hart88770672014-04-02 18:08:30 -070063 private IOnosDeviceService onosDeviceService;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070064
Jonathan Hart88770672014-04-02 18:08:30 -070065 private NetworkGraph networkGraph;
66 private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
Jonathan Hartb3e1b052014-04-02 16:01:12 -070067
Jonathan Hart88770672014-04-02 18:08:30 -070068 private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
69 private boolean cleanupEnabled = true;
70 private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
71 private SingletonTask cleanupTask;
Toshio Koide2f570c12014-02-06 16:55:32 -080072
Jonathan Hart369875b2014-02-13 10:00:31 -080073 /**
Jonathan Hart88770672014-04-02 18:08:30 -070074 * Cleanup old switches from the network graph. Old switches are those
75 * which have no controller in the registry.
Jonathan Hart369875b2014-02-13 10:00:31 -080076 */
77 private class SwitchCleanup implements ControlChangeCallback, Runnable {
78 @Override
79 public void run() {
80 String old = Thread.currentThread().getName();
81 Thread.currentThread().setName("SwitchCleanup@" + old);
Jonathan Hartb3e1b052014-04-02 16:01:12 -070082
Jonathan Hart369875b2014-02-13 10:00:31 -080083 try {
Jonathan Hart88770672014-04-02 18:08:30 -070084 if (log.isTraceEnabled()) {
85 log.trace("Running cleanup thread");
86 }
Jonathan Hart369875b2014-02-13 10:00:31 -080087 switchCleanup();
Jonathan Hart369875b2014-02-13 10:00:31 -080088 } finally {
89 cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
Jonathan Hart88770672014-04-02 18:08:30 -070090 TimeUnit.SECONDS);
Jonathan Hart369875b2014-02-13 10:00:31 -080091 Thread.currentThread().setName(old);
92 }
93 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -070094
Jonathan Hart88770672014-04-02 18:08:30 -070095 /**
96 * First half of the switch cleanup operation. This method will attempt
97 * to get control of any switch it sees without a controller via the
98 * registry.
99 */
Jonathan Hart369875b2014-02-13 10:00:31 -0800100 private void switchCleanup() {
Jonathan Hart88770672014-04-02 18:08:30 -0700101 Iterable<Switch> switches = networkGraph.getSwitches();
Jonathan Hart369875b2014-02-13 10:00:31 -0800102
Jonathan Hart88770672014-04-02 18:08:30 -0700103 if (log.isTraceEnabled()) {
104 log.trace("Checking for inactive switches");
105 }
106 // For each switch check if a controller exists in controller registry
107 for (Switch sw: switches) {
108 try {
109 String controller =
110 registryService.getControllerForSwitch(sw.getDpid());
111 if (controller == null) {
112 log.debug("Requesting control to set switch {} INACTIVE",
113 HexString.toHexString(sw.getDpid()));
114 registryService.requestControl(sw.getDpid(), this);
115 }
116 } catch (RegistryException e) {
117 log.error("Caught RegistryException in cleanup thread", e);
118 }
119 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800120 }
121
Jonathan Hart88770672014-04-02 18:08:30 -0700122 /**
123 * Second half of the switch cleanup operation. If the registry grants
124 * control of a switch, we can be sure no other instance is writing
125 * this switch to the network graph, so we can remove it now.
126 * @param dpid the dpid of the switch we requested control for
127 * @param hasControl whether we got control or not
128 */
129 @Override
130 public void controlChanged(long dpid, boolean hasControl) {
131 if (hasControl) {
132 log.debug("Got control to set switch {} INACTIVE",
133 HexString.toHexString(dpid));
Jonathan Harte02cf542014-04-02 16:24:44 -0700134
Jonathan Hart88770672014-04-02 18:08:30 -0700135 SwitchEvent switchEvent = new SwitchEvent(dpid);
136 networkGraphDiscoveryInterface.
137 removeSwitchDiscoveryEvent(switchEvent);
138 registryService.releaseControl(dpid);
139 }
140 }
Jonathan Hart369875b2014-02-13 10:00:31 -0800141 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800142
Jonathan Hart88770672014-04-02 18:08:30 -0700143 @Override
144 public void linkDiscoveryUpdate(LDUpdate update) {
145 LinkEvent linkEvent = new LinkEvent(update.getSrc(),
146 (long) update.getSrcPort(), update.getDst(),
147 (long) update.getDstPort());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700148
Jonathan Hart88770672014-04-02 18:08:30 -0700149 switch (update.getOperation()) {
150 case LINK_ADDED:
151 networkGraphDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
152 break;
153 case LINK_UPDATED:
154 // We don't use the LINK_UPDATED event (unsure what it means)
155 break;
156 case LINK_REMOVED:
157 networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
158 break;
159 default:
160 break;
161 }
162 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800163
Jonathan Hart88770672014-04-02 18:08:30 -0700164 @Override
165 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
166 PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
167 networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
168 linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
169 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800170
Jonathan Hart88770672014-04-02 18:08:30 -0700171 @Override
172 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
173 PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
174 networkGraphDiscoveryInterface.removePortDiscoveryEvent(portEvent);
175 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800176
Jonathan Hart88770672014-04-02 18:08:30 -0700177 @Override
178 public void addedSwitch(IOFSwitch sw) {
179 // TODO Not very robust
180 if (!registryService.hasControl(sw.getId())) {
181 return;
182 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800183
Jonathan Hart88770672014-04-02 18:08:30 -0700184 SwitchEvent switchEvent = new SwitchEvent(sw.getId());
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700185
Jonathan Hart88770672014-04-02 18:08:30 -0700186 List<PortEvent> portEvents = new ArrayList<PortEvent>();
187 for (OFPhysicalPort port : sw.getPorts()) {
188 portEvents.add(new PortEvent(sw.getId(), (long) port.getPortNumber()));
189 }
190 networkGraphDiscoveryInterface
191 .putSwitchDiscoveryEvent(switchEvent, portEvents);
Toshio Koide2f570c12014-02-06 16:55:32 -0800192
Jonathan Hart88770672014-04-02 18:08:30 -0700193 for (OFPhysicalPort port : sw.getPorts()) {
194 // Allow links to be discovered on this port now that it's
195 // in the database
196 linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
197 }
198 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800199
Jonathan Hart88770672014-04-02 18:08:30 -0700200 @Override
201 public void removedSwitch(IOFSwitch sw) {
202 // We don't use this event - switch remove is done by cleanup thread
203 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800204
Jonathan Hart88770672014-04-02 18:08:30 -0700205 @Override
206 public void switchPortChanged(Long switchId) {
207 // We don't use this event
208 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800209
Jonathan Hart88770672014-04-02 18:08:30 -0700210 @Override
211 public String getName() {
212 // TODO Auto-generated method stub
213 return null;
214 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800215
Jonathan Hart88770672014-04-02 18:08:30 -0700216 /* *****************
217 * IFloodlightModule
218 * *****************/
Toshio Koide2f570c12014-02-06 16:55:32 -0800219
Jonathan Hart88770672014-04-02 18:08:30 -0700220 @Override
221 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
222 return null;
223 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800224
Jonathan Hart88770672014-04-02 18:08:30 -0700225 @Override
226 public Map<Class<? extends IFloodlightService>, IFloodlightService>
227 getServiceImpls() {
228 return null;
229 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800230
Jonathan Hart88770672014-04-02 18:08:30 -0700231 @Override
232 public Collection<Class<? extends IFloodlightService>>
233 getModuleDependencies() {
234 Collection<Class<? extends IFloodlightService>> l =
235 new ArrayList<Class<? extends IFloodlightService>>();
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800236 l.add(IFloodlightProviderService.class);
237 l.add(ILinkDiscoveryService.class);
Jonathan Hart369875b2014-02-13 10:00:31 -0800238 l.add(IThreadPoolService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800239 l.add(IControllerRegistryService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800240 l.add(INetworkGraphService.class);
Jonathan Hartebbe6a62014-04-02 16:10:25 -0700241 l.add(IOnosDeviceService.class);
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800242 return l;
Jonathan Hart88770672014-04-02 18:08:30 -0700243 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800244
Jonathan Hart88770672014-04-02 18:08:30 -0700245 @Override
246 public void init(FloodlightModuleContext context)
247 throws FloodlightModuleException {
248 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
249 linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
250 registryService = context.getServiceImpl(IControllerRegistryService.class);
251 onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
Toshio Koide2f570c12014-02-06 16:55:32 -0800252
Jonathan Hart88770672014-04-02 18:08:30 -0700253 networkGraphService = context.getServiceImpl(INetworkGraphService.class);
254 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800255
Jonathan Hart88770672014-04-02 18:08:30 -0700256 @Override
257 public void startUp(FloodlightModuleContext context) {
258 floodlightProvider.addOFSwitchListener(this);
259 linkDiscovery.addListener(this);
260 onosDeviceService.addOnosDeviceListener(this);
Toshio Koide2f570c12014-02-06 16:55:32 -0800261
Jonathan Hart88770672014-04-02 18:08:30 -0700262 networkGraph = networkGraphService.getNetworkGraph();
263 networkGraphDiscoveryInterface =
264 networkGraphService.getNetworkGraphDiscoveryInterface();
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700265
Jonathan Hart88770672014-04-02 18:08:30 -0700266 // Run the cleanup thread
267 String enableCleanup =
268 context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
269 if (enableCleanup != null
270 && enableCleanup.equalsIgnoreCase("false")) {
271 cleanupEnabled = false;
272 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700273
Jonathan Hart88770672014-04-02 18:08:30 -0700274 log.debug("Cleanup thread is {}enabled", (cleanupEnabled) ? "" : "not ");
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700275
Jonathan Hart88770672014-04-02 18:08:30 -0700276 if (cleanupEnabled) {
277 IThreadPoolService threadPool =
278 context.getServiceImpl(IThreadPoolService.class);
279 cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
280 new SwitchCleanup());
281 // Run the cleanup task immediately on startup
282 cleanupTask.reschedule(0, TimeUnit.SECONDS);
283 }
284 }
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700285
Jonathan Hart88770672014-04-02 18:08:30 -0700286 @Override
287 public void onosDeviceAdded(OnosDevice device) {
288 log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());
TeruUd1c5b652014-03-24 13:58:46 -0700289
Jonathan Hart88770672014-04-02 18:08:30 -0700290 SwitchPort sp = new SwitchPort(device.getSwitchDPID(),
291 (long) device.getSwitchPort());
292 List<SwitchPort> spLists = new ArrayList<SwitchPort>();
293 spLists.add(sp);
294 DeviceEvent event = new DeviceEvent(device.getMacAddress());
295 event.setAttachmentPoints(spLists);
296 event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
297 if (device.getIpv4Address() != null) {
298 InetAddress ip = InetAddresses.fromInteger(device.getIpv4Address());
299 event.addIpAddress(ip);
300 }
301 // Does not use vlan info now.
Jonathan Hartb3e1b052014-04-02 16:01:12 -0700302
Jonathan Hart88770672014-04-02 18:08:30 -0700303 networkGraphDiscoveryInterface.putDeviceDiscoveryEvent(event);
304 }
TeruUd1c5b652014-03-24 13:58:46 -0700305
Jonathan Hart88770672014-04-02 18:08:30 -0700306 @Override
307 public void onosDeviceRemoved(OnosDevice device) {
308 log.debug("Called onosDeviceRemoved");
309 DeviceEvent event = new DeviceEvent(device.getMacAddress());
310 networkGraphDiscoveryInterface.removeDeviceDiscoveryEvent(event);
311 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800312}