0c28a6fad73ba3224e341430b26fc9578842f47b
[onosfw.git] /
1 /*
2  * Copyright 2014-2015 Open Networking Laboratory
3  *
4  * 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
7  *
8  *     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.
15  */
16
17 package org.onosproject.openflow.controller.impl;
18
19 import org.jboss.netty.bootstrap.ServerBootstrap;
20 import org.jboss.netty.channel.ChannelPipelineFactory;
21 import org.jboss.netty.channel.group.ChannelGroup;
22 import org.jboss.netty.channel.group.DefaultChannelGroup;
23 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
24 import org.onlab.util.ItemNotFoundException;
25 import org.onosproject.net.DeviceId;
26 import org.onosproject.net.driver.DefaultDriverData;
27 import org.onosproject.net.driver.DefaultDriverHandler;
28 import org.onosproject.net.driver.Driver;
29 import org.onosproject.net.driver.DriverService;
30 import org.onosproject.openflow.controller.Dpid;
31 import org.onosproject.openflow.controller.driver.OpenFlowAgent;
32 import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
33 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
34 import org.projectfloodlight.openflow.protocol.OFFactories;
35 import org.projectfloodlight.openflow.protocol.OFFactory;
36 import org.projectfloodlight.openflow.protocol.OFVersion;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import java.lang.management.ManagementFactory;
41 import java.lang.management.RuntimeMXBean;
42 import java.net.InetSocketAddress;
43 import java.util.HashMap;
44 import java.util.Map;
45 import java.util.concurrent.Executors;
46
47 import static org.onlab.util.Tools.groupedThreads;
48 import static org.onosproject.net.DeviceId.deviceId;
49 import static org.onosproject.openflow.controller.Dpid.uri;
50
51
52 /**
53  * The main controller class.  Handles all setup and network listeners
54  * - Distributed ownership control of switch through IControllerRegistryService
55  */
56 public class Controller {
57
58     protected static final Logger log = LoggerFactory.getLogger(Controller.class);
59
60     protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
61     protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
62
63     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;
80     private DriverService driverService;
81
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
96     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
100         HashMap<String, String> retval = new HashMap<>();
101         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) {
146             execFactory = new NioServerSocketChannelFactory(
147                     Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
148                     Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")));
149             return new ServerBootstrap(execFactory);
150         } else {
151             execFactory = new NioServerSocketChannelFactory(
152                     Executors.newCachedThreadPool(groupedThreads("onos/of", "boss-%d")),
153                     Executors.newCachedThreadPool(groupedThreads("onos/of", "worker-%d")), workerThreads);
154             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         }
163
164         log.debug("OpenFlow port set to {}", this.openFlowPort);
165         String threads = configParams.get("workerthreads");
166         this.workerThreads = threads != null ? Integer.parseInt(threads) : 16;
167         log.debug("Number of worker threads set to {}", this.workerThreads);
168     }
169
170
171     /**
172      * Initialize internal data structures.
173      */
174     public void init() {
175         // These data structures are initialized here because other
176         // module's startUp() might be called before ours
177         this.controllerNodeIPsCache = new HashMap<>();
178
179         this.systemStartTime = System.currentTimeMillis();
180     }
181
182     // **************
183     // Utility methods
184     // **************
185
186     public Map<String, Long> getMemory() {
187         Map<String, Long> m = new HashMap<>();
188         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.
202      *
203      * @param dpid data path id
204      * @param desc switch description
205      * @param ofv  OpenFlow version
206      * @return switch instance
207      */
208     protected OpenFlowSwitchDriver getOFSwitchInstance(long dpid,
209                                                        OFDescStatsReply desc,
210                                                        OFVersion ofv) {
211         Dpid dpidObj = new Dpid(dpid);
212
213         Driver driver;
214         try {
215             driver = driverService.getDriver(DeviceId.deviceId(Dpid.uri(dpidObj)));
216         } catch (ItemNotFoundException e) {
217             driver = driverService.getDriver(desc.getMfrDesc(), desc.getHwDesc(), desc.getSwDesc());
218         }
219
220         if (driver != null && driver.hasBehaviour(OpenFlowSwitchDriver.class)) {
221             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);
227             ofSwitchDriver.setAgent(agent);
228             ofSwitchDriver.setRoleHandler(new RoleManager(ofSwitchDriver));
229             log.info("OpenFlow handshaker found for device {}: {}", dpid, ofSwitchDriver);
230             return ofSwitchDriver;
231         }
232         log.error("No OpenFlow driver for {} : {}", dpid, desc);
233         return null;
234
235     }
236
237     public void start(OpenFlowAgent ag, DriverService driverService) {
238         log.info("Starting OpenFlow IO");
239         this.agent = ag;
240         this.driverService = driverService;
241         this.init();
242         this.run();
243     }
244
245
246     public void stop() {
247         log.info("Stopping OpenFlow IO");
248         cg.close();
249         execFactory.shutdown();
250     }
251
252 }