blob: b88a9ec4f3a4ac7cb5ce2f471cb9f1be0858d51f [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;
alshabibd777b202014-08-28 17:52:55 -070032import org.onlab.onos.of.controller.Dpid;
alshabib54ebd9c2014-08-27 18:38:41 -070033import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
34import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
35import org.onlab.onos.of.controller.impl.internal.OpenFlowControllerImpl.OpenFlowSwitchAgent;
alshabibd777b202014-08-28 17:52:55 -070036import org.onlab.onos.of.drivers.DriverManager;
alshabib1f44e8e2014-08-14 15:19:57 -070037import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
38import org.projectfloodlight.openflow.protocol.OFFactories;
39import org.projectfloodlight.openflow.protocol.OFFactory;
alshabib1f44e8e2014-08-14 15:19:57 -070040import org.projectfloodlight.openflow.protocol.OFVersion;
alshabib1f44e8e2014-08-14 15:19:57 -070041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
44
45/**
46 * The main controller class. Handles all setup and network listeners
47 * - Distributed ownership control of switch through IControllerRegistryService
48 */
alshabib1f44e8e2014-08-14 15:19:57 -070049public class Controller {
50
51 protected static final Logger log = LoggerFactory.getLogger(Controller.class);
52 static final String ERROR_DATABASE =
53 "The controller could not communicate with the system database.";
54 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
55 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
56
alshabib54ebd9c2014-08-27 18:38:41 -070057
alshabib1f44e8e2014-08-14 15:19:57 -070058
59 // The controllerNodeIPsCache maps Controller IDs to their IP address.
60 // It's only used by handleControllerNodeIPsChanged
61 protected HashMap<String, String> controllerNodeIPsCache;
62
alshabib1f44e8e2014-08-14 15:19:57 -070063
64 private IOFSwitchManager switchManager;
65
alshabib54ebd9c2014-08-27 18:38:41 -070066 private ChannelGroup cg;
67
alshabib1f44e8e2014-08-14 15:19:57 -070068 // Configuration options
69 protected int openFlowPort = 6633;
70 protected int workerThreads = 0;
71
alshabib1f44e8e2014-08-14 15:19:57 -070072 // Start time of the controller
73 protected long systemStartTime;
74
75 // Flag to always flush flow table on switch reconnect (HA or otherwise)
76 protected boolean alwaysClearFlowsOnSwAdd = false;
alshabib54ebd9c2014-08-27 18:38:41 -070077 private OpenFlowSwitchAgent agent;
alshabib1f44e8e2014-08-14 15:19:57 -070078
79 // Perf. related configuration
80 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
81 protected static final int BATCH_MAX_SIZE = 100;
82 protected static final boolean ALWAYS_DECODE_ETH = true;
83
alshabib1f44e8e2014-08-14 15:19:57 -070084 // ***************
85 // Getters/Setters
86 // ***************
87
alshabib1f44e8e2014-08-14 15:19:57 -070088 public OFFactory getOFMessageFactory10() {
89 return FACTORY10;
90 }
91
92
93 public OFFactory getOFMessageFactory13() {
94 return FACTORY13;
95 }
96
97
98
99 public Map<String, String> getControllerNodeIPs() {
100 // We return a copy of the mapping so we can guarantee that
101 // the mapping return is the same as one that will be (or was)
102 // dispatched to IHAListeners
103 HashMap<String, String> retval = new HashMap<String, String>();
104 synchronized (controllerNodeIPsCache) {
105 retval.putAll(controllerNodeIPsCache);
106 }
107 return retval;
108 }
109
110
111 public long getSystemStartTime() {
112 return (this.systemStartTime);
113 }
114
alshabib1f44e8e2014-08-14 15:19:57 -0700115 // **************
116 // Initialization
117 // **************
118
119 /**
120 * Tell controller that we're ready to accept switches loop.
alshabib1f44e8e2014-08-14 15:19:57 -0700121 */
122 @LogMessageDocs({
123 @LogMessageDoc(message = "Listening for switch connections on {address}",
124 explanation = "The controller is ready and listening for new" +
125 " switch connections"),
126 @LogMessageDoc(message = "Storage exception in controller " +
127 "updates loop; terminating process",
128 explanation = ERROR_DATABASE,
129 recommendation = LogMessageDoc.CHECK_CONTROLLER),
130 @LogMessageDoc(level = "ERROR",
131 message = "Exception in controller updates loop",
132 explanation = "Failed to dispatch controller event",
133 recommendation = LogMessageDoc.GENERIC_ACTION)
134 })
135 public void run() {
136
137 try {
138 final ServerBootstrap bootstrap = createServerBootStrap();
139
140 bootstrap.setOption("reuseAddr", true);
141 bootstrap.setOption("child.keepAlive", true);
142 bootstrap.setOption("child.tcpNoDelay", true);
143 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
144
145 ChannelPipelineFactory pfact =
146 new OpenflowPipelineFactory(this, null);
147 bootstrap.setPipelineFactory(pfact);
148 InetSocketAddress sa = new InetSocketAddress(openFlowPort);
alshabib54ebd9c2014-08-27 18:38:41 -0700149 cg = new DefaultChannelGroup();
alshabib1f44e8e2014-08-14 15:19:57 -0700150 cg.add(bootstrap.bind(sa));
151
152 log.info("Listening for switch connections on {}", sa);
153 } catch (Exception e) {
154 throw new RuntimeException(e);
155 }
156
157 }
158
159 private ServerBootstrap createServerBootStrap() {
160 if (workerThreads == 0) {
161 return new ServerBootstrap(
162 new NioServerSocketChannelFactory(
163 Executors.newCachedThreadPool(),
164 Executors.newCachedThreadPool()));
165 } else {
166 return new ServerBootstrap(
167 new NioServerSocketChannelFactory(
168 Executors.newCachedThreadPool(),
169 Executors.newCachedThreadPool(), workerThreads));
170 }
171 }
172
173 public void setConfigParams(Map<String, String> configParams) {
174 String ofPort = configParams.get("openflowport");
175 if (ofPort != null) {
176 this.openFlowPort = Integer.parseInt(ofPort);
177 }
178 log.debug("OpenFlow port set to {}", this.openFlowPort);
179 String threads = configParams.get("workerthreads");
180 if (threads != null) {
181 this.workerThreads = Integer.parseInt(threads);
182 }
183 log.debug("Number of worker threads set to {}", this.workerThreads);
alshabib1f44e8e2014-08-14 15:19:57 -0700184 }
185
186
187 /**
188 * Initialize internal data structures.
189 */
190 public void init(Map<String, String> configParams) {
191 // These data structures are initialized here because other
192 // module's startUp() might be called before ours
alshabib1f44e8e2014-08-14 15:19:57 -0700193 this.controllerNodeIPsCache = new HashMap<String, String>();
194
195 setConfigParams(configParams);
196 this.systemStartTime = System.currentTimeMillis();
alshabib54ebd9c2014-08-27 18:38:41 -0700197
alshabib1f44e8e2014-08-14 15:19:57 -0700198
alshabib1f44e8e2014-08-14 15:19:57 -0700199 }
200
alshabib1f44e8e2014-08-14 15:19:57 -0700201 // **************
alshabib1f44e8e2014-08-14 15:19:57 -0700202 // Utility methods
203 // **************
204
alshabib1f44e8e2014-08-14 15:19:57 -0700205 public Map<String, Long> getMemory() {
206 Map<String, Long> m = new HashMap<String, Long>();
207 Runtime runtime = Runtime.getRuntime();
208 m.put("total", runtime.totalMemory());
209 m.put("free", runtime.freeMemory());
210 return m;
211 }
212
213
214 public Long getUptime() {
215 RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
216 return rb.getUptime();
217 }
218
219 /**
220 * Forward to the driver-manager to get an IOFSwitch instance.
221 * @param desc
tom9ccd7812014-08-25 22:43:19 -0700222 * @return switch instance
alshabib1f44e8e2014-08-14 15:19:57 -0700223 */
alshabibd777b202014-08-28 17:52:55 -0700224 protected AbstractOpenFlowSwitch getOFSwitchInstance(long dpid,
225 OFDescStatsReply desc, OFVersion ofv) {
226 AbstractOpenFlowSwitch sw = DriverManager.getOFSwitchImpl(new Dpid(dpid),
227 desc, ofv);
alshabib54ebd9c2014-08-27 18:38:41 -0700228 sw.setAgent(agent);
229 return sw;
alshabib1f44e8e2014-08-14 15:19:57 -0700230 }
231
alshabib54ebd9c2014-08-27 18:38:41 -0700232 public void start(OpenFlowSwitchAgent ag) {
alshabib1f44e8e2014-08-14 15:19:57 -0700233 log.info("Initialising OpenFlow Lib and IO");
alshabib54ebd9c2014-08-27 18:38:41 -0700234 this.agent = ag;
alshabib1f44e8e2014-08-14 15:19:57 -0700235 this.init(new HashMap<String, String>());
alshabib1f44e8e2014-08-14 15:19:57 -0700236 this.run();
237 }
238
alshabib54ebd9c2014-08-27 18:38:41 -0700239
240 public void stop() {
241 cg.close();
242 }
243
alshabib1f44e8e2014-08-14 15:19:57 -0700244}