Disable to create duplicate (with same IP Address) PCEP sessions. 41/13541/8
authorMilos Fabian <milfabia@cisco.com>
Wed, 10 Dec 2014 15:21:54 +0000 (16:21 +0100)
committerDana Kutenicsova <dkutenic@cisco.com>
Fri, 12 Dec 2014 14:07:46 +0000 (14:07 +0000)
Session ref. entries stored in bi-map were identifed by byte array (raw IP Address of client),
casuing that already existing session in bi-map were not look-up properly => allowing to create duplicate sessions.
Changed type of bi-map's key to wrapper of byte array.

Fixed also removing of session refs. from map on channel close. Turned bi-map to map, since inverse map is not used anymore.

pcc-mock is reusing this code - need to create session negotiator factory per pcc.

Change-Id: I85670b083b6ea832f8b9a4891c812845174f03ff
Signed-off-by: Milos Fabian <milfabia@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
pcep/impl/src/main/java/org/opendaylight/protocol/pcep/impl/AbstractPCEPSessionNegotiatorFactory.java
pcep/impl/src/test/java/org/opendaylight/protocol/pcep/impl/PCEPDispatcherImplTest.java
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/Main.java
pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/PCCMockTest.java

index fca042dfdaf1ea2ea24781049f8d4c149967a654..c03401efdfd99809524ab3edd30f3b6b05ea1759 100644 (file)
@@ -9,23 +9,20 @@ package org.opendaylight.protocol.pcep.impl;
 
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
 import com.google.common.primitives.UnsignedBytes;
-
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import io.netty.util.concurrent.Promise;
-
 import java.net.InetSocketAddress;
+import java.util.Arrays;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
-
 import javax.annotation.concurrent.GuardedBy;
-
 import org.opendaylight.protocol.framework.AbstractSessionNegotiator;
 import org.opendaylight.protocol.framework.SessionListenerFactory;
 import org.opendaylight.protocol.framework.SessionNegotiator;
@@ -62,7 +59,7 @@ public abstract class AbstractPCEPSessionNegotiatorFactory implements
     private static final long ID_CACHE_SECONDS = 3 * 3600;
 
     @GuardedBy("this")
-    private final BiMap<byte[], SessionReference> sessions = HashBiMap.create();
+    private final Map<ByteArrayWrapper, SessionReference> sessions = new HashMap<>();
 
     @GuardedBy("this")
     private final Cache<byte[], PeerRecord> formerClients = CacheBuilder.newBuilder().expireAfterAccess(PEER_CACHE_SECONDS,
@@ -100,12 +97,13 @@ public abstract class AbstractPCEPSessionNegotiatorFactory implements
                  * registered for this client.
                  */
                 final byte[] clientAddress = ((InetSocketAddress) this.channel.remoteAddress()).getAddress().getAddress();
+                final ByteArrayWrapper clientAddressWrapper = new ByteArrayWrapper(clientAddress);
 
                 synchronized (lock) {
-                    if (AbstractPCEPSessionNegotiatorFactory.this.sessions.containsKey(clientAddress)) {
+                    if (AbstractPCEPSessionNegotiatorFactory.this.sessions.containsKey(clientAddressWrapper)) {
                         final byte[] serverAddress = ((InetSocketAddress) this.channel.localAddress()).getAddress().getAddress();
                         if (COMPARATOR.compare(serverAddress, clientAddress) > 0) {
-                            final SessionReference n = AbstractPCEPSessionNegotiatorFactory.this.sessions.remove(clientAddress);
+                            final SessionReference n = AbstractPCEPSessionNegotiatorFactory.this.sessions.remove(clientAddressWrapper);
                             try {
                                 n.close();
                             } catch (final Exception e) {
@@ -121,7 +119,7 @@ public abstract class AbstractPCEPSessionNegotiatorFactory implements
                     final Short sessionId = nextSession(clientAddress);
                     final AbstractPCEPSessionNegotiator n = createNegotiator(promise, factory.getSessionListener(), this.channel, sessionId);
 
-                    AbstractPCEPSessionNegotiatorFactory.this.sessions.put(clientAddress, new SessionReference() {
+                    AbstractPCEPSessionNegotiatorFactory.this.sessions.put(clientAddressWrapper, new SessionReference() {
                         @Override
                         public void close() throws ExecutionException {
                             try {
@@ -146,7 +144,7 @@ public abstract class AbstractPCEPSessionNegotiatorFactory implements
                         @Override
                         public void operationComplete(final ChannelFuture future) {
                             synchronized (lock) {
-                                AbstractPCEPSessionNegotiatorFactory.this.sessions.inverse().remove(this);
+                                AbstractPCEPSessionNegotiatorFactory.this.sessions.remove(clientAddressWrapper);
                             }
                         }
                     });
@@ -175,4 +173,29 @@ public abstract class AbstractPCEPSessionNegotiatorFactory implements
 
         return peer.allocId();
     }
+
+    private static final class ByteArrayWrapper {
+
+        private final byte[] byteArray;
+
+        ByteArrayWrapper(final byte[] byteArray) {
+            this.byteArray = byteArray;
+        }
+
+        @Override
+        public int hashCode() {
+            return Arrays.hashCode(byteArray);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof ByteArrayWrapper)) {
+                return false;
+            }
+            return Arrays.equals(byteArray, ((ByteArrayWrapper) obj).byteArray);
+        }
+    }
 }
index e0ce7c13767d7463e0fcab8075d32ea0b3a538e5..4b239f3d431c8db20bf4c4fa394ca1c445c9b51b 100644 (file)
@@ -53,14 +53,14 @@ public class PCEPDispatcherImplTest {
     public void setUp() {
         final Open open = new OpenBuilder().setSessionId((short) 0).setDeadTimer(DEAD_TIMER).setKeepalive(KEEP_ALIVE)
                 .build();
-        final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = new DefaultPCEPSessionNegotiatorFactory(
-                open, 0);
         final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
         final MessageRegistry msgReg = ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance()
                 .getMessageHandlerRegistry();
-        this.dispatcher = new PCEPDispatcherImpl(msgReg, snf, eventLoopGroup, eventLoopGroup);
-        this.pccMock = new PCCMock<>(snf, new PCEPHandlerFactory(msgReg), new DefaultPromise<PCEPSessionImpl>(
-                GlobalEventExecutor.INSTANCE));
+        this.dispatcher = new PCEPDispatcherImpl(msgReg, new DefaultPCEPSessionNegotiatorFactory(open, 0),
+                eventLoopGroup, eventLoopGroup);
+        this.pccMock = new PCCMock<>(new DefaultPCEPSessionNegotiatorFactory(open, 0),
+                new PCEPHandlerFactory(msgReg), new DefaultPromise<PCEPSessionImpl>(
+                        GlobalEventExecutor.INSTANCE));
     }
 
     @Test
@@ -102,8 +102,80 @@ public class PCEPDispatcherImplTest {
         session1.close();
         session2.close();
         Assert.assertTrue(futureChannel.channel().isActive());
+    }
+
+    @Test
+    public void testCreateDuplicateClient() throws InterruptedException, ExecutionException {
+        final ChannelFuture futureChannel = this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", PORT),
+                new SessionListenerFactory<PCEPSessionListener>() {
+                    @Override
+                    public PCEPSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                });
+        final PCEPSessionImpl session1 = pccMock.createClient(CLIENT1_ADDRESS,
+                new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 500),
+                new SessionListenerFactory<PCEPSessionListener>() {
+                    @Override
+                    public PCEPSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                }).get();
+
+        try {
+            pccMock.createClient(CLIENT1_ADDRESS,
+                    new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 500),
+                    new SessionListenerFactory<PCEPSessionListener>() {
+                        @Override
+                        public PCEPSessionListener getSessionListener() {
+                            return new SimpleSessionListener();
+                        }
+                    }).get();
+            Assert.fail();
+        } catch(ExecutionException e) {
+            Assert.assertTrue(e.getMessage().contains("A conflicting session for address"));
+        } finally {
+            session1.close();
+        }
+    }
 
-        futureChannel.channel().close();
+    @Test
+    public void testReconectClient() throws InterruptedException, ExecutionException {
+        final ChannelFuture futureChannel = this.dispatcher.createServer(new InetSocketAddress("0.0.0.0", PORT),
+                new SessionListenerFactory<PCEPSessionListener>() {
+                    @Override
+                    public PCEPSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                });
+        final PCEPSessionImpl session1 = pccMock.createClient(CLIENT1_ADDRESS,
+                new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 500),
+                new SessionListenerFactory<PCEPSessionListener>() {
+                    @Override
+                    public PCEPSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                }).get();
+
+        Assert.assertEquals(CLIENT1_ADDRESS.getAddress().getHostAddress(), session1.getPeerAddress());
+        Assert.assertEquals(DEAD_TIMER, session1.getDeadTimerValue().shortValue());
+        Assert.assertEquals(KEEP_ALIVE, session1.getKeepAliveTimerValue().shortValue());
+        session1.close();
+
+        final PCEPSessionImpl session2 = pccMock.createClient(CLIENT1_ADDRESS,
+                new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 500),
+                new SessionListenerFactory<PCEPSessionListener>() {
+                    @Override
+                    public PCEPSessionListener getSessionListener() {
+                        return new SimpleSessionListener();
+                    }
+                }).get();
+
+        Assert.assertEquals(CLIENT1_ADDRESS.getAddress().getHostAddress(), session2.getPeerAddress());
+        Assert.assertEquals(DEAD_TIMER, session2.getDeadTimerValue().shortValue());
+        Assert.assertEquals(KEEP_ALIVE, session2.getKeepAliveTimerValue().shortValue());
+
+        session2.close();
     }
 
     @After
index 74e591f679a42820dd5ad37a476f4b32bd7a1e59..0c7b6e98fca8abc9179af5d2ee855e724a08b062 100644 (file)
@@ -85,20 +85,19 @@ public final class Main {
 
     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 SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = new DefaultPCEPSessionNegotiatorFactory(
-                new OpenBuilder().setKeepalive(keepalive).setDeadTimer(deadtimer).setSessionId((short) 0).build(), 0);
-
         final StatefulActivator activator07 = new StatefulActivator();
         activator07.start(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance());
-        final PCCMock<Message, PCEPSessionImpl, PCEPSessionListener> pcc = new PCCMock<>(snf, new PCEPHandlerFactory(
-                ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance().getMessageHandlerRegistry()),
-                new DefaultPromise<PCEPSessionImpl>(GlobalEventExecutor.INSTANCE));
-
         for (final InetAddress pceAddress : remoteAddress) {
             InetAddress currentAddress = localAddress;
             int i = 0;
             while (i < pccCount) {
                 final InetAddress pccAddress = currentAddress;
+                final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = new DefaultPCEPSessionNegotiatorFactory(
+                        new OpenBuilder().setKeepalive(keepalive).setDeadTimer(deadtimer).setSessionId((short) 0).build(), 0);
+
+                final PCCMock<Message, PCEPSessionImpl, PCEPSessionListener> pcc = new PCCMock<>(snf, new PCEPHandlerFactory(
+                        ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance().getMessageHandlerRegistry()),
+                        new DefaultPromise<PCEPSessionImpl>(GlobalEventExecutor.INSTANCE));
                 pcc.createClient(new InetSocketAddress(pccAddress, 0), new InetSocketAddress(pceAddress, DEFAULT_PORT),
                         new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, RECONNECT_STRATEGY_TIMEOUT),
                         new SessionListenerFactory<PCEPSessionListener>() {
index 225b673e036195ca6269c62aef5aac8096636f95..401369e10a9050a00561787a3ff474f7a31a04bf 100644 (file)
@@ -42,7 +42,7 @@ public class PCCMockTest {
             org.opendaylight.protocol.pcep.testtool.Main.main(new String[]{"-a", "127.0.4.0:4189", "-ka", "10", "-d", "0", "--stateful", "--active"});
             org.opendaylight.protocol.pcep.testtool.Main.main(new String[]{"-a", "127.0.2.0:4189", "-ka", "10", "-d", "0", "--stateful", "--active"});
             org.opendaylight.protocol.pcep.testtool.Main.main(new String[]{"-a", "127.0.3.0:4189", "-ka", "10", "-d", "0", "--stateful", "--active"});
-            Main.main(new String[] {"--local-address", "127.0.0.1", "--remote-address", "127.0.4.0,127.0.2.0,127.0.3.0"});
+            Main.main(new String[] {"--local-address", "127.0.0.1", "--remote-address", "127.0.4.0,127.0.2.0,127.0.3.0", "--pcc", "3"});
         } catch (Exception e) {
             Assert.fail(e.getMessage());
         }