Merge "Fixed inappropriate uses of log level INFO"
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / core / internal / ControllerIO.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
10
11 import java.io.IOException;
12 import java.net.InetAddress;
13 import java.net.NetworkInterface;
14 import java.net.SocketException;
15 import java.nio.channels.SelectionKey;
16 import java.nio.channels.Selector;
17 import java.nio.channels.ServerSocketChannel;
18 import java.nio.channels.spi.SelectorProvider;
19 import java.util.Iterator;
20
21 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 public class ControllerIO {
26     private static final Logger logger = LoggerFactory
27             .getLogger(ControllerIO.class);
28     private static Short defaultOpenFlowPort = 6633;
29     private Short openFlowPort;
30     private InetAddress controllerIP;
31     private NetworkInterface netInt;
32     private SelectionKey serverSelectionKey;
33     private IController listener;
34     private ServerSocketChannel serverSocket;
35     private Selector selector;
36     private boolean running;
37     private Thread controllerIOThread;
38
39     public ControllerIO(IController l) {
40         this.listener = l;
41         this.openFlowPort = defaultOpenFlowPort;
42         String portString = System.getProperty("of.listenPort");
43         if (portString != null) {
44             try {
45                 openFlowPort = Short.decode(portString).shortValue();
46             } catch (NumberFormatException e) {
47                 logger.warn("Invalid port:{}, use default({})", portString,
48                         openFlowPort);
49             }
50         }
51         String addressString = System.getProperty("of.address");
52         if (addressString != null) {
53             try {
54                 controllerIP = InetAddress.getByName(addressString);
55             } catch (Exception e) {
56                 controllerIP = null;
57                 logger.warn("Invalid IP: {}, use wildcard *", addressString);
58             }
59         } else {
60             controllerIP = null;
61         }
62     }
63
64     public void start() throws IOException {
65         this.running = true;
66         this.netInt = null;
67         controllerIOThread = new Thread(new Runnable() {
68             @Override
69             public void run() {
70                 waitUntilInterfaceUp();
71                 if (!startAcceptConnections()) {
72                     return;
73                 }
74                 logger.info("Controller is now listening on {}:{}",
75                         (controllerIP == null) ? "any" : controllerIP.getHostAddress(),
76                         openFlowPort);
77                 boolean netInterfaceUp = true;
78                 while (running) {
79                     try {
80                         // wait for an incoming connection
81                         // check interface state every 5sec
82                         selector.select(5000);
83                         Iterator<SelectionKey> selectedKeys = selector
84                                 .selectedKeys().iterator();
85                         netInterfaceUp = isNetInterfaceUp(netInterfaceUp);
86                         while (selectedKeys.hasNext()) {
87                             SelectionKey skey = selectedKeys.next();
88                             selectedKeys.remove();
89                             if (skey.isValid() && skey.isAcceptable()) {
90                                 ((Controller) listener).handleNewConnection(
91                                         selector, serverSelectionKey);
92                             }
93                         }
94                     } catch (Exception e) {
95                         continue;
96                     }
97                 }
98             }
99         }, "ControllerI/O Thread");
100         controllerIOThread.start();
101     }
102
103     private boolean startAcceptConnections() {
104         if (running) {
105             try {
106                 // obtain a selector
107                 selector = SelectorProvider.provider().openSelector();
108                 // create the listening socket
109                 serverSocket = ServerSocketChannel.open();
110                 serverSocket.configureBlocking(false);
111                 serverSocket.socket().bind(
112                         new java.net.InetSocketAddress(controllerIP,
113                                 openFlowPort));
114                 serverSocket.socket().setReuseAddress(true);
115                 // register this socket for accepting incoming
116                 // connections
117                 serverSelectionKey = serverSocket.register(selector,
118                         SelectionKey.OP_ACCEPT);
119             } catch (IOException e) {
120                 logger.error(
121                         "Failed to listen on {}:{}, exit",
122                         (controllerIP == null) ? "" : controllerIP
123                                 .getHostAddress(), openFlowPort);
124                 return false;
125             }
126             return true;
127         }
128         return false;
129     }
130
131     private boolean isNetInterfaceUp(boolean currentlyUp) {
132         if (controllerIP == null) {
133             // for wildcard address, return since there is always an "up"
134             // interface (such as loopback)
135             return true;
136         }
137         boolean up;
138         try {
139             if (netInt == null) {
140                 logger.warn("Can't find any operational interface for address {}",
141                         controllerIP.getHostAddress());
142                 return false;
143             }
144             up = netInt.isUp();
145             if (!up) {
146                 // always generate log if the interface is down
147                 logger.warn("Interface {} with address {} is DOWN!",
148                         netInt.getDisplayName(),
149                         controllerIP.getHostAddress());
150             } else {
151                 if (!currentlyUp) {
152                     // only generate log if the interface changes from down to up
153                     logger.trace("Interface {} with address {} is UP!",
154                             netInt.getDisplayName(),
155                             controllerIP.getHostAddress());
156                 }
157             }
158         } catch (SocketException e) {
159             logger.warn("Interface {} with address {} is DOWN!",
160                     netInt.getDisplayName(),
161                     controllerIP.getHostAddress());
162            up = false;
163         }
164         return up;
165     }
166
167     private void waitUntilInterfaceUp() {
168         if (controllerIP == null) {
169             // for wildcard address, return since there is always an "up"
170             // interface (such as loopback)
171             return;
172         }
173         boolean isUp = false;
174         do {
175             try {
176                 // get the network interface from the address
177                 netInt = NetworkInterface.getByInetAddress(controllerIP);
178                 isUp = isNetInterfaceUp(isUp);
179                 if (!isUp) {
180                     Thread.sleep(5000);
181                 }
182             } catch (Exception e) {
183             }
184         } while ((!isUp) && (running));
185     }
186     public void shutDown() throws IOException {
187         this.running = false;
188         this.selector.wakeup();
189         this.serverSocket.close();
190     }
191 }