From 2e1c698a2bdfcbc3582fc72bf75424e1dc11f263 Mon Sep 17 00:00:00 2001 From: Chi-Vien Ly Date: Tue, 3 Sep 2013 10:07:13 -0700 Subject: [PATCH] Controller network interface enhancements: - Provide a configuration parameter "of.address = " in config.ini which allows a specific IP address to be specified. If a valid IP address is specified, the controller will ONLY accept connections from switches with destination address matching the specified configured address. If an address it NOT specified (which is the default case) or is syntactically incorrect, the controller will use "any" (wildcard) address. The default case is what currently been implemented. - If the IP address is specified, the controller will determine the networking interface (eg, eth0) on which the IP address is configured. If the interface is NOT up and is changed status between up and down, a log will be generated to alert the network operation to take corrective actions. If the address is not specified (or is specified with an invalid address syntax), the controller will use any interfaces and will NOT monitor the status of these interfaces. Change-Id: Ie2a92ad99d35367a1d89dca390e7af54321bfe7c Signed-off-by: Chi-Vien Ly --- .../main/resources/configuration/config.ini | 2 + .../openflow/core/internal/ControllerIO.java | 124 ++++++++++++++++-- 2 files changed, 113 insertions(+), 13 deletions(-) diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini index f9899d7d8b..5501be46b2 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -46,6 +46,8 @@ org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml # Open Flow related system parameters # TCP port on which the controller is listening (default 6633) # of.listenPort=6633 +# IP address of the controller (default: wild card) +# of.address = 127.0.0.1 # The time (in milliseconds) the controller will wait for a response after sending a Barrier Request or a Statistic Request message (default 2000 msec) # of.messageResponseTimer=2000 # The switch liveness timeout value (default 60500 msec) diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java index 868e208651..70c5072076 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java @@ -9,6 +9,9 @@ package org.opendaylight.controller.protocol_plugin.openflow.core.internal; import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; @@ -24,6 +27,8 @@ public class ControllerIO { .getLogger(ControllerIO.class); private static Short defaultOpenFlowPort = 6633; private Short openFlowPort; + private InetAddress controllerIP; + private NetworkInterface netInt; private SelectionKey serverSelectionKey; private IController listener; private ServerSocketChannel serverSocket; @@ -43,30 +48,41 @@ public class ControllerIO { openFlowPort); } } + String addressString = System.getProperty("of.address"); + if (addressString != null) { + try { + controllerIP = InetAddress.getByName(addressString); + } catch (Exception e) { + controllerIP = null; + logger.warn("Invalid IP: {}, use wildcard *", addressString); + } + } else { + controllerIP = null; + } } public void start() throws IOException { this.running = true; - // obtain a selector - this.selector = SelectorProvider.provider().openSelector(); - // create the listening socket - this.serverSocket = ServerSocketChannel.open(); - this.serverSocket.configureBlocking(false); - this.serverSocket.socket().bind( - new java.net.InetSocketAddress(openFlowPort)); - this.serverSocket.socket().setReuseAddress(true); - // register this socket for accepting incoming connections - this.serverSelectionKey = this.serverSocket.register(selector, - SelectionKey.OP_ACCEPT); + this.netInt = null; controllerIOThread = new Thread(new Runnable() { @Override public void run() { + waitUntilInterfaceUp(); + if (!startAcceptConnections()) { + return; + } + logger.info("Controller is now listening on {}:{}", + (controllerIP == null) ? "any" : controllerIP.getHostAddress(), + openFlowPort); + boolean netInterfaceUp = true; while (running) { try { // wait for an incoming connection - selector.select(0); + // check interface state every 5sec + selector.select(5000); Iterator selectedKeys = selector .selectedKeys().iterator(); + netInterfaceUp = isNetInterfaceUp(netInterfaceUp); while (selectedKeys.hasNext()) { SelectionKey skey = selectedKeys.next(); selectedKeys.remove(); @@ -82,9 +98,91 @@ public class ControllerIO { } }, "ControllerI/O Thread"); controllerIOThread.start(); - logger.info("Controller is now listening on port {}", openFlowPort); } + private boolean startAcceptConnections() { + if (running) { + try { + // obtain a selector + selector = SelectorProvider.provider().openSelector(); + // create the listening socket + serverSocket = ServerSocketChannel.open(); + serverSocket.configureBlocking(false); + serverSocket.socket().bind( + new java.net.InetSocketAddress(controllerIP, + openFlowPort)); + serverSocket.socket().setReuseAddress(true); + // register this socket for accepting incoming + // connections + serverSelectionKey = serverSocket.register(selector, + SelectionKey.OP_ACCEPT); + } catch (IOException e) { + logger.error( + "Failed to listen on {}:{}, exit", + (controllerIP == null) ? "" : controllerIP + .getHostAddress(), openFlowPort); + return false; + } + return true; + } + return false; + } + + private boolean isNetInterfaceUp(boolean currentlyUp) { + if (controllerIP == null) { + // for wildcard address, return since there is always an "up" + // interface (such as loopback) + return true; + } + boolean up; + try { + if (netInt == null) { + logger.warn("Can't find any operational interface for address {}", + controllerIP.getHostAddress()); + return false; + } + up = netInt.isUp(); + if (!up) { + // always generate log if the interface is down + logger.warn("Interface {} with address {} is DOWN!", + netInt.getDisplayName(), + controllerIP.getHostAddress()); + } else { + if (!currentlyUp) { + // only generate log if the interface changes from down to up + logger.info("Interface {} with address {} is UP!", + netInt.getDisplayName(), + controllerIP.getHostAddress()); + } + } + } catch (SocketException e) { + logger.warn("Interface {} with address {} is DOWN!", + netInt.getDisplayName(), + controllerIP.getHostAddress()); + up = false; + } + return up; + } + + private void waitUntilInterfaceUp() { + if (controllerIP == null) { + // for wildcard address, return since there is always an "up" + // interface (such as loopback) + return; + } + boolean isUp = false; + do { + try { + // get the network interface from the address + netInt = NetworkInterface.getByInetAddress(controllerIP); + isUp = isNetInterfaceUp(isUp); + if (!isUp) { + Thread.sleep(5000); + } + } catch (Exception e) { + } + } while ((!isUp) && (running)); + } public void shutDown() throws IOException { this.running = false; this.selector.wakeup(); -- 2.36.6