import java.net.InetAddress;
+import javax.net.ssl.SSLEngine;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
+
/**
* @author mirehak
*
* @return encryption feature support
*/
public FEATURE_SUPPORT getTlsSupport();
+
+ /**
+ * @return silence time (in milliseconds) - after this time {@link SwitchIdleEvent} message is sent upstream
+ */
+ public long getSwitchIdleTimeout();
+
+ /**
+ * @return seed for {@link SSLEngine}
+ */
+ public Object getSslContext();
}
module openflow-augments {\r
namespace "urn:opendaylight:openflow:augments";\r
prefix "aug";\r
- \r
+\r
import openflow-protocol {prefix ofproto;}\r
+ import openflow-extensible-match {prefix oxm;}\r
\r
\r
revision "2013-10-02" {\r
description "Initial model";\r
}\r
\r
- augment "/ofproto:hello-message/ofproto:elements" {\r
- leaf uid {\r
- type uint16;\r
- }\r
+ augment "/oxm:oxm-container/oxm:match-entries" {\r
+ uses oxm:in-port;\r
+ /* common augment for fields:\r
+ OXM_OF_IN_PORT\r
+ OXM_OF_IN_PHY_PORT\r
+ */\r
+ }\r
+\r
+ augment "/oxm:oxm-container/oxm:match-entries" {\r
+ uses oxm:metadata;\r
+ /* common augment for fields:\r
+ OXM_OF_METADATA\r
+ OXM_OF_TUNNEL_ID\r
+ */\r
}\r
+\r
}
\ No newline at end of file
}
// oxm classes
- identity class {
+ identity clazz {
description "Base identity for OXM classes";
}
identity nxm-0-class {
description "Backward compatibility with NXM";
- base class;
+ base clazz;
}
identity nxm-1-class {
description "Backward compatibility with NXM";
- base class;
+ base clazz;
}
identity openflow-basic-class {
description "Basic class for OpenFlow";
- base class;
+ base clazz;
}
identity experimenter-class {
description
"Marks Experimenter match type class.
All experimenter match classes MUST use this class as a base.";
- base class;
+ base clazz;
}
leaf address {
type yang:mac-address;
}
+ leaf mask {
+ type binary;
+ }
}
grouping eth-src {
description "Ethernet source address.";
leaf type {
type oft:ether-type; // Needs to define that as general model
}
- leaf mask {
- type binary;
- }
}
grouping vlan-vid {
description "VLAN id.";
}
}
+ container oxm-container {
+ uses oxm-fields;
+ }
+
grouping oxm-fields {
list match-entries {
leaf oxm-class {
type identityref {
- base class;
+ base clazz;
}
}
leaf oxm-match-field {
base match-field;
}
}
- leaf has-mask {
- type boolean;
- }
}
}
revision "2013-09-27" {
//description "Initial model";
}
-
+
notification disconnect-event {
leaf info {
type string;
- }
+ }
+ }
+
+ notification switch-idle-event {
+ leaf info {
+ type string;
+ }
}
-
+
}
\ No newline at end of file
</instructions>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetConfigInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Notification;
responseCache = CacheBuilder.newBuilder()
.concurrencyLevel(1)
.expireAfterWrite(RPC_RESPONSE_EXPIRATION, TimeUnit.MINUTES)
- .removalListener(new RemovalListener<RpcResponseKey, SettableFuture<?>>() {
-
- @Override
- public void onRemoval(
- RemovalNotification<RpcResponseKey, SettableFuture<?>> notification) {
- SettableFuture<?> future = notification.getValue();
- if (!future.isDone()) {
- LOG.warn("rpc response discarded: " + notification.getKey());
- future.cancel(true);
- }
- }
- }).build();
+ .removalListener(new ResponseRemovalListener()).build();
LOG.info("ConnectionAdapter created");
+
+
}
/**
systemListener.onDisconnectEvent((DisconnectEvent) message);
responseCache.invalidateAll();
disconnectOccured = true;
- }
+ } else if (message instanceof SwitchIdleEvent) {
+ systemListener.onSwitchIdleEvent((SwitchIdleEvent) message);
+ }
// OpenFlow messages
else if (message instanceof EchoRequestMessage) {
messageListener.onEchoRequestMessage((EchoRequestMessage) message);
throw new IllegalStateException("Missing listeners: " + buffer.toString());
}
}
+
+ static class ResponseRemovalListener implements RemovalListener<RpcResponseKey, SettableFuture<?>> {
+
+ @Override
+ public void onRemoval(
+ RemovalNotification<RpcResponseKey, SettableFuture<?>> notification) {
+ SettableFuture<?> future = notification.getValue();
+ if (!future.isDone()) {
+ LOG.warn("rpc response discarded: " + notification.getKey());
+ future.cancel(true);
+ }
+ }
+ }
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;
*/
public class SwitchConnectionProviderImpl implements SwitchConnectionProvider {
- private static final Logger LOG = LoggerFactory
+ private static final Logger LOGGER = LoggerFactory
.getLogger(SwitchConnectionProviderImpl.class);
private SwitchConnectionHandler switchConnectionHandler;
private Set<ServerFacade> serverLot;
@Override
public void configure(Collection<ConnectionConfiguration> connConfigs) {
- LOG.debug("Configurating ..");
+ LOGGER.debug("Configuring ..");
//TODO - configure servers according to configuration
serverLot = new HashSet<>();
- for (Iterator<ConnectionConfiguration> iterator = connConfigs.iterator(); iterator.hasNext();) {
- ConnectionConfiguration connConfig = iterator.next();
+ for (ConnectionConfiguration connConfig : connConfigs) {
TcpHandler server = new TcpHandler(connConfig.getAddress(), connConfig.getPort());
server.setSwitchConnectionHandler(switchConnectionHandler);
+ server.setSwitchIdleTimeout(connConfig.getSwitchIdleTimeout());
serverLot.add(server);
}
}
@Override
public void setSwitchConnectionHandler(SwitchConnectionHandler switchConnectionHandler) {
- LOG.debug("setSwitchConnectionHanler");
+ LOGGER.debug("setSwitchConnectionHandler");
this.switchConnectionHandler = switchConnectionHandler;
}
@Override
public Future<List<Boolean>> shutdown() {
- LOG.debug("Shutdown summoned");
+ LOGGER.debug("Shutdown summoned");
ListenableFuture<List<Boolean>> result = SettableFuture.create();
try {
List<ListenableFuture<Boolean>> shutdownChain = new ArrayList<>();
@Override
public Future<List<Boolean>> startup() {
- LOG.debug("startup summoned");
+ LOGGER.debug("startup summoned");
ListenableFuture<List<Boolean>> result = SettableFuture.create();
try {
if (serverLot.isEmpty()) {
--- /dev/null
+package org.opendaylight.openflowjava.protocol.impl.core;\r
+\r
+import java.util.concurrent.TimeUnit;\r
+\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.timeout.IdleState;\r
+import io.netty.handler.timeout.IdleStateEvent;\r
+import io.netty.handler.timeout.IdleStateHandler;\r
+\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEventBuilder;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class IdleHandler extends IdleStateHandler{\r
+ \r
+ public IdleHandler(long readerIdleTime, long writerIdleTime,\r
+ long allIdleTime, TimeUnit unit) {\r
+ super(readerIdleTime, writerIdleTime, allIdleTime, unit);\r
+ }\r
+\r
+\r
+ private static final Logger LOGGER = LoggerFactory.getLogger(IdleHandler.class);\r
+\r
+ \r
+ @Override\r
+ protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt)\r
+ throws Exception {\r
+ if ((evt.state() == IdleState.READER_IDLE) && (evt.isFirst())) {\r
+ LOGGER.info("Switch idle");\r
+ SwitchIdleEventBuilder builder = new SwitchIdleEventBuilder();\r
+ builder.setInfo("Switch idle");\r
+ ctx.fireChannelRead(builder.build());\r
+ }\r
+ }\r
+\r
+}\r
\r
import java.net.InetAddress;\r
import java.util.Iterator;\r
+import java.util.concurrent.TimeUnit;\r
\r
import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;\r
import org.opendaylight.openflowjava.protocol.impl.connection.ConnectionAdapterFactory;\r
.getLogger(PublishingChannelInitializer.class);\r
private DefaultChannelGroup allChannels;\r
private SwitchConnectionHandler switchConnectionHandler;\r
+ private long switchIdleTimeout;\r
\r
/**\r
* default ctor\r
LOGGER.debug("calling plugin: "+switchConnectionHandler);\r
switchConnectionHandler.onSwitchConnected(connectionAdapter);\r
connectionAdapter.checkListeners();\r
+ ch.pipeline().addLast(COMPONENT_NAMES.IDLE_HANDLER.name(), new IdleHandler(switchIdleTimeout, 0, 0, TimeUnit.MILLISECONDS));\r
ch.pipeline().addLast(COMPONENT_NAMES.TLS_DETECTOR.name(), new TlsDetector());\r
ch.pipeline().addLast(COMPONENT_NAMES.DELEGATING_INBOUND_HANDLER.name(), new DelegatingInboundHandler(connectionAdapter));\r
} catch (Exception e) {\r
public void setSwitchConnectionHandler(SwitchConnectionHandler switchConnectionHandler) {\r
this.switchConnectionHandler = switchConnectionHandler;\r
}\r
+\r
+ /**\r
+ * @param switchIdleTimeout the switchIdleTimeout to set\r
+ */\r
+ public void setSwitchIdleTimeout(long switchIdleTimeout) {\r
+ this.switchIdleTimeout = switchIdleTimeout;\r
+ }\r
+ \r
}\r
serverContext = SSLContext.getInstance(PROTOCOL);
serverContext.init(kmf.getKeyManagers(), null, null);
+ } catch (RuntimeException e) {
+ throw new Error(
+ "Failed to initialize the server-side SSLContext", e);
} catch (Exception e) {
throw new Error(
"Failed to initialize the server-side SSLContext", e);
public static enum COMPONENT_NAMES {
/**
- * First component in pipeline - detecting TLS connections
+ * Detects switch idle state
+ */
+ IDLE_HANDLER,
+ /**
+ * Detects TLS connections
*/
TLS_DETECTOR,
/**
channelInitializer.setSwitchConnectionHandler(switchConnectionHandler);
}
+ public void setSwitchIdleTimeout(long switchIdleTimeout) {
+ channelInitializer.setSwitchIdleTimeout(switchIdleTimeout);
+ }
+
}
package org.opendaylight.openflowjava.protocol.impl.integration;\r
\r
import java.net.InetAddress;\r
-import java.net.UnknownHostException;\r
import java.util.ArrayList;\r
import java.util.List;\r
import java.util.concurrent.ExecutionException;\r
public static final String OF_BINARY_MESSAGE_INPUT_TXT = "OFBinaryMessageInput.txt";\r
private static final int DEFAULT_PORT = 6633;\r
private static final FEATURE_SUPPORT DEFAULT_TLS_SUPPORT = FEATURE_SUPPORT.NOT_SUPPORTED;\r
+ private static final int SWITCH_IDLE_TIMEOUT = 2000;\r
\r
protected static final Logger LOGGER = LoggerFactory\r
.getLogger(IntegrationTest.class);\r
private MockPlugin mockPlugin;\r
\r
/**\r
- * @throws UnknownHostException\r
+ * @throws Exception\r
*/\r
@Before\r
- public void setUp() throws UnknownHostException {\r
+ public void setUp() throws Exception {\r
startupAddress = InetAddress.getLocalHost();\r
+ mockPlugin = new MockPlugin();\r
+ SwitchConnectionProviderImpl scpimpl = new SwitchConnectionProviderImpl();\r
+ scpimpl.setSwitchConnectionHandler(mockPlugin);\r
+ List<ConnectionConfiguration> configs = new ArrayList<>();\r
+ configs.add(new TestingConnConfigImpl(startupAddress, DEFAULT_PORT, DEFAULT_TLS_SUPPORT, SWITCH_IDLE_TIMEOUT));\r
+ scpimpl.configure(configs);\r
+ scpimpl.startup().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);\r
}\r
\r
/**\r
*/\r
@Test\r
public void testCommunication() throws Exception {\r
- mockPlugin = new MockPlugin();\r
- SwitchConnectionProviderImpl scpimpl = new SwitchConnectionProviderImpl();\r
- scpimpl.setSwitchConnectionHandler(mockPlugin);\r
- List<ConnectionConfiguration> configs = new ArrayList<>();\r
- configs.add(new TestingConnConfigImpl(startupAddress, DEFAULT_PORT, DEFAULT_TLS_SUPPORT));\r
- scpimpl.configure(configs);\r
- scpimpl.startup().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);\r
-\r
int amountOfCLients = 1;\r
List<SimpleClient> clients = createAndStartClient(amountOfCLients);\r
SimpleClient firstClient = clients.get(0);\r
*/\r
//@Test\r
public void testCommunicationWithVM() throws Exception {\r
- mockPlugin = new MockPlugin();\r
- SwitchConnectionProviderImpl scpimpl = new SwitchConnectionProviderImpl();\r
- scpimpl.setSwitchConnectionHandler(mockPlugin);\r
- List<ConnectionConfiguration> configs = new ArrayList<>();\r
- configs.add(new TestingConnConfigImpl(startupAddress, DEFAULT_PORT, DEFAULT_TLS_SUPPORT));\r
- scpimpl.configure(configs);\r
- scpimpl.startup().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);\r
mockPlugin.getFinishedFuture().get();\r
}\r
\r
/**\r
* @param amountOfCLients \r
- * @param dataLimit TODO\r
* @return new clients up and running\r
* @throws InterruptedException\r
* @throws ExecutionException\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;\r
import org.opendaylight.yangtools.yang.common.RpcError;\r
import org.opendaylight.yangtools.yang.common.RpcResult;\r
private static final Logger LOGGER = LoggerFactory.getLogger(MockPlugin.class);\r
private ConnectionAdapter adapter;\r
private SettableFuture<Void> finishedFuture;\r
+ private int idleCounter = 0;\r
\r
public MockPlugin() {\r
finishedFuture = SettableFuture.create();\r
return finishedFuture;\r
}\r
\r
+ @Override\r
+ public void onSwitchIdleEvent(SwitchIdleEvent notification) {\r
+ LOGGER.debug("switch status: "+notification.getInfo());\r
+ idleCounter ++;\r
+ }\r
+ \r
+ public int getIdleCounter() {\r
+ return idleCounter;\r
+ }\r
+\r
\r
}\r
private int port;\r
private Object transferProtocol;\r
private FEATURE_SUPPORT tlsSupport;\r
+ private long switchIdleTimeout;\r
\r
// TODO - implement transferProtocol\r
- public TestingConnConfigImpl(InetAddress address, int port, FEATURE_SUPPORT tlsSupport) {\r
+ public TestingConnConfigImpl(InetAddress address, int port, FEATURE_SUPPORT tlsSupport, long switchIdleTimeout) {\r
this.address = address;\r
this.port = port;\r
this.tlsSupport = tlsSupport;\r
+ this.switchIdleTimeout = switchIdleTimeout;\r
}\r
\r
@Override\r
return tlsSupport;\r
}\r
\r
+ @Override\r
+ public long getSwitchIdleTimeout() {\r
+ return switchIdleTimeout;\r
+ }\r
+\r
+ @Override\r
+ public Object getSslContext() {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
}\r
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
</plugins>
</pluginManagement>
</build>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
- <version>2.4.0</version>
+ <version>2.5.2</version>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<goal>site</goal>
</configuration>
</plugin>
+ <plugin>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.3</version>
+ <configuration>
+ <aggregate>true</aggregate>
+ <linkJavadoc>true</linkJavadoc>
+ </configuration>
+ </plugin>
+
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jdepend-maven-plugin</artifactId>