blob: e2cb693cdee3e6cdf5aab3348df429f04f4b14d2 [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
alshabib1f44e8e2014-08-14 15:19:57 -070064
65 private IOFSwitchManager switchManager;
66
alshabib54ebd9c2014-08-27 18:38:41 -070067 private ChannelGroup cg;
68
alshabib1f44e8e2014-08-14 15:19:57 -070069 // Configuration options
70 protected int openFlowPort = 6633;
71 protected int workerThreads = 0;
72
alshabib1f44e8e2014-08-14 15:19:57 -070073 // Start time of the controller
74 protected long systemStartTime;
75
76 // Flag to always flush flow table on switch reconnect (HA or otherwise)
77 protected boolean alwaysClearFlowsOnSwAdd = false;
alshabib6171f182014-09-02 19:00:32 -070078 private OpenFlowAgent agent;
alshabib1f44e8e2014-08-14 15:19:57 -070079
80 // Perf. related configuration
81 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
82 protected static final int BATCH_MAX_SIZE = 100;
83 protected static final boolean ALWAYS_DECODE_ETH = true;
84
alshabib1f44e8e2014-08-14 15:19:57 -070085 // ***************
86 // Getters/Setters
87 // ***************
88
alshabib1f44e8e2014-08-14 15:19:57 -070089 public OFFactory getOFMessageFactory10() {
90 return FACTORY10;
91 }
92
93
94 public OFFactory getOFMessageFactory13() {
95 return FACTORY13;
96 }
97
98
99
100 public Map<String, String> getControllerNodeIPs() {
101 // We return a copy of the mapping so we can guarantee that
102 // the mapping return is the same as one that will be (or was)
103 // dispatched to IHAListeners
104 HashMap<String, String> retval = new HashMap<String, String>();
105 synchronized (controllerNodeIPsCache) {
106 retval.putAll(controllerNodeIPsCache);
107 }
108 return retval;
109 }
110
111
112 public long getSystemStartTime() {
113 return (this.systemStartTime);
114 }
115
alshabib1f44e8e2014-08-14 15:19:57 -0700116 // **************
117 // Initialization
118 // **************
119
120 /**
121 * Tell controller that we're ready to accept switches loop.
alshabib1f44e8e2014-08-14 15:19:57 -0700122 */
123 @LogMessageDocs({
alshabib6171f182014-09-02 19:00:32 -0700124 @LogMessageDoc(message = "Listening for switch connections on {address}",
125 explanation = "The controller is ready and listening for new" +
126 " switch connections"),
127 @LogMessageDoc(message = "Storage exception in controller " +
128 "updates loop; terminating process",
129 explanation = ERROR_DATABASE,
130 recommendation = LogMessageDoc.CHECK_CONTROLLER),
131 @LogMessageDoc(level = "ERROR",
132 message = "Exception in controller updates loop",
133 explanation = "Failed to dispatch controller event",
134 recommendation = LogMessageDoc.GENERIC_ACTION)
alshabib1f44e8e2014-08-14 15:19:57 -0700135 })
136 public void run() {
137
138 try {
139 final ServerBootstrap bootstrap = createServerBootStrap();
140
141 bootstrap.setOption("reuseAddr", true);
142 bootstrap.setOption("child.keepAlive", true);
143 bootstrap.setOption("child.tcpNoDelay", true);
144 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
145
146 ChannelPipelineFactory pfact =
147 new OpenflowPipelineFactory(this, null);
148 bootstrap.setPipelineFactory(pfact);
149 InetSocketAddress sa = new InetSocketAddress(openFlowPort);
alshabib54ebd9c2014-08-27 18:38:41 -0700150 cg = new DefaultChannelGroup();
alshabib1f44e8e2014-08-14 15:19:57 -0700151 cg.add(bootstrap.bind(sa));
152
153 log.info("Listening for switch connections on {}", sa);
154 } catch (Exception e) {
155 throw new RuntimeException(e);
156 }
157
158 }
159
160 private ServerBootstrap createServerBootStrap() {
161 if (workerThreads == 0) {
162 return new ServerBootstrap(
163 new NioServerSocketChannelFactory(
164 Executors.newCachedThreadPool(),
165 Executors.newCachedThreadPool()));
166 } else {
167 return new ServerBootstrap(
168 new NioServerSocketChannelFactory(
169 Executors.newCachedThreadPool(),
170 Executors.newCachedThreadPool(), workerThreads));
171 }
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) {
alshabib1f44e8e2014-08-14 15:19:57 -0700235 log.info("Initialising OpenFlow Lib and 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() {
243 cg.close();
244 }
245
alshabib1f44e8e2014-08-14 15:19:57 -0700246}