blob: 5b0c8ac6a8f8ee7502511a55513763bb3dcfd81c [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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
Brian O'Connorabafb502014-12-02 22:26:20 -080017package org.onosproject.openflow.controller.impl;
tom7ef8ff92014-09-17 13:08:06 -070018
tom7ef8ff92014-09-17 13:08:06 -070019import org.jboss.netty.bootstrap.ServerBootstrap;
20import org.jboss.netty.channel.ChannelPipelineFactory;
21import org.jboss.netty.channel.group.ChannelGroup;
22import org.jboss.netty.channel.group.DefaultChannelGroup;
23import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
alshabibb452fd72015-04-22 20:46:20 -070024import org.onosproject.net.driver.DefaultDriverData;
25import org.onosproject.net.driver.DefaultDriverHandler;
26import org.onosproject.net.driver.Driver;
27import org.onosproject.net.driver.DriverService;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.openflow.controller.Dpid;
29import org.onosproject.openflow.controller.driver.OpenFlowAgent;
30import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
tom7ef8ff92014-09-17 13:08:06 -070031import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
32import org.projectfloodlight.openflow.protocol.OFFactories;
33import org.projectfloodlight.openflow.protocol.OFFactory;
34import org.projectfloodlight.openflow.protocol.OFVersion;
35import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080038import java.lang.management.ManagementFactory;
39import java.lang.management.RuntimeMXBean;
40import java.net.InetSocketAddress;
41import java.util.HashMap;
42import java.util.Map;
43import java.util.concurrent.Executors;
44
45import static org.onlab.util.Tools.groupedThreads;
46
tom7ef8ff92014-09-17 13:08:06 -070047
48/**
49 * The main controller class. Handles all setup and network listeners
50 * - Distributed ownership control of switch through IControllerRegistryService
51 */
52public class Controller {
53
54 protected static final Logger log = LoggerFactory.getLogger(Controller.class);
alshabib9eab22f2014-10-20 17:17:31 -070055
tom7ef8ff92014-09-17 13:08:06 -070056 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
57 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
58
tom7ef8ff92014-09-17 13:08:06 -070059 protected HashMap<String, String> controllerNodeIPsCache;
60
61 private ChannelGroup cg;
62
63 // Configuration options
64 protected int openFlowPort = 6633;
65 protected int workerThreads = 0;
66
67 // Start time of the controller
68 protected long systemStartTime;
69
70 private OpenFlowAgent agent;
71
72 private NioServerSocketChannelFactory execFactory;
73
74 // Perf. related configuration
75 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
alshabibb452fd72015-04-22 20:46:20 -070076 private DriverService driverService;
tom7ef8ff92014-09-17 13:08:06 -070077
78 // ***************
79 // Getters/Setters
80 // ***************
81
82 public OFFactory getOFMessageFactory10() {
83 return FACTORY10;
84 }
85
86
87 public OFFactory getOFMessageFactory13() {
88 return FACTORY13;
89 }
90
91
tom7ef8ff92014-09-17 13:08:06 -070092 public Map<String, String> getControllerNodeIPs() {
93 // We return a copy of the mapping so we can guarantee that
94 // the mapping return is the same as one that will be (or was)
95 // dispatched to IHAListeners
Jonathan Hartbbd91d42015-02-27 11:18:04 -080096 HashMap<String, String> retval = new HashMap<>();
tom7ef8ff92014-09-17 13:08:06 -070097 synchronized (controllerNodeIPsCache) {
98 retval.putAll(controllerNodeIPsCache);
99 }
100 return retval;
101 }
102
103
104 public long getSystemStartTime() {
105 return (this.systemStartTime);
106 }
107
108 // **************
109 // Initialization
110 // **************
111
112 /**
113 * Tell controller that we're ready to accept switches loop.
114 */
115 public void run() {
116
117 try {
118 final ServerBootstrap bootstrap = createServerBootStrap();
119
120 bootstrap.setOption("reuseAddr", true);
121 bootstrap.setOption("child.keepAlive", true);
122 bootstrap.setOption("child.tcpNoDelay", true);
123 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
124
125 ChannelPipelineFactory pfact =
126 new OpenflowPipelineFactory(this, null);
127 bootstrap.setPipelineFactory(pfact);
128 InetSocketAddress sa = new InetSocketAddress(openFlowPort);
129 cg = new DefaultChannelGroup();
130 cg.add(bootstrap.bind(sa));
131
132 log.info("Listening for switch connections on {}", sa);
133 } catch (Exception e) {
134 throw new RuntimeException(e);
135 }
136
137 }
138
139 private ServerBootstrap createServerBootStrap() {
140
141 if (workerThreads == 0) {
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800142 execFactory = new NioServerSocketChannelFactory(
143 Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
144 Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")));
tom7ef8ff92014-09-17 13:08:06 -0700145 return new ServerBootstrap(execFactory);
146 } else {
147 execFactory = new NioServerSocketChannelFactory(
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800148 Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
149 Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")), workerThreads);
tom7ef8ff92014-09-17 13:08:06 -0700150 return new ServerBootstrap(execFactory);
151 }
152 }
153
154 public void setConfigParams(Map<String, String> configParams) {
155 String ofPort = configParams.get("openflowport");
156 if (ofPort != null) {
157 this.openFlowPort = Integer.parseInt(ofPort);
158 }
alshabibb452fd72015-04-22 20:46:20 -0700159
tom7ef8ff92014-09-17 13:08:06 -0700160 log.debug("OpenFlow port set to {}", this.openFlowPort);
161 String threads = configParams.get("workerthreads");
tom1679e182014-10-09 13:50:45 -0700162 this.workerThreads = threads != null ? Integer.parseInt(threads) : 16;
tom7ef8ff92014-09-17 13:08:06 -0700163 log.debug("Number of worker threads set to {}", this.workerThreads);
164 }
165
166
167 /**
168 * Initialize internal data structures.
169 */
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800170 public void init() {
tom7ef8ff92014-09-17 13:08:06 -0700171 // These data structures are initialized here because other
172 // module's startUp() might be called before ours
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800173 this.controllerNodeIPsCache = new HashMap<>();
tom7ef8ff92014-09-17 13:08:06 -0700174
tom7ef8ff92014-09-17 13:08:06 -0700175 this.systemStartTime = System.currentTimeMillis();
tom7ef8ff92014-09-17 13:08:06 -0700176 }
177
178 // **************
179 // Utility methods
180 // **************
181
182 public Map<String, Long> getMemory() {
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800183 Map<String, Long> m = new HashMap<>();
tom7ef8ff92014-09-17 13:08:06 -0700184 Runtime runtime = Runtime.getRuntime();
185 m.put("total", runtime.totalMemory());
186 m.put("free", runtime.freeMemory());
187 return m;
188 }
189
190
191 public Long getUptime() {
192 RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
193 return rb.getUptime();
194 }
195
196 /**
197 * Forward to the driver-manager to get an IOFSwitch instance.
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800198 *
Yuta HIGUCHI5c947272014-11-03 21:39:21 -0800199 * @param dpid data path id
200 * @param desc switch description
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800201 * @param ofv OpenFlow version
tom7ef8ff92014-09-17 13:08:06 -0700202 * @return switch instance
203 */
204 protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
alshabibb452fd72015-04-22 20:46:20 -0700205 OFDescStatsReply desc,
206 OFVersion ofv) {
207 Driver driver = driverService
208 .getDriver(desc.getMfrDesc(), desc.getHwDesc(), desc.getSwDesc());
209
Thomas Vachuska3358af22015-05-19 18:40:34 -0700210 if (driver != null && driver.hasBehaviour(OpenFlowSwitchDriver.class)) {
alshabibb452fd72015-04-22 20:46:20 -0700211 OpenFlowSwitchDriver ofSwitchDriver = driver.createBehaviour(new DefaultDriverHandler(
212 new DefaultDriverData(driver)), OpenFlowSwitchDriver.class);
213 ofSwitchDriver.init(new Dpid(dpid), desc, ofv);
214 ofSwitchDriver.setAgent(agent);
215 ofSwitchDriver.setRoleHandler(new RoleManager(ofSwitchDriver));
Saurav Das100e3b82015-04-30 11:12:10 -0700216 log.info("OpenFlow handshaker found for device {}: {}", dpid, ofSwitchDriver);
alshabibb452fd72015-04-22 20:46:20 -0700217 return ofSwitchDriver;
218 }
219 log.error("No OpenFlow driver for {} : {}", dpid, desc);
220 return null;
221
tom7ef8ff92014-09-17 13:08:06 -0700222 }
223
alshabibb452fd72015-04-22 20:46:20 -0700224 public void start(OpenFlowAgent ag, DriverService driverService) {
tom7ef8ff92014-09-17 13:08:06 -0700225 log.info("Starting OpenFlow IO");
226 this.agent = ag;
alshabibb452fd72015-04-22 20:46:20 -0700227 this.driverService = driverService;
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800228 this.init();
tom7ef8ff92014-09-17 13:08:06 -0700229 this.run();
230 }
231
232
233 public void stop() {
234 log.info("Stopping OpenFlow IO");
tom7ef8ff92014-09-17 13:08:06 -0700235 cg.close();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700236 execFactory.shutdown();
tom7ef8ff92014-09-17 13:08:06 -0700237 }
238
239}