blob: 0c28a6fad73ba3224e341430b26fc9578842f47b [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;
Jonathan Harta0d12492015-07-16 12:03:41 -070024import org.onlab.util.ItemNotFoundException;
25import org.onosproject.net.DeviceId;
alshabibb452fd72015-04-22 20:46:20 -070026import org.onosproject.net.driver.DefaultDriverData;
27import org.onosproject.net.driver.DefaultDriverHandler;
28import org.onosproject.net.driver.Driver;
29import org.onosproject.net.driver.DriverService;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.openflow.controller.Dpid;
31import org.onosproject.openflow.controller.driver.OpenFlowAgent;
32import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
tom7ef8ff92014-09-17 13:08:06 -070033import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
34import org.projectfloodlight.openflow.protocol.OFFactories;
35import org.projectfloodlight.openflow.protocol.OFFactory;
36import org.projectfloodlight.openflow.protocol.OFVersion;
37import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080040import java.lang.management.ManagementFactory;
41import java.lang.management.RuntimeMXBean;
42import java.net.InetSocketAddress;
43import java.util.HashMap;
44import java.util.Map;
45import java.util.concurrent.Executors;
46
47import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuska80b0a802015-07-17 08:43:30 -070048import static org.onosproject.net.DeviceId.deviceId;
49import static org.onosproject.openflow.controller.Dpid.uri;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080050
tom7ef8ff92014-09-17 13:08:06 -070051
52/**
53 * The main controller class. Handles all setup and network listeners
54 * - Distributed ownership control of switch through IControllerRegistryService
55 */
56public class Controller {
57
58 protected static final Logger log = LoggerFactory.getLogger(Controller.class);
alshabib9eab22f2014-10-20 17:17:31 -070059
tom7ef8ff92014-09-17 13:08:06 -070060 protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
61 protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
62
tom7ef8ff92014-09-17 13:08:06 -070063 protected HashMap<String, String> controllerNodeIPsCache;
64
65 private ChannelGroup cg;
66
67 // Configuration options
68 protected int openFlowPort = 6633;
69 protected int workerThreads = 0;
70
71 // Start time of the controller
72 protected long systemStartTime;
73
74 private OpenFlowAgent agent;
75
76 private NioServerSocketChannelFactory execFactory;
77
78 // Perf. related configuration
79 protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
alshabibb452fd72015-04-22 20:46:20 -070080 private DriverService driverService;
tom7ef8ff92014-09-17 13:08:06 -070081
82 // ***************
83 // Getters/Setters
84 // ***************
85
86 public OFFactory getOFMessageFactory10() {
87 return FACTORY10;
88 }
89
90
91 public OFFactory getOFMessageFactory13() {
92 return FACTORY13;
93 }
94
95
tom7ef8ff92014-09-17 13:08:06 -070096 public Map<String, String> getControllerNodeIPs() {
97 // We return a copy of the mapping so we can guarantee that
98 // the mapping return is the same as one that will be (or was)
99 // dispatched to IHAListeners
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800100 HashMap<String, String> retval = new HashMap<>();
tom7ef8ff92014-09-17 13:08:06 -0700101 synchronized (controllerNodeIPsCache) {
102 retval.putAll(controllerNodeIPsCache);
103 }
104 return retval;
105 }
106
107
108 public long getSystemStartTime() {
109 return (this.systemStartTime);
110 }
111
112 // **************
113 // Initialization
114 // **************
115
116 /**
117 * Tell controller that we're ready to accept switches loop.
118 */
119 public void run() {
120
121 try {
122 final ServerBootstrap bootstrap = createServerBootStrap();
123
124 bootstrap.setOption("reuseAddr", true);
125 bootstrap.setOption("child.keepAlive", true);
126 bootstrap.setOption("child.tcpNoDelay", true);
127 bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
128
129 ChannelPipelineFactory pfact =
130 new OpenflowPipelineFactory(this, null);
131 bootstrap.setPipelineFactory(pfact);
132 InetSocketAddress sa = new InetSocketAddress(openFlowPort);
133 cg = new DefaultChannelGroup();
134 cg.add(bootstrap.bind(sa));
135
136 log.info("Listening for switch connections on {}", sa);
137 } catch (Exception e) {
138 throw new RuntimeException(e);
139 }
140
141 }
142
143 private ServerBootstrap createServerBootStrap() {
144
145 if (workerThreads == 0) {
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800146 execFactory = new NioServerSocketChannelFactory(
147 Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
148 Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")));
tom7ef8ff92014-09-17 13:08:06 -0700149 return new ServerBootstrap(execFactory);
150 } else {
151 execFactory = new NioServerSocketChannelFactory(
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800152 Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
153 Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")), workerThreads);
tom7ef8ff92014-09-17 13:08:06 -0700154 return new ServerBootstrap(execFactory);
155 }
156 }
157
158 public void setConfigParams(Map<String, String> configParams) {
159 String ofPort = configParams.get("openflowport");
160 if (ofPort != null) {
161 this.openFlowPort = Integer.parseInt(ofPort);
162 }
alshabibb452fd72015-04-22 20:46:20 -0700163
tom7ef8ff92014-09-17 13:08:06 -0700164 log.debug("OpenFlow port set to {}", this.openFlowPort);
165 String threads = configParams.get("workerthreads");
tom1679e182014-10-09 13:50:45 -0700166 this.workerThreads = threads != null ? Integer.parseInt(threads) : 16;
tom7ef8ff92014-09-17 13:08:06 -0700167 log.debug("Number of worker threads set to {}", this.workerThreads);
168 }
169
170
171 /**
172 * Initialize internal data structures.
173 */
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800174 public void init() {
tom7ef8ff92014-09-17 13:08:06 -0700175 // These data structures are initialized here because other
176 // module's startUp() might be called before ours
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800177 this.controllerNodeIPsCache = new HashMap<>();
tom7ef8ff92014-09-17 13:08:06 -0700178
tom7ef8ff92014-09-17 13:08:06 -0700179 this.systemStartTime = System.currentTimeMillis();
tom7ef8ff92014-09-17 13:08:06 -0700180 }
181
182 // **************
183 // Utility methods
184 // **************
185
186 public Map<String, Long> getMemory() {
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800187 Map<String, Long> m = new HashMap<>();
tom7ef8ff92014-09-17 13:08:06 -0700188 Runtime runtime = Runtime.getRuntime();
189 m.put("total", runtime.totalMemory());
190 m.put("free", runtime.freeMemory());
191 return m;
192 }
193
194
195 public Long getUptime() {
196 RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
197 return rb.getUptime();
198 }
199
200 /**
201 * Forward to the driver-manager to get an IOFSwitch instance.
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800202 *
Yuta HIGUCHI5c947272014-11-03 21:39:21 -0800203 * @param dpid data path id
204 * @param desc switch description
Thomas Vachuska6f94ded2015-02-21 14:02:38 -0800205 * @param ofv OpenFlow version
tom7ef8ff92014-09-17 13:08:06 -0700206 * @return switch instance
207 */
208 protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
alshabibb452fd72015-04-22 20:46:20 -0700209 OFDescStatsReply desc,
210 OFVersion ofv) {
Jonathan Harta0d12492015-07-16 12:03:41 -0700211 Dpid dpidObj = new Dpid(dpid);
212
213 Driver driver;
214 try {
Sho SHIMIZUbc82ebb2015-08-25 10:15:21 -0700215 driver = driverService.getDriver(DeviceId.deviceId(Dpid.uri(dpidObj)));
Jonathan Harta0d12492015-07-16 12:03:41 -0700216 } catch (ItemNotFoundException e) {
217 driver = driverService.getDriver(desc.getMfrDesc(), desc.getHwDesc(), desc.getSwDesc());
218 }
alshabibb452fd72015-04-22 20:46:20 -0700219
Thomas Vachuska3358af22015-05-19 18:40:34 -0700220 if (driver != null && driver.hasBehaviour(OpenFlowSwitchDriver.class)) {
Thomas Vachuska80b0a802015-07-17 08:43:30 -0700221 Dpid did = new Dpid(dpid);
222 DefaultDriverHandler handler =
223 new DefaultDriverHandler(new DefaultDriverData(driver, deviceId(uri(did))));
224 OpenFlowSwitchDriver ofSwitchDriver =
225 driver.createBehaviour(handler, OpenFlowSwitchDriver.class);
226 ofSwitchDriver.init(did, desc, ofv);
alshabibb452fd72015-04-22 20:46:20 -0700227 ofSwitchDriver.setAgent(agent);
228 ofSwitchDriver.setRoleHandler(new RoleManager(ofSwitchDriver));
Saurav Das100e3b82015-04-30 11:12:10 -0700229 log.info("OpenFlow handshaker found for device {}: {}", dpid, ofSwitchDriver);
alshabibb452fd72015-04-22 20:46:20 -0700230 return ofSwitchDriver;
231 }
232 log.error("No OpenFlow driver for {} : {}", dpid, desc);
233 return null;
234
tom7ef8ff92014-09-17 13:08:06 -0700235 }
236
alshabibb452fd72015-04-22 20:46:20 -0700237 public void start(OpenFlowAgent ag, DriverService driverService) {
tom7ef8ff92014-09-17 13:08:06 -0700238 log.info("Starting OpenFlow IO");
239 this.agent = ag;
alshabibb452fd72015-04-22 20:46:20 -0700240 this.driverService = driverService;
Jonathan Hartbbd91d42015-02-27 11:18:04 -0800241 this.init();
tom7ef8ff92014-09-17 13:08:06 -0700242 this.run();
243 }
244
245
246 public void stop() {
247 log.info("Stopping OpenFlow IO");
tom7ef8ff92014-09-17 13:08:06 -0700248 cg.close();
Thomas Vachuska1c681d72015-05-18 14:58:53 -0700249 execFactory.shutdown();
tom7ef8ff92014-09-17 13:08:06 -0700250 }
251
252}