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