blob: 168c06d9816c71e3c421a89221c75dd4493f7e68 [file] [log] [blame]
tom7ef8ff92014-09-17 13:08:06 -07001/**
2 * Copyright 2011, Big Switch Networks, Inc.
3 * Originally created by David Erickson, Stanford University
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 **/
17
tom9c94c5b2014-09-17 13:14:42 -070018package org.onlab.onos.openflow.controller.impl;
tom7ef8ff92014-09-17 13:08:06 -070019
20import java.lang.management.ManagementFactory;
21import java.lang.management.RuntimeMXBean;
22import java.net.InetSocketAddress;
23import java.util.HashMap;
24import java.util.Map;
25import java.util.concurrent.Executors;
26
27import org.jboss.netty.bootstrap.ServerBootstrap;
28import org.jboss.netty.channel.ChannelPipelineFactory;
29import org.jboss.netty.channel.group.ChannelGroup;
30import org.jboss.netty.channel.group.DefaultChannelGroup;
31import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
tom9c94c5b2014-09-17 13:14:42 -070032import org.onlab.onos.openflow.controller.Dpid;
33import org.onlab.onos.openflow.controller.driver.OpenFlowAgent;
34import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver;
35import org.onlab.onos.openflow.drivers.impl.DriverManager;
tom7ef8ff92014-09-17 13:08:06 -070036import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
37import org.projectfloodlight.openflow.protocol.OFFactories;
38import org.projectfloodlight.openflow.protocol.OFFactory;
39import org.projectfloodlight.openflow.protocol.OFVersion;
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43
44/**
45 * The main controller class. Handles all setup and network listeners
46 * - Distributed ownership control of switch through IControllerRegistryService
47 */
48public class Controller {
49
50 protected static final Logger log = LoggerFactory.getLogger(Controller.class);
51 static final String ERROR_DATABASE =
52 "The controller could not communicate with the system database.";
53 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
54 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
55
56 // The controllerNodeIPsCache maps Controller IDs to their IP address.
57 // It's only used by handleControllerNodeIPsChanged
58 protected HashMap<String, String> controllerNodeIPsCache;
59
60 private ChannelGroup cg;
61
62 // Configuration options
63 protected int openFlowPort = 6633;
64 protected int workerThreads = 0;
65
66 // Start time of the controller
67 protected long systemStartTime;
68
69 private OpenFlowAgent agent;
70
71 private NioServerSocketChannelFactory execFactory;
72
73 // Perf. related configuration
74 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
75
76 // ***************
77 // Getters/Setters
78 // ***************
79
80 public OFFactory getOFMessageFactory10() {
81 return FACTORY10;
82 }
83
84
85 public OFFactory getOFMessageFactory13() {
86 return FACTORY13;
87 }
88
89
90
91 public Map<String, String> getControllerNodeIPs() {
92 // We return a copy of the mapping so we can guarantee that
93 // the mapping return is the same as one that will be (or was)
94 // dispatched to IHAListeners
95 HashMap<String, String> retval = new HashMap<String, String>();
96 synchronized (controllerNodeIPsCache) {
97 retval.putAll(controllerNodeIPsCache);
98 }
99 return retval;
100 }
101
102
103 public long getSystemStartTime() {
104 return (this.systemStartTime);
105 }
106
107 // **************
108 // Initialization
109 // **************
110
111 /**
112 * Tell controller that we're ready to accept switches loop.
113 */
114 public void run() {
115
116 try {
117 final ServerBootstrap bootstrap = createServerBootStrap();
118
119 bootstrap.setOption("reuseAddr", true);
120 bootstrap.setOption("child.keepAlive", true);
121 bootstrap.setOption("child.tcpNoDelay", true);
122 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
123
124 ChannelPipelineFactory pfact =
125 new OpenflowPipelineFactory(this, null);
126 bootstrap.setPipelineFactory(pfact);
127 InetSocketAddress sa = new InetSocketAddress(openFlowPort);
128 cg = new DefaultChannelGroup();
129 cg.add(bootstrap.bind(sa));
130
131 log.info("Listening for switch connections on {}", sa);
132 } catch (Exception e) {
133 throw new RuntimeException(e);
134 }
135
136 }
137
138 private ServerBootstrap createServerBootStrap() {
139
140 if (workerThreads == 0) {
141 execFactory = new NioServerSocketChannelFactory(
142 Executors.newCachedThreadPool(),
143 Executors.newCachedThreadPool());
144 return new ServerBootstrap(execFactory);
145 } else {
146 execFactory = new NioServerSocketChannelFactory(
147 Executors.newCachedThreadPool(),
148 Executors.newCachedThreadPool(), workerThreads);
149 return new ServerBootstrap(execFactory);
150 }
151 }
152
153 public void setConfigParams(Map<String, String> configParams) {
154 String ofPort = configParams.get("openflowport");
155 if (ofPort != null) {
156 this.openFlowPort = Integer.parseInt(ofPort);
157 }
158 log.debug("OpenFlow port set to {}", this.openFlowPort);
159 String threads = configParams.get("workerthreads");
tom1679e182014-10-09 13:50:45 -0700160 this.workerThreads = threads != null ? Integer.parseInt(threads) : 16;
tom7ef8ff92014-09-17 13:08:06 -0700161 log.debug("Number of worker threads set to {}", this.workerThreads);
162 }
163
164
165 /**
166 * Initialize internal data structures.
167 */
168 public void init(Map<String, String> configParams) {
169 // These data structures are initialized here because other
170 // module's startUp() might be called before ours
171 this.controllerNodeIPsCache = new HashMap<String, String>();
172
173 setConfigParams(configParams);
174 this.systemStartTime = System.currentTimeMillis();
175
176
177 }
178
179 // **************
180 // Utility methods
181 // **************
182
183 public Map<String, Long> getMemory() {
184 Map<String, Long> m = new HashMap<String, Long>();
185 Runtime runtime = Runtime.getRuntime();
186 m.put("total", runtime.totalMemory());
187 m.put("free", runtime.freeMemory());
188 return m;
189 }
190
191
192 public Long getUptime() {
193 RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
194 return rb.getUptime();
195 }
196
197 /**
198 * Forward to the driver-manager to get an IOFSwitch instance.
199 * @param desc
200 * @return switch instance
201 */
202 protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
203 OFDescStatsReply desc, OFVersion ofv) {
204 OpenFlowSwitchDriver sw = DriverManager.getSwitch(new Dpid(dpid),
205 desc, ofv);
206 sw.setAgent(agent);
207 sw.setRoleHandler(new RoleManager(sw));
208 return sw;
209 }
210
211 public void start(OpenFlowAgent ag) {
212 log.info("Starting OpenFlow IO");
213 this.agent = ag;
214 this.init(new HashMap<String, String>());
215 this.run();
216 }
217
218
219 public void stop() {
220 log.info("Stopping OpenFlow IO");
221 execFactory.shutdown();
222 cg.close();
223 }
224
225}