blob: 6ae3abb90c75aa61233d73bdfc5768b617da0f26 [file] [log] [blame]
alshabib1f44e8e2014-08-14 15:19:57 -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
tom9ccd7812014-08-25 22:43:19 -070018package org.onlab.onos.of.controller.impl.internal;
alshabib1f44e8e2014-08-14 15:19:57 -070019
20import java.lang.management.ManagementFactory;
21import java.lang.management.RuntimeMXBean;
22import java.net.InetSocketAddress;
alshabib1f44e8e2014-08-14 15:19:57 -070023import java.util.HashMap;
alshabib1f44e8e2014-08-14 15:19:57 -070024import java.util.Map;
alshabib1f44e8e2014-08-14 15:19:57 -070025import java.util.concurrent.Executors;
26
alshabib1f44e8e2014-08-14 15:19:57 -070027import 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;
alshabib54ebd9c2014-08-27 18:38:41 -070032import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
33import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
34import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
alshabib1f44e8e2014-08-14 15:19:57 -070035import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
36import org.projectfloodlight.openflow.protocol.OFFactories;
37import org.projectfloodlight.openflow.protocol.OFFactory;
alshabib1f44e8e2014-08-14 15:19:57 -070038import org.projectfloodlight.openflow.protocol.OFVersion;
alshabib1f44e8e2014-08-14 15:19:57 -070039import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
42
43/**
44 * The main controller class. Handles all setup and network listeners
45 * - Distributed ownership control of switch through IControllerRegistryService
46 */
alshabib1f44e8e2014-08-14 15:19:57 -070047public class Controller {
48
49 protected static final Logger log = LoggerFactory.getLogger(Controller.class);
50 static final String ERROR_DATABASE =
51 "The controller could not communicate with the system database.";
52 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
53 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
54
alshabib54ebd9c2014-08-27 18:38:41 -070055
alshabib1f44e8e2014-08-14 15:19:57 -070056
57 // The controllerNodeIPsCache maps Controller IDs to their IP address.
58 // It's only used by handleControllerNodeIPsChanged
59 protected HashMap<String, String> controllerNodeIPsCache;
60
alshabib1f44e8e2014-08-14 15:19:57 -070061
62 private IOFSwitchManager switchManager;
63
alshabib54ebd9c2014-08-27 18:38:41 -070064 private ChannelGroup cg;
65
alshabib1f44e8e2014-08-14 15:19:57 -070066 // Configuration options
67 protected int openFlowPort = 6633;
68 protected int workerThreads = 0;
69
alshabib1f44e8e2014-08-14 15:19:57 -070070 // Start time of the controller
71 protected long systemStartTime;
72
73 // Flag to always flush flow table on switch reconnect (HA or otherwise)
74 protected boolean alwaysClearFlowsOnSwAdd = false;
alshabib54ebd9c2014-08-27 18:38:41 -070075 private OpenFlowSwitchAgent agent;
alshabib1f44e8e2014-08-14 15:19:57 -070076
77 // Perf. related configuration
78 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
79 protected static final int BATCH_MAX_SIZE = 100;
80 protected static final boolean ALWAYS_DECODE_ETH = true;
81
alshabib1f44e8e2014-08-14 15:19:57 -070082 // ***************
83 // Getters/Setters
84 // ***************
85
86
87 public synchronized void setIOFSwitchManager(IOFSwitchManager swManager) {
88 this.switchManager = swManager;
alshabib1f44e8e2014-08-14 15:19:57 -070089 }
90
alshabib1f44e8e2014-08-14 15:19:57 -070091 public OFFactory getOFMessageFactory10() {
92 return FACTORY10;
93 }
94
95
96 public OFFactory getOFMessageFactory13() {
97 return FACTORY13;
98 }
99
100
101
102 public Map<String, String> getControllerNodeIPs() {
103 // We return a copy of the mapping so we can guarantee that
104 // the mapping return is the same as one that will be (or was)
105 // dispatched to IHAListeners
106 HashMap<String, String> retval = new HashMap<String, String>();
107 synchronized (controllerNodeIPsCache) {
108 retval.putAll(controllerNodeIPsCache);
109 }
110 return retval;
111 }
112
113
114 public long getSystemStartTime() {
115 return (this.systemStartTime);
116 }
117
alshabib1f44e8e2014-08-14 15:19:57 -0700118 // **************
119 // Initialization
120 // **************
121
122 /**
123 * Tell controller that we're ready to accept switches loop.
alshabib1f44e8e2014-08-14 15:19:57 -0700124 */
125 @LogMessageDocs({
126 @LogMessageDoc(message = "Listening for switch connections on {address}",
127 explanation = "The controller is ready and listening for new" +
128 " switch connections"),
129 @LogMessageDoc(message = "Storage exception in controller " +
130 "updates loop; terminating process",
131 explanation = ERROR_DATABASE,
132 recommendation = LogMessageDoc.CHECK_CONTROLLER),
133 @LogMessageDoc(level = "ERROR",
134 message = "Exception in controller updates loop",
135 explanation = "Failed to dispatch controller event",
136 recommendation = LogMessageDoc.GENERIC_ACTION)
137 })
138 public void run() {
139
140 try {
141 final ServerBootstrap bootstrap = createServerBootStrap();
142
143 bootstrap.setOption("reuseAddr", true);
144 bootstrap.setOption("child.keepAlive", true);
145 bootstrap.setOption("child.tcpNoDelay", true);
146 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
147
148 ChannelPipelineFactory pfact =
149 new OpenflowPipelineFactory(this, null);
150 bootstrap.setPipelineFactory(pfact);
151 InetSocketAddress sa = new InetSocketAddress(openFlowPort);
alshabib54ebd9c2014-08-27 18:38:41 -0700152 cg = new DefaultChannelGroup();
alshabib1f44e8e2014-08-14 15:19:57 -0700153 cg.add(bootstrap.bind(sa));
154
155 log.info("Listening for switch connections on {}", sa);
156 } catch (Exception e) {
157 throw new RuntimeException(e);
158 }
159
160 }
161
162 private ServerBootstrap createServerBootStrap() {
163 if (workerThreads == 0) {
164 return new ServerBootstrap(
165 new NioServerSocketChannelFactory(
166 Executors.newCachedThreadPool(),
167 Executors.newCachedThreadPool()));
168 } else {
169 return new ServerBootstrap(
170 new NioServerSocketChannelFactory(
171 Executors.newCachedThreadPool(),
172 Executors.newCachedThreadPool(), workerThreads));
173 }
174 }
175
176 public void setConfigParams(Map<String, String> configParams) {
177 String ofPort = configParams.get("openflowport");
178 if (ofPort != null) {
179 this.openFlowPort = Integer.parseInt(ofPort);
180 }
181 log.debug("OpenFlow port set to {}", this.openFlowPort);
182 String threads = configParams.get("workerthreads");
183 if (threads != null) {
184 this.workerThreads = Integer.parseInt(threads);
185 }
186 log.debug("Number of worker threads set to {}", this.workerThreads);
alshabib1f44e8e2014-08-14 15:19:57 -0700187 }
188
189
190 /**
191 * Initialize internal data structures.
192 */
193 public void init(Map<String, String> configParams) {
194 // These data structures are initialized here because other
195 // module's startUp() might be called before ours
alshabib1f44e8e2014-08-14 15:19:57 -0700196 this.controllerNodeIPsCache = new HashMap<String, String>();
197
198 setConfigParams(configParams);
199 this.systemStartTime = System.currentTimeMillis();
alshabib54ebd9c2014-08-27 18:38:41 -0700200
alshabib1f44e8e2014-08-14 15:19:57 -0700201
alshabib1f44e8e2014-08-14 15:19:57 -0700202 }
203
204 /**
205 * Startup all of the controller's components.
206 */
207 @LogMessageDoc(message = "Waiting for storage source",
208 explanation = "The system database is not yet ready",
209 recommendation = "If this message persists, this indicates " +
210 "that the system database has failed to start. " +
211 LogMessageDoc.CHECK_CONTROLLER)
212 public synchronized void startupComponents() {
alshabib54ebd9c2014-08-27 18:38:41 -0700213 //TODO do something maybe
alshabib1f44e8e2014-08-14 15:19:57 -0700214 }
215
216 // **************
alshabib1f44e8e2014-08-14 15:19:57 -0700217 // Utility methods
218 // **************
219
alshabib1f44e8e2014-08-14 15:19:57 -0700220 public Map<String, Long> getMemory() {
221 Map<String, Long> m = new HashMap<String, Long>();
222 Runtime runtime = Runtime.getRuntime();
223 m.put("total", runtime.totalMemory());
224 m.put("free", runtime.freeMemory());
225 return m;
226 }
227
228
229 public Long getUptime() {
230 RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
231 return rb.getUptime();
232 }
233
234 /**
235 * Forward to the driver-manager to get an IOFSwitch instance.
236 * @param desc
tom9ccd7812014-08-25 22:43:19 -0700237 * @return switch instance
alshabib1f44e8e2014-08-14 15:19:57 -0700238 */
alshabib54ebd9c2014-08-27 18:38:41 -0700239 protected AbstractOpenFlowSwitch getOFSwitchInstance(OFDescStatsReply desc, OFVersion ofv) {
240 AbstractOpenFlowSwitch sw = switchManager.getSwitchImpl(desc.getMfrDesc(), desc.getHwDesc(),
alshabib1f44e8e2014-08-14 15:19:57 -0700241 desc.getSwDesc(), ofv);
alshabib54ebd9c2014-08-27 18:38:41 -0700242 sw.setAgent(agent);
243 return sw;
alshabib1f44e8e2014-08-14 15:19:57 -0700244 }
245
alshabib54ebd9c2014-08-27 18:38:41 -0700246 public void start(OpenFlowSwitchAgent ag) {
alshabib1f44e8e2014-08-14 15:19:57 -0700247 log.info("Initialising OpenFlow Lib and IO");
alshabib54ebd9c2014-08-27 18:38:41 -0700248 this.agent = ag;
alshabib1f44e8e2014-08-14 15:19:57 -0700249 this.init(new HashMap<String, String>());
250 this.startupComponents();
251 this.run();
252 }
253
alshabib54ebd9c2014-08-27 18:38:41 -0700254
255 public void stop() {
256 cg.close();
257 }
258
alshabib1f44e8e2014-08-14 15:19:57 -0700259}