From 0d8525a6df847f3cdac88f8c78b7cb914c51e1c8 Mon Sep 17 00:00:00 2001 From: Michal Polkorab Date: Mon, 14 Oct 2013 14:27:25 +0200 Subject: [PATCH] Added support for switch idle state Added jar packaging for test classes Signed-off-by: Michal Polkorab Change-Id: Iaa5cec646cbe2de7cb1f97b16be4f481c7c31673 --- .../connection/ConnectionConfiguration.java | 14 ++++++++ .../src/main/yang/openflow-augments.yang | 22 +++++++++--- .../main/yang/openflow-extensible-match.yang | 25 ++++++------- .../src/main/yang/system-notifications.yang | 12 +++++-- openflow-protocol-impl/pom.xml | 11 ++++++ .../connection/ConnectionAdapterImpl.java | 33 ++++++++++------- .../SwitchConnectionProviderImpl.java | 15 ++++---- .../protocol/impl/core/IdleHandler.java | 36 +++++++++++++++++++ .../core/PublishingChannelInitializer.java | 11 ++++++ .../protocol/impl/core/SslContextFactory.java | 3 ++ .../protocol/impl/core/TcpHandler.java | 10 +++++- .../impl/integration/IntegrationTest.java | 29 ++++++--------- .../protocol/impl/integration/MockPlugin.java | 12 +++++++ .../integration/TestingConnConfigImpl.java | 15 +++++++- pom.xml | 16 ++++++++- 15 files changed, 201 insertions(+), 63 deletions(-) create mode 100644 openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/IdleHandler.java diff --git a/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionConfiguration.java b/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionConfiguration.java index 139d84ec..a42b000c 100644 --- a/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionConfiguration.java +++ b/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionConfiguration.java @@ -4,6 +4,10 @@ package org.opendaylight.openflowjava.protocol.api.connection; import java.net.InetAddress; +import javax.net.ssl.SSLEngine; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent; + /** * @author mirehak * @@ -41,5 +45,15 @@ public interface ConnectionConfiguration { * @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(); } diff --git a/openflow-protocol-api/src/main/yang/openflow-augments.yang b/openflow-protocol-api/src/main/yang/openflow-augments.yang index 13f8b00a..badda304 100644 --- a/openflow-protocol-api/src/main/yang/openflow-augments.yang +++ b/openflow-protocol-api/src/main/yang/openflow-augments.yang @@ -1,17 +1,29 @@ module openflow-augments { namespace "urn:opendaylight:openflow:augments"; prefix "aug"; - + import openflow-protocol {prefix ofproto;} + import openflow-extensible-match {prefix oxm;} revision "2013-10-02" { description "Initial model"; } - augment "/ofproto:hello-message/ofproto:elements" { - leaf uid { - type uint16; - } + augment "/oxm:oxm-container/oxm:match-entries" { + uses oxm:in-port; + /* common augment for fields: + OXM_OF_IN_PORT + OXM_OF_IN_PHY_PORT + */ + } + + augment "/oxm:oxm-container/oxm:match-entries" { + uses oxm:metadata; + /* common augment for fields: + OXM_OF_METADATA + OXM_OF_TUNNEL_ID + */ } + } \ No newline at end of file diff --git a/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang b/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang index 3845f1ab..54decb1a 100644 --- a/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang +++ b/openflow-protocol-api/src/main/yang/openflow-extensible-match.yang @@ -21,28 +21,28 @@ module openflow-extensible-match { } // 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; } @@ -243,6 +243,9 @@ module openflow-extensible-match { leaf address { type yang:mac-address; } + leaf mask { + type binary; + } } grouping eth-src { description "Ethernet source address."; @@ -258,9 +261,6 @@ module openflow-extensible-match { leaf type { type oft:ether-type; // Needs to define that as general model } - leaf mask { - type binary; - } } grouping vlan-vid { description "VLAN id."; @@ -739,11 +739,15 @@ module openflow-extensible-match { } } + 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 { @@ -751,9 +755,6 @@ module openflow-extensible-match { base match-field; } } - leaf has-mask { - type boolean; - } } } diff --git a/openflow-protocol-api/src/main/yang/system-notifications.yang b/openflow-protocol-api/src/main/yang/system-notifications.yang index b4d1e02b..a74f2744 100644 --- a/openflow-protocol-api/src/main/yang/system-notifications.yang +++ b/openflow-protocol-api/src/main/yang/system-notifications.yang @@ -5,11 +5,17 @@ module system-notifications { 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 diff --git a/openflow-protocol-impl/pom.xml b/openflow-protocol-impl/pom.xml index dd363201..0179a7d3 100644 --- a/openflow-protocol-impl/pom.xml +++ b/openflow-protocol-impl/pom.xml @@ -23,6 +23,17 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/ConnectionAdapterImpl.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/ConnectionAdapterImpl.java index f2e5fdca..0658b714 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/ConnectionAdapterImpl.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/ConnectionAdapterImpl.java @@ -51,6 +51,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 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; @@ -96,19 +97,10 @@ public class ConnectionAdapterImpl implements ConnectionFacade { responseCache = CacheBuilder.newBuilder() .concurrencyLevel(1) .expireAfterWrite(RPC_RESPONSE_EXPIRATION, TimeUnit.MINUTES) - .removalListener(new RemovalListener>() { - - @Override - public void onRemoval( - RemovalNotification> 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"); + + } /** @@ -252,7 +244,9 @@ public class ConnectionAdapterImpl implements ConnectionFacade { 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); @@ -515,5 +509,18 @@ public class ConnectionAdapterImpl implements ConnectionFacade { throw new IllegalStateException("Missing listeners: " + buffer.toString()); } } + + static class ResponseRemovalListener implements RemovalListener> { + + @Override + public void onRemoval( + RemovalNotification> notification) { + SettableFuture future = notification.getValue(); + if (!future.isDone()) { + LOG.warn("rpc response discarded: " + notification.getKey()); + future.cancel(true); + } + } + } } diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/SwitchConnectionProviderImpl.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/SwitchConnectionProviderImpl.java index 8d21a2fd..0cd2bef5 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/SwitchConnectionProviderImpl.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/SwitchConnectionProviderImpl.java @@ -5,7 +5,6 @@ package org.opendaylight.openflowjava.protocol.impl.connection; 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; @@ -27,34 +26,34 @@ import com.google.common.util.concurrent.SettableFuture; */ 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 serverLot; @Override public void configure(Collection connConfigs) { - LOG.debug("Configurating .."); + LOGGER.debug("Configuring .."); //TODO - configure servers according to configuration serverLot = new HashSet<>(); - for (Iterator 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> shutdown() { - LOG.debug("Shutdown summoned"); + LOGGER.debug("Shutdown summoned"); ListenableFuture> result = SettableFuture.create(); try { List> shutdownChain = new ArrayList<>(); @@ -77,7 +76,7 @@ public class SwitchConnectionProviderImpl implements SwitchConnectionProvider { @Override public Future> startup() { - LOG.debug("startup summoned"); + LOGGER.debug("startup summoned"); ListenableFuture> result = SettableFuture.create(); try { if (serverLot.isEmpty()) { diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/IdleHandler.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/IdleHandler.java new file mode 100644 index 00000000..c3bd7ab7 --- /dev/null +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/IdleHandler.java @@ -0,0 +1,36 @@ +package org.opendaylight.openflowjava.protocol.impl.core; + +import java.util.concurrent.TimeUnit; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import io.netty.handler.timeout.IdleStateHandler; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEventBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IdleHandler extends IdleStateHandler{ + + public IdleHandler(long readerIdleTime, long writerIdleTime, + long allIdleTime, TimeUnit unit) { + super(readerIdleTime, writerIdleTime, allIdleTime, unit); + } + + + private static final Logger LOGGER = LoggerFactory.getLogger(IdleHandler.class); + + + @Override + protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) + throws Exception { + if ((evt.state() == IdleState.READER_IDLE) && (evt.isFirst())) { + LOGGER.info("Switch idle"); + SwitchIdleEventBuilder builder = new SwitchIdleEventBuilder(); + builder.setInfo("Switch idle"); + ctx.fireChannelRead(builder.build()); + } + } + +} diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/PublishingChannelInitializer.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/PublishingChannelInitializer.java index 5866ebf2..0fab3e4a 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/PublishingChannelInitializer.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/PublishingChannelInitializer.java @@ -7,6 +7,7 @@ import io.netty.channel.socket.SocketChannel; import java.net.InetAddress; import java.util.Iterator; +import java.util.concurrent.TimeUnit; import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler; import org.opendaylight.openflowjava.protocol.impl.connection.ConnectionAdapterFactory; @@ -25,6 +26,7 @@ public class PublishingChannelInitializer extends ChannelInitializer configs = new ArrayList<>(); + configs.add(new TestingConnConfigImpl(startupAddress, DEFAULT_PORT, DEFAULT_TLS_SUPPORT, SWITCH_IDLE_TIMEOUT)); + scpimpl.configure(configs); + scpimpl.startup().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); } /** @@ -50,14 +57,6 @@ public class IntegrationTest { */ @Test public void testCommunication() throws Exception { - mockPlugin = new MockPlugin(); - SwitchConnectionProviderImpl scpimpl = new SwitchConnectionProviderImpl(); - scpimpl.setSwitchConnectionHandler(mockPlugin); - List configs = new ArrayList<>(); - configs.add(new TestingConnConfigImpl(startupAddress, DEFAULT_PORT, DEFAULT_TLS_SUPPORT)); - scpimpl.configure(configs); - scpimpl.startup().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - int amountOfCLients = 1; List clients = createAndStartClient(amountOfCLients); SimpleClient firstClient = clients.get(0); @@ -71,19 +70,11 @@ public class IntegrationTest { */ //@Test public void testCommunicationWithVM() throws Exception { - mockPlugin = new MockPlugin(); - SwitchConnectionProviderImpl scpimpl = new SwitchConnectionProviderImpl(); - scpimpl.setSwitchConnectionHandler(mockPlugin); - List configs = new ArrayList<>(); - configs.add(new TestingConnConfigImpl(startupAddress, DEFAULT_PORT, DEFAULT_TLS_SUPPORT)); - scpimpl.configure(configs); - scpimpl.startup().get(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); mockPlugin.getFinishedFuture().get(); } /** * @param amountOfCLients - * @param dataLimit TODO * @return new clients up and running * @throws InterruptedException * @throws ExecutionException diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/MockPlugin.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/MockPlugin.java index 5603a473..3ae7a9d8 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/MockPlugin.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/MockPlugin.java @@ -29,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage; 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.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -46,6 +47,7 @@ public class MockPlugin implements OpenflowProtocolListener, SwitchConnectionHan private static final Logger LOGGER = LoggerFactory.getLogger(MockPlugin.class); private ConnectionAdapter adapter; private SettableFuture finishedFuture; + private int idleCounter = 0; public MockPlugin() { finishedFuture = SettableFuture.create(); @@ -172,5 +174,15 @@ public class MockPlugin implements OpenflowProtocolListener, SwitchConnectionHan return finishedFuture; } + @Override + public void onSwitchIdleEvent(SwitchIdleEvent notification) { + LOGGER.debug("switch status: "+notification.getInfo()); + idleCounter ++; + } + + public int getIdleCounter() { + return idleCounter; + } + } diff --git a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/TestingConnConfigImpl.java b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/TestingConnConfigImpl.java index 2db3b5b2..a7e9ef0e 100644 --- a/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/TestingConnConfigImpl.java +++ b/openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/integration/TestingConnConfigImpl.java @@ -15,12 +15,14 @@ public class TestingConnConfigImpl implements ConnectionConfiguration { private int port; private Object transferProtocol; private FEATURE_SUPPORT tlsSupport; + private long switchIdleTimeout; // TODO - implement transferProtocol - public TestingConnConfigImpl(InetAddress address, int port, FEATURE_SUPPORT tlsSupport) { + public TestingConnConfigImpl(InetAddress address, int port, FEATURE_SUPPORT tlsSupport, long switchIdleTimeout) { this.address = address; this.port = port; this.tlsSupport = tlsSupport; + this.switchIdleTimeout = switchIdleTimeout; } @Override @@ -43,4 +45,15 @@ public class TestingConnConfigImpl implements ConnectionConfiguration { return tlsSupport; } + @Override + public long getSwitchIdleTimeout() { + return switchIdleTimeout; + } + + @Override + public Object getSslContext() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/pom.xml b/pom.xml index eb5c77f5..ad45ee88 100644 --- a/pom.xml +++ b/pom.xml @@ -234,6 +234,11 @@ maven-deploy-plugin 2.7 + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + @@ -242,13 +247,22 @@ org.codehaus.mojo findbugs-maven-plugin - 2.4.0 + 2.5.2 Max Low site + + maven-jxr-plugin + 2.3 + + true + true + + + org.codehaus.mojo jdepend-maven-plugin -- 2.36.6