From 0c09ae4a352cccbd7dbaa1058bfb5ac370b9310a Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Fri, 15 May 2015 20:35:50 +0200 Subject: [PATCH] BUG-3229: Add support for PacketIn filtering When we are facing an overload situation, we may need to suppress PacketIns while still processing other messages. This patch adds the interface for ConnectionAdapter users which they can use to enable filtering of such packets. The implementation ensures that we filter these packets as efficiently as possible. Change-Id: I431631922437af7a08eb8ece647904d487634bd9 Signed-off-by: Robert Varga (cherry picked from commit 1f1a00d6c132e58a4d8f549f836323ecfe003e77) --- .../api/connection/ConnectionAdapter.java | 7 +++++ .../protocol/impl/core/OFVersionDetector.java | 30 ++++++++++++------- .../connection/ConnectionAdapterImpl.java | 13 ++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionAdapter.java b/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionAdapter.java index 02679f05..443dea57 100644 --- a/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionAdapter.java +++ b/openflow-protocol-api/src/main/java/org/opendaylight/openflowjava/protocol/api/connection/ConnectionAdapter.java @@ -82,4 +82,11 @@ public interface ConnectionAdapter extends OpenflowProtocolService { @Beta OutboundQueueHandlerRegistration registerOutboundQueueHandler(T handler, int maxQueueDepth, long maxBarrierNanos); + + /** + * Set filtering of PacketIn messages. By default these messages are not filtered. + * @param enabled True if PacketIn messages should be filtered, false if they should be reported. + */ + @Beta + void setPacketInFiltering(boolean enabled); } diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFVersionDetector.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFVersionDetector.java index 85bb5d55..083cf0ec 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFVersionDetector.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFVersionDetector.java @@ -26,7 +26,9 @@ public class OFVersionDetector extends ByteToMessageDecoder { private static final byte OF10_VERSION_ID = EncodeConstants.OF10_VERSION_ID; /** Version number of OpenFlow 1.3 protocol */ private static final byte OF13_VERSION_ID = EncodeConstants.OF13_VERSION_ID; + private static final short OF_PACKETIN = 10; private static final Logger LOGGER = LoggerFactory.getLogger(OFVersionDetector.class); + private volatile boolean filterPacketIns; /** * Constructor of class. @@ -35,23 +37,31 @@ public class OFVersionDetector extends ByteToMessageDecoder { LOGGER.trace("Creating OFVersionDetector"); } + public void setFilterPacketIns(final boolean enabled) { + filterPacketIns = enabled; + } + @Override - protected void decode(final ChannelHandlerContext chc, final ByteBuf bb, final List list) throws Exception { - if (bb.readableBytes() == 0) { + protected void decode(final ChannelHandlerContext ctx, final ByteBuf in, final List out) { + if (!in.isReadable()) { LOGGER.debug("not enough data"); - bb.release(); + in.release(); return; } - byte version = bb.readByte(); - if ((version == OF13_VERSION_ID) || (version == OF10_VERSION_ID)) { + + final byte version = in.readByte(); + if (version == OF13_VERSION_ID || version == OF10_VERSION_ID) { LOGGER.debug("detected version: {}", version); - ByteBuf messageBuffer = bb.slice(); - list.add(new VersionMessageWrapper(version, messageBuffer)); - messageBuffer.retain(); + if (!filterPacketIns || OF_PACKETIN != in.getUnsignedByte(in.readerIndex())) { + ByteBuf messageBuffer = in.slice(); + out.add(new VersionMessageWrapper(version, messageBuffer)); + messageBuffer.retain(); + } else { + LOGGER.debug("dropped packetin"); + } } else { LOGGER.warn("detected version: {} - currently not supported", version); } - bb.skipBytes(bb.readableBytes()); + in.skipBytes(in.readableBytes()); } - } diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/connection/ConnectionAdapterImpl.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/connection/ConnectionAdapterImpl.java index 91f4ceb1..464527c7 100644 --- a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/connection/ConnectionAdapterImpl.java +++ b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/connection/ConnectionAdapterImpl.java @@ -27,6 +27,8 @@ import java.util.concurrent.TimeUnit; import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener; import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandler; import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration; +import org.opendaylight.openflowjava.protocol.impl.core.OFVersionDetector; +import org.opendaylight.openflowjava.protocol.impl.core.PipelineHandlers; import org.opendaylight.openflowjava.statistics.CounterEventTypes; import org.opendaylight.openflowjava.statistics.StatisticsCounters; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput; @@ -117,6 +119,7 @@ public class ConnectionAdapterImpl implements ConnectionFacade { private OutboundQueueManager outputManager; private boolean disconnectOccured = false; private final StatisticsCounters statisticsCounters; + private OFVersionDetector versionDetector; private final InetSocketAddress address; /** @@ -135,6 +138,7 @@ public class ConnectionAdapterImpl implements ConnectionFacade { this.address = address; channel.pipeline().addLast(output); statisticsCounters = StatisticsCounters.getInstance(); + LOG.debug("ConnectionAdapter created"); } @@ -455,6 +459,9 @@ public class ConnectionAdapterImpl implements ConnectionFacade { @Override public void fireConnectionReadyNotification() { + versionDetector = (OFVersionDetector) channel.pipeline().get(PipelineHandlers.OF_VERSION_DETECTOR.name()); + Preconditions.checkState(versionDetector != null); + new Thread(new Runnable() { @Override public void run() { @@ -514,4 +521,10 @@ public class ConnectionAdapterImpl implements ConnectionFacade { Channel getChannel() { return channel; } + + @Override + public void setPacketInFiltering(final boolean enabled) { + versionDetector.setFilterPacketIns(enabled); + LOG.debug("PacketIn filtering {}abled", enabled ? "en" : "dis"); + } } -- 2.36.6