blob: 7c6b2cef6f2800971e9c5d201b760014d6e5e528 [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
alshabibf1216ed2014-09-03 11:53:54 -070018package org.onlab.onos.of.controller.impl;
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;
alshabib6171f182014-09-02 19:00:32 -070033import org.onlab.onos.of.controller.driver.OpenFlowAgent;
34import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver;
alshabib54ebd9c2014-08-27 18:38:41 -070035import org.onlab.onos.of.controller.impl.annotations.LogMessageDoc;
36import org.onlab.onos.of.controller.impl.annotations.LogMessageDocs;
alshabibf1216ed2014-09-03 11:53:54 -070037import org.onlab.onos.of.drivers.impl.DriverManager;
alshabib1f44e8e2014-08-14 15:19:57 -070038import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
39import org.projectfloodlight.openflow.protocol.OFFactories;
40import org.projectfloodlight.openflow.protocol.OFFactory;
alshabib1f44e8e2014-08-14 15:19:57 -070041import org.projectfloodlight.openflow.protocol.OFVersion;
alshabib1f44e8e2014-08-14 15:19:57 -070042import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
45
46/**
47 * The main controller class. Handles all setup and network listeners
48 * - Distributed ownership control of switch through IControllerRegistryService
49 */
alshabib1f44e8e2014-08-14 15:19:57 -070050public class Controller {
51
52 protected static final Logger log = LoggerFactory.getLogger(Controller.class);
53 static final String ERROR_DATABASE =
54 "The controller could not communicate with the system database.";
55 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
56 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
57
alshabib54ebd9c2014-08-27 18:38:41 -070058
alshabib1f44e8e2014-08-14 15:19:57 -070059
60 // The controllerNodeIPsCache maps Controller IDs to their IP address.
61 // It's only used by handleControllerNodeIPsChanged
62 protected HashMap<String, String> controllerNodeIPsCache;
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;
alshabib6171f182014-09-02 19:00:32 -070075 private OpenFlowAgent agent;
alshabib1f44e8e2014-08-14 15:19:57 -070076
alshabib6f5460b2014-09-03 14:46:17 -070077 private NioServerSocketChannelFactory execFactory;
78
alshabib1f44e8e2014-08-14 15:19:57 -070079 // 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({
alshabib6171f182014-09-02 19:00:32 -0700123 @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)
alshabib1f44e8e2014-08-14 15:19:57 -0700134 })
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() {
alshabib6f5460b2014-09-03 14:46:17 -0700160
alshabib1f44e8e2014-08-14 15:19:57 -0700161 if (workerThreads == 0) {
alshabib6f5460b2014-09-03 14:46:17 -0700162 execFactory = new NioServerSocketChannelFactory(
163 Executors.newCachedThreadPool(),
164 Executors.newCachedThreadPool());
165 return new ServerBootstrap(execFactory);
alshabib1f44e8e2014-08-14 15:19:57 -0700166 } else {
alshabib6f5460b2014-09-03 14:46:17 -0700167 execFactory = new NioServerSocketChannelFactory(
168 Executors.newCachedThreadPool(),
169 Executors.newCachedThreadPool(), workerThreads);
170 return new ServerBootstrap(execFactory);
alshabib1f44e8e2014-08-14 15:19:57 -0700171 }
172 }
173
174 public void setConfigParams(Map<String, String> configParams) {
175 String ofPort = configParams.get("openflowport");
176 if (ofPort != null) {
177 this.openFlowPort = Integer.parseInt(ofPort);
178 }
179 log.debug("OpenFlow port set to {}", this.openFlowPort);
180 String threads = configParams.get("workerthreads");
181 if (threads != null) {
182 this.workerThreads = Integer.parseInt(threads);
183 }
184 log.debug("Number of worker threads set to {}", this.workerThreads);
alshabib1f44e8e2014-08-14 15:19:57 -0700185 }
186
187
188 /**
189 * Initialize internal data structures.
190 */
191 public void init(Map<String, String> configParams) {
192 // These data structures are initialized here because other
193 // module's startUp() might be called before ours
alshabib1f44e8e2014-08-14 15:19:57 -0700194 this.controllerNodeIPsCache = new HashMap<String, String>();
195
196 setConfigParams(configParams);
197 this.systemStartTime = System.currentTimeMillis();
alshabib54ebd9c2014-08-27 18:38:41 -0700198
alshabib1f44e8e2014-08-14 15:19:57 -0700199
alshabib1f44e8e2014-08-14 15:19:57 -0700200 }
201
alshabib1f44e8e2014-08-14 15:19:57 -0700202 // **************
alshabib1f44e8e2014-08-14 15:19:57 -0700203 // Utility methods
204 // **************
205
alshabib1f44e8e2014-08-14 15:19:57 -0700206 public Map<String, Long> getMemory() {
207 Map<String, Long> m = new HashMap<String, Long>();
208 Runtime runtime = Runtime.getRuntime();
209 m.put("total", runtime.totalMemory());
210 m.put("free", runtime.freeMemory());
211 return m;
212 }
213
214
215 public Long getUptime() {
216 RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
217 return rb.getUptime();
218 }
219
220 /**
221 * Forward to the driver-manager to get an IOFSwitch instance.
222 * @param desc
tom9ccd7812014-08-25 22:43:19 -0700223 * @return switch instance
alshabib1f44e8e2014-08-14 15:19:57 -0700224 */
alshabib6171f182014-09-02 19:00:32 -0700225 protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
alshabibd777b202014-08-28 17:52:55 -0700226 OFDescStatsReply desc, OFVersion ofv) {
alshabib6171f182014-09-02 19:00:32 -0700227 OpenFlowSwitchDriver sw = DriverManager.getSwitch(new Dpid(dpid),
alshabibd777b202014-08-28 17:52:55 -0700228 desc, ofv);
alshabib54ebd9c2014-08-27 18:38:41 -0700229 sw.setAgent(agent);
alshabib6171f182014-09-02 19:00:32 -0700230 sw.setRoleHandler(new RoleManager(sw));
alshabib54ebd9c2014-08-27 18:38:41 -0700231 return sw;
alshabib1f44e8e2014-08-14 15:19:57 -0700232 }
233
alshabib6171f182014-09-02 19:00:32 -0700234 public void start(OpenFlowAgent ag) {
tom69012372014-09-08 01:58:45 -0700235 log.info("Starting OpenFlow IO");
alshabib54ebd9c2014-08-27 18:38:41 -0700236 this.agent = ag;
alshabib1f44e8e2014-08-14 15:19:57 -0700237 this.init(new HashMap<String, String>());
alshabib1f44e8e2014-08-14 15:19:57 -0700238 this.run();
239 }
240
alshabib54ebd9c2014-08-27 18:38:41 -0700241
242 public void stop() {
tom69012372014-09-08 01:58:45 -0700243 log.info("Stopping OpenFlow IO");
alshabib6f5460b2014-09-03 14:46:17 -0700244 execFactory.shutdown();
alshabib54ebd9c2014-08-27 18:38:41 -0700245 cg.close();
246 }
247
alshabib1f44e8e2014-08-14 15:19:57 -0700248}