2 * Copyright 2014-2015 Open Networking Laboratory
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onosproject.openflow.controller.impl;
19 import org.jboss.netty.bootstrap.ServerBootstrap;
20 import org.jboss.netty.channel.ChannelPipelineFactory;
21 import org.jboss.netty.channel.group.ChannelGroup;
22 import org.jboss.netty.channel.group.DefaultChannelGroup;
23 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
24 import org.onlab.util.ItemNotFoundException;
25 import org.onosproject.net.DeviceId;
26 import org.onosproject.net.driver.DefaultDriverData;
27 import org.onosproject.net.driver.DefaultDriverHandler;
28 import org.onosproject.net.driver.Driver;
29 import org.onosproject.net.driver.DriverService;
30 import org.onosproject.openflow.controller.Dpid;
31 import org.onosproject.openflow.controller.driver.OpenFlowAgent;
32 import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
33 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
34 import org.projectfloodlight.openflow.protocol.OFFactories;
35 import org.projectfloodlight.openflow.protocol.OFFactory;
36 import org.projectfloodlight.openflow.protocol.OFVersion;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 import java.lang.management.ManagementFactory;
41 import java.lang.management.RuntimeMXBean;
42 import java.net.InetSocketAddress;
43 import java.util.HashMap;
45 import java.util.concurrent.Executors;
47 import static org.onlab.util.Tools.groupedThreads;
48 import static org.onosproject.net.DeviceId.deviceId;
49 import static org.onosproject.openflow.controller.Dpid.uri;
53 * The main controller class. Handles all setup and network listeners
54 * - Distributed ownership control of switch through IControllerRegistryService
56 public class Controller {
58 protected static final Logger log = LoggerFactory.getLogger(Controller.class);
60 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
61 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
63 protected HashMap<String, String> controllerNodeIPsCache;
65 private ChannelGroup cg;
67 // Configuration options
68 protected int openFlowPort = 6633;
69 protected int workerThreads = 0;
71 // Start time of the controller
72 protected long systemStartTime;
74 private OpenFlowAgent agent;
76 private NioServerSocketChannelFactory execFactory;
78 // Perf. related configuration
79 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
80 private DriverService driverService;
86 public OFFactory getOFMessageFactory10() {
91 public OFFactory getOFMessageFactory13() {
96 public Map<String, String> getControllerNodeIPs() {
97 // We return a copy of the mapping so we can guarantee that
98 // the mapping return is the same as one that will be (or was)
99 // dispatched to IHAListeners
100 HashMap<String, String> retval = new HashMap<>();
101 synchronized (controllerNodeIPsCache) {
102 retval.putAll(controllerNodeIPsCache);
108 public long getSystemStartTime() {
109 return (this.systemStartTime);
117 * Tell controller that we're ready to accept switches loop.
122 final ServerBootstrap bootstrap = createServerBootStrap();
124 bootstrap.setOption("reuseAddr", true);
125 bootstrap.setOption("child.keepAlive", true);
126 bootstrap.setOption("child.tcpNoDelay", true);
127 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
129 ChannelPipelineFactory pfact =
130 new OpenflowPipelineFactory(this, null);
131 bootstrap.setPipelineFactory(pfact);
132 InetSocketAddress sa = new InetSocketAddress(openFlowPort);
133 cg = new DefaultChannelGroup();
134 cg.add(bootstrap.bind(sa));
136 log.info("Listening for switch connections on {}", sa);
137 } catch (Exception e) {
138 throw new RuntimeException(e);
143 private ServerBootstrap createServerBootStrap() {
145 if (workerThreads == 0) {
146 execFactory = new NioServerSocketChannelFactory(
147 Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
148 Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")));
149 return new ServerBootstrap(execFactory);
151 execFactory = new NioServerSocketChannelFactory(
152 Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
153 Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")), workerThreads);
154 return new ServerBootstrap(execFactory);
158 public void setConfigParams(Map<String, String> configParams) {
159 String ofPort = configParams.get("openflowport");
160 if (ofPort != null) {
161 this.openFlowPort = Integer.parseInt(ofPort);
164 log.debug("OpenFlow port set to {}", this.openFlowPort);
165 String threads = configParams.get("workerthreads");
166 this.workerThreads = threads != null ? Integer.parseInt(threads) : 16;
167 log.debug("Number of worker threads set to {}", this.workerThreads);
172 * Initialize internal data structures.
175 // These data structures are initialized here because other
176 // module's startUp() might be called before ours
177 this.controllerNodeIPsCache = new HashMap<>();
179 this.systemStartTime = System.currentTimeMillis();
186 public Map<String, Long> getMemory() {
187 Map<String, Long> m = new HashMap<>();
188 Runtime runtime = Runtime.getRuntime();
189 m.put("total", runtime.totalMemory());
190 m.put("free", runtime.freeMemory());
195 public Long getUptime() {
196 RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
197 return rb.getUptime();
201 * Forward to the driver-manager to get an IOFSwitch instance.
203 * @param dpid data path id
204 * @param desc switch description
205 * @param ofv OpenFlow version
206 * @return switch instance
208 protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
209 OFDescStatsReply desc,
211 Dpid dpidObj = new Dpid(dpid);
215 driver = driverService.getDriver(DeviceId.deviceId(Dpid.uri(dpidObj)));
216 } catch (ItemNotFoundException e) {
217 driver = driverService.getDriver(desc.getMfrDesc(), desc.getHwDesc(), desc.getSwDesc());
220 if (driver != null && driver.hasBehaviour(OpenFlowSwitchDriver.class)) {
221 Dpid did = new Dpid(dpid);
222 DefaultDriverHandler handler =
223 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId(uri(did))));
224 OpenFlowSwitchDriver ofSwitchDriver =
225 driver.createBehaviour(handler, OpenFlowSwitchDriver.class);
226 ofSwitchDriver.init(did, desc, ofv);
227 ofSwitchDriver.setAgent(agent);
228 ofSwitchDriver.setRoleHandler(new RoleManager(ofSwitchDriver));
229 log.info("OpenFlow handshaker found for device {}: {}", dpid, ofSwitchDriver);
230 return ofSwitchDriver;
232 log.error("No OpenFlow driver for {} : {}", dpid, desc);
237 public void start(OpenFlowAgent ag, DriverService driverService) {
238 log.info("Starting OpenFlow IO");
240 this.driverService = driverService;
247 log.info("Stopping OpenFlow IO");
249 execFactory.shutdown();