Bug-2250: pcc-mock support TCP MD5 11/15111/5
authorMilos Fabian <milfabia@cisco.com>
Tue, 10 Feb 2015 08:37:05 +0000 (09:37 +0100)
committerRobert Varga <nite@hq.sk>
Sun, 15 Feb 2015 16:07:13 +0000 (16:07 +0000)
-new input argument "--password <string>"
-when password is omitted, plain tcp is used

Change-Id: I973ac455be1fe093a129dc065bd1d6a28bc3dfe4
Signed-off-by: Milos Fabian <milfabia@cisco.com>
pcep/pcc-mock/pom.xml
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/Main.java
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCDispatcher.java

index 5c49339b72dc3b0826f458a85f0f07ce8a448bfe..2449bcaad9aa81a1b3a2739e9f16c8888ac51083 100644 (file)
       <groupId>io.netty</groupId>
       <artifactId>netty-common</artifactId>
     </dependency>
-    <dependency>
-      <groupId>io.netty</groupId>
-      <artifactId>netty-buffer</artifactId>
-    </dependency>
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-transport</artifactId>
        <groupId>org.opendaylight.yangtools.model</groupId>
        <artifactId>ietf-inet-types</artifactId>
     </dependency>
+    <dependency>
+        <groupId>org.opendaylight.tcpmd5</groupId>
+        <artifactId>tcpmd5-jni</artifactId>
+    </dependency>
+    <dependency>
+        <groupId>org.opendaylight.tcpmd5</groupId>
+        <artifactId>tcpmd5-netty</artifactId>
+    </dependency>
+    <dependency>
+        <groupId>org.opendaylight.tcpmd5</groupId>
+        <artifactId>tcpmd5-api</artifactId>
+    </dependency>
 
     <!-- Testing dependencies -->
     <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
     </dependency>
-    <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>pcep-testtool</artifactId>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <build>
index cf641b227c858088b1554458d24189cd19abf45a..fec2ac8724d006e932ebd847b493e12ea8284011 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.protocol.pcep.pcc.mock;
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.LoggerContext;
+import com.google.common.base.Charsets;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
@@ -30,6 +31,7 @@ import org.opendaylight.protocol.pcep.ietf.stateful07.StatefulActivator;
 import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiatorFactory;
 import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
 import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
+import org.opendaylight.tcpmd5.api.KeyMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
 import org.slf4j.Logger;
@@ -55,6 +57,7 @@ public final class Main {
         final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
         short ka = DEFAULT_KEEP_ALIVE;
         short dt = DEFAULT_DEAD_TIMER;
+        String password = null;
 
         getRootLogger(lc).setLevel(ch.qos.logback.classic.Level.INFO);
         int argIdx = 0;
@@ -75,29 +78,33 @@ public final class Main {
                 ka = Short.valueOf(args[++argIdx]);
             } else if (args[argIdx].equals("--deadtimer") || args[argIdx].equals("-d")) {
                 dt = Short.valueOf(args[++argIdx]);
+            } else if (args[argIdx].equals("--password")) {
+                password = args[++argIdx];
             } else {
                 LOG.warn("WARNING: Unrecognized argument: {}", args[argIdx]);
             }
             argIdx++;
         }
-        createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt);
+        createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt, password);
     }
 
     public static void createPCCs(final int lspsPerPcc, final boolean pcerr, final int pccCount,
-            final InetAddress localAddress, final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer) throws InterruptedException, ExecutionException {
+            final InetAddress localAddress, final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer,
+            final String password) throws InterruptedException, ExecutionException {
         final StatefulActivator activator07 = new StatefulActivator();
         activator07.start(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance());
         InetAddress currentAddress = localAddress;
         final PCCDispatcher pccDispatcher = new PCCDispatcher(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance().getMessageHandlerRegistry(),
                 getSessionNegotiatorFactory(keepalive, deadtimer));
         for (int i = 0; i < pccCount; i++) {
-            createPCC(lspsPerPcc, pcerr, currentAddress, remoteAddress, keepalive, deadtimer, pccDispatcher);
+            createPCC(lspsPerPcc, pcerr, currentAddress, remoteAddress, keepalive, deadtimer, pccDispatcher, password);
             currentAddress = InetAddresses.increment(currentAddress);
         }
     }
 
     private static void createPCC(final int lspsPerPcc, final boolean pcerr, final InetAddress localAddress,
-            final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer, final PCCDispatcher pccDispatcher) throws InterruptedException, ExecutionException {
+            final List<InetAddress> remoteAddress, final short keepalive, final short deadtimer, final PCCDispatcher pccDispatcher,
+            final String password) throws InterruptedException, ExecutionException {
         final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = getSessionNegotiatorFactory(keepalive, deadtimer);
         for (final InetAddress pceAddress : remoteAddress) {
             pccDispatcher.createClient(new InetSocketAddress(localAddress, 0), new InetSocketAddress(pceAddress, DEFAULT_PORT), new ReconnectImmediatelyStrategy(GlobalEventExecutor.INSTANCE, RECONNECT_STRATEGY_TIMEOUT), new SessionListenerFactory<PCEPSessionListener>() {
@@ -105,7 +112,7 @@ public final class Main {
                 public PCEPSessionListener getSessionListener() {
                     return new SimpleSessionListener(lspsPerPcc, pcerr, localAddress);
                 }
-            }, snf);
+            }, snf, getKeyMapping(pceAddress, password));
         }
     }
 
@@ -137,4 +144,13 @@ public final class Main {
         });
     }
 
+    private static KeyMapping getKeyMapping(final InetAddress inetAddress, final String password) {
+        if (password != null) {
+            final KeyMapping keyMapping = new KeyMapping();
+            keyMapping.put(inetAddress, password.getBytes(Charsets.US_ASCII));
+            return keyMapping;
+        }
+        return null;
+    }
+
 }
index 251162f5011356b30212107bb8f5efe7ef1aea66..c1d410d3d5331fd7c764c17b5fda3164642424fe 100644 (file)
@@ -22,22 +22,42 @@ import org.opendaylight.protocol.pcep.impl.PCEPDispatcherImpl;
 import org.opendaylight.protocol.pcep.impl.PCEPHandlerFactory;
 import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
 import org.opendaylight.protocol.pcep.spi.MessageRegistry;
+import org.opendaylight.tcpmd5.api.DummyKeyAccessFactory;
+import org.opendaylight.tcpmd5.api.KeyAccessFactory;
+import org.opendaylight.tcpmd5.api.KeyMapping;
+import org.opendaylight.tcpmd5.jni.NativeKeyAccessFactory;
+import org.opendaylight.tcpmd5.jni.NativeSupportUnavailableException;
+import org.opendaylight.tcpmd5.netty.MD5ChannelFactory;
+import org.opendaylight.tcpmd5.netty.MD5ChannelOption;
+import org.opendaylight.tcpmd5.netty.MD5NioSocketChannelFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public final class PCCDispatcher extends PCEPDispatcherImpl {
 
     private InetSocketAddress localAddress;
     private final PCEPHandlerFactory factory;
+    private final MD5ChannelFactory<?> cf;
+    private KeyMapping keys;
 
     public PCCDispatcher(final MessageRegistry registry,
             final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory) {
         super(registry, negotiatorFactory, new NioEventLoopGroup(), new NioEventLoopGroup(), null, null);
         this.factory = new PCEPHandlerFactory(registry);
+        this.cf = new MD5NioSocketChannelFactory(DeafultKeyAccessFactory.getKeyAccessFactory());
     }
 
     @Override
     protected void customizeBootstrap(final Bootstrap b) {
-        super.customizeBootstrap(b);
+        if (this.keys != null && !this.keys.isEmpty()) {
+            if (this.cf == null) {
+                throw new UnsupportedOperationException("No key access instance available, cannot use key mapping");
+            }
+
+            b.channelFactory(this.cf);
+            b.option(MD5ChannelOption.TCP_MD5SIG, this.keys);
+        }
         if (this.localAddress != null) {
             b.localAddress(this.localAddress);
         }
@@ -45,8 +65,9 @@ public final class PCCDispatcher extends PCEPDispatcherImpl {
 
     public synchronized Future<PCEPSessionImpl> createClient(final InetSocketAddress localAddress, final InetSocketAddress remoteAddress,
             final ReconnectStrategy strategy, final SessionListenerFactory<PCEPSessionListener> listenerFactory,
-            final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory) {
+            final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> negotiatorFactory, final KeyMapping keys) {
         this.localAddress = localAddress;
+        this.keys = keys;
         final Future<PCEPSessionImpl> futureClient = super.createClient(remoteAddress, strategy, new PipelineInitializer<PCEPSessionImpl>() {
             @Override
             public void initializeChannel(final SocketChannel ch, final Promise<PCEPSessionImpl> promise) {
@@ -57,6 +78,33 @@ public final class PCCDispatcher extends PCEPDispatcherImpl {
             }
         });
         this.localAddress = null;
+        this.keys = null;
         return futureClient;
     }
+
+    private static final class DeafultKeyAccessFactory {
+        private static final Logger LOG = LoggerFactory.getLogger(DeafultKeyAccessFactory.class);
+        private static final KeyAccessFactory FACTORY;
+
+        static {
+            KeyAccessFactory factory;
+
+            try {
+                factory = NativeKeyAccessFactory.getInstance();
+            } catch (NativeSupportUnavailableException e) {
+                LOG.debug("Native key access not available, using no-op fallback", e);
+                factory = DummyKeyAccessFactory.getInstance();
+            }
+
+            FACTORY = factory;
+        }
+
+        private DeafultKeyAccessFactory() {
+            throw new UnsupportedOperationException("Utility class should never be instantiated");
+        }
+
+        public static KeyAccessFactory getKeyAccessFactory() {
+            return FACTORY;
+        }
+    }
 }