Bug 2208 - pcc-mock: enhancemnets 53/22853/4
authorLadislav Borak <lborak@cisco.com>
Wed, 10 Jun 2015 14:56:04 +0000 (16:56 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 3 Jul 2015 11:16:37 +0000 (11:16 +0000)
*new functionality
- refuse operations with not delegated LSP
- refuse removing of non PCE-initiated LSPs
- delegate PCC's LSPs to the first PCE at start-up
- support "return delegate" request from PCE for PCC's LSPs, re-delegate, after the "redelegation timeout" expires, to the next PCE in cyclic order
- support "delegate" and "return delegation" for PCE-initiated LSPs, delete LSP if "state-timeout" expires
- if PCE connects, report all LSPs (PCC's and PCE-initiated) with actual state

*new input arguments
--redelegation-timeout <seconds>, default 0 - start timer when delegation for PCC's LSP is returned or when PCE fails;
hold delegation for PCE until expiration; timout is cancelled when LSP is delegated to PCE

--state-timeout <seconds>, default -1 (infinite) - start timer when delegation is returned or when PCE fails;
after timeout expiration, LSP is removed; timeout is cancelled when LSP is delegated to PCE

*new PCEP error added
- LSP is not PCE-initiated Error-type=19, Error-value=9

Change-Id: I7bb4cdf03dd04f9caddc13cf7a70c913aa7e6e2b
Signed-off-by: Ladislav Borak <lborak@cisco.com>
Signed-off-by: Milos Fabian <milfabia@cisco.com>
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/MsgBuilderUtil.java
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PccSessionListener.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PccTunnelManagerImpl.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListener.java [deleted file]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/api/PccSession.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/api/PccTunnelManager.java [new file with mode: 0644]
pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/PccSessionListenerTest.java [new file with mode: 0644]
pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/PccTunnelManagerImplTest.java [new file with mode: 0644]
pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListenerTest.java [deleted file]
pcep/spi/src/main/java/org/opendaylight/protocol/pcep/spi/PCEPErrors.java

index 6b032b94203d8223da061c5ac2fe511cc9022770..0c20fc6b15dd25b9f80142b65d0a743376eff9b5 100644 (file)
@@ -17,6 +17,8 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.net.HostAndPort;
 import com.google.common.net.InetAddresses;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timer;
 import io.netty.util.concurrent.GlobalEventExecutor;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
@@ -35,6 +37,7 @@ import org.opendaylight.protocol.pcep.ietf.initiated00.CrabbeInitiatedActivator;
 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.pcc.mock.api.PccTunnelManager;
 import org.opendaylight.protocol.pcep.spi.PCEPExtensionProviderContext;
 import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
 import org.opendaylight.tcpmd5.api.KeyMapping;
@@ -74,6 +77,9 @@ public final class Main {
         short dt = DEFAULT_DEAD_TIMER;
         String password = null;
         int reconnectTime = -1;
+        int redelegationTimeout = 0;
+        int stateTimeout = -1;
+        final Timer timer = new HashedWheelTimer();
 
         getRootLogger(lc).setLevel(ch.qos.logback.classic.Level.INFO);
         int argIdx = 0;
@@ -98,41 +104,49 @@ public final class Main {
                 password = args[++argIdx];
             } else if (args[argIdx].equals("--reconnect")) {
                 reconnectTime = Integer.valueOf(args[++argIdx]).intValue() * 1000;
+            } else if (args[argIdx].equals("--redelegation-timeout")) {
+                redelegationTimeout = Integer.valueOf(args[++argIdx]);
+            } else if (args[argIdx].equals("--state-timeout")) {
+                stateTimeout = Integer.valueOf(args[++argIdx]);
             } else {
                 LOG.warn("WARNING: Unrecognized argument: {}", args[argIdx]);
             }
             argIdx++;
         }
-        createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt, password, reconnectTime);
+        createPCCs(lsps, pcError, pccCount, localAddress, remoteAddress, ka, dt, password, reconnectTime, redelegationTimeout, stateTimeout, timer);
     }
 
     public static void createPCCs(final int lspsPerPcc, final boolean pcerr, final int pccCount,
             final InetSocketAddress localAddress, final List<InetSocketAddress> remoteAddress, final short keepalive, final short deadtimer,
-            final String password, final int reconnectTime) throws InterruptedException, ExecutionException {
+            final String password, final int reconnectTime, final int redelegationTimeout, final int stateTimeout, final Timer timer) throws InterruptedException, ExecutionException {
         startActivators();
         InetAddress currentAddress = localAddress.getAddress();
         final Open openMessage = getOpenMessage(keepalive, deadtimer);
         final PCCDispatcher pccDispatcher = new PCCDispatcher(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance().getMessageHandlerRegistry(),
                 getSessionNegotiatorFactory(openMessage));
         for (int i = 0; i < pccCount; i++) {
-            createPCC(lspsPerPcc, pcerr, new InetSocketAddress(currentAddress, localAddress.getPort()),
-                    remoteAddress, openMessage, pccDispatcher, password, reconnectTime);
+            final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(lspsPerPcc, currentAddress,
+                    redelegationTimeout, stateTimeout, timer);
+            createPCC(pcerr, new InetSocketAddress(currentAddress, localAddress.getPort()),
+                    remoteAddress, openMessage, pccDispatcher, password, reconnectTime, tunnelManager);
             currentAddress = InetAddresses.increment(currentAddress);
         }
     }
 
     @SuppressWarnings("deprecation")
-    private static void createPCC(final int lspsPerPcc, final boolean pcerr, final InetSocketAddress localAddress,
+    private static void createPCC(final boolean pcerr, final InetSocketAddress localAddress,
             final List<InetSocketAddress> remoteAddress, final Open openMessage, final PCCDispatcher pccDispatcher,
-            final String password, final int reconnectTime) throws InterruptedException, ExecutionException {
+            final String password, final int reconnectTime, final PccTunnelManager tunnelManager) throws InterruptedException, ExecutionException {
         final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = getSessionNegotiatorFactory(openMessage);
+
         for (final InetSocketAddress pceAddress : remoteAddress) {
-            pccDispatcher.createClient(localAddress, pceAddress, reconnectTime == -1 ? getNeverReconnectStrategyFactory() : getTimedReconnectStrategyFactory(reconnectTime), new SessionListenerFactory<PCEPSessionListener>() {
-                @Override
-                public PCEPSessionListener getSessionListener() {
-                    return new SimpleSessionListener(lspsPerPcc, pcerr, localAddress.getAddress());
-                }
-            }, snf, getKeyMapping(pceAddress.getAddress(), password));
+            pccDispatcher.createClient(localAddress, pceAddress, reconnectTime == -1 ? getNeverReconnectStrategyFactory() : getTimedReconnectStrategyFactory(reconnectTime),
+                    new SessionListenerFactory<PCEPSessionListener>() {
+                        @Override
+                        public PCEPSessionListener getSessionListener() {
+                            return new PccSessionListener(remoteAddress.indexOf(pceAddress), tunnelManager, pcerr);
+                        }
+                    } ,snf, getKeyMapping(pceAddress.getAddress(), password));
         }
     }
 
index 40ad4b0af8ec5d48eb2f26cdfbeec3f0c2938581..88513dcf4b4a7508339a02cd8855c77a7dbbd204 100644 (file)
@@ -39,8 +39,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.iet
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
-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.explicit.route.object.EroBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObjectBuilder;
@@ -68,20 +68,24 @@ public final class MsgBuilderUtil {
         return rptBuilder.build();
     }
 
-    public static Lsp createLsp(final long plspId, final boolean sync, final Optional<Tlvs> tlvs) {
+    public static Lsp createLsp(final long plspId, final boolean sync, final Optional<Tlvs> tlvs, final boolean isDelegatedLsp, final boolean remove) {
         final LspBuilder lspBuilder = new LspBuilder();
         lspBuilder.setAdministrative(true);
-        lspBuilder.setDelegate(true);
+        lspBuilder.setDelegate(isDelegatedLsp);
         lspBuilder.setIgnore(false);
         lspBuilder.setOperational(OperationalStatus.Up);
         lspBuilder.setPlspId(new PlspId(plspId));
         lspBuilder.setProcessingRule(false);
-        lspBuilder.setRemove(false);
+        lspBuilder.setRemove(remove);
         lspBuilder.setSync(sync);
         lspBuilder.setTlvs(tlvs.orNull());
         return lspBuilder.build();
     }
 
+    public static Lsp createLsp(final long plspId, final boolean sync, final Optional<Tlvs> tlvs, final boolean isDelegatedLspe) {
+        return createLsp(plspId, sync, tlvs, isDelegatedLspe, false);
+    }
+
     public static Path createPath(final List<Subobject> subobjects) {
         final PathBuilder pathBuilder = new PathBuilder();
         pathBuilder.setEro(new EroBuilder().setSubobject(subobjects).build());
@@ -97,15 +101,19 @@ public final class MsgBuilderUtil {
     }
 
     public static Path updToRptPath(
-            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.Path path) {
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.Path path) {
         final PathBuilder pathBuilder = new PathBuilder();
-        pathBuilder.fieldsFrom(path);
+        if (path != null) {
+            pathBuilder.fieldsFrom(path);
+        }
         return pathBuilder.build();
     }
 
     public static Path reqToRptPath(final Requests request) {
         final PathBuilder pathBuilder = new PathBuilder();
-        pathBuilder.fieldsFrom(request);
+        if (request != null) {
+            pathBuilder.fieldsFrom(request);
+        }
         return pathBuilder.build();
     }
 
@@ -122,19 +130,18 @@ public final class MsgBuilderUtil {
                                                 new Ipv4ExtendedTunnelId(extendedTunnelAddress))
                                         .build()).build()).setTunnelId(new TunnelId((int) lspId)).build());
         if (symbolicPathName) {
-            final byte[] pathName;
             if (symbolicName.isPresent()) {
-                pathName = symbolicName.get();
+                tlvs.setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(
+                        new SymbolicPathName(symbolicName.get())).build());
             } else {
-                pathName = ("pcc_" + tunnelSender + "_tunnel_" + lspId).getBytes(Charsets.UTF_8);
+                tlvs.setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(
+                        new SymbolicPathName(getDefaultPathName(tunnelSender, lspId))).build());
             }
-            tlvs.setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(
-                    new SymbolicPathName(pathName)).build());
         }
         return tlvs.build();
     }
 
-    public static Message createErrorMsg(final PCEPErrors e, final long srpId) {
+    public static Pcerr createErrorMsg(final PCEPErrors e, final long srpId) {
         final PcerrMessageBuilder msgBuilder = new PcerrMessageBuilder();
         return new PcerrBuilder().setPcerrMessage(
                 msgBuilder
@@ -151,4 +158,8 @@ public final class MsgBuilderUtil {
                                                 .build()).build())).build()).build();
     }
 
+    public static byte[] getDefaultPathName(final String address, final long lspId) {
+        return ("pcc_" + address + "_tunnel_" + lspId).getBytes(Charsets.UTF_8);
+    }
+
 }
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PccSessionListener.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PccSessionListener.java
new file mode 100644 (file)
index 0000000..a367898
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import java.util.Random;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.PCEPTerminationReason;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Pcinitiate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
+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 class PccSessionListener implements PCEPSessionListener, PccSession {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PccSessionListener.class);
+
+    private final boolean errorMode;
+    private final PccTunnelManager tunnelManager;
+    private final int sessionId;
+    private PCEPSession session;
+
+    public PccSessionListener(final int sessionId, final PccTunnelManager tunnelManager, final boolean errorMode) {
+        this.errorMode = errorMode;
+        this.tunnelManager = tunnelManager;
+        this.sessionId = sessionId;
+    }
+
+    @Override
+    public void onMessage(final PCEPSession session, final Message message) {
+        LOG.trace("Received message: {}", message);
+        if (this.errorMode) {
+            //random error message
+            session.sendMessage(createErrorMessage(message));
+            return;
+        }
+        if (message instanceof Pcupd) {
+            final Updates update = ((Pcupd) message).getPcupdMessage().getUpdates().get(0);
+            if (update.getLsp().isDelegate() != null && update.getLsp().isDelegate()) {
+                //regular LSP update
+                this.tunnelManager.reportToAll(update, this);
+            } else {
+                //returning LSP delegation
+                this.tunnelManager.returnDelegation(update, this);
+            }
+        } else if (message instanceof Pcinitiate) {
+            final Requests request = ((Pcinitiate) message).getPcinitiateMessage().getRequests().get(0);
+            if (request.getSrp().getAugmentation(Srp1.class) != null && request.getSrp().getAugmentation(Srp1.class).isRemove()) {
+                //remove LSP
+                this.tunnelManager.removeTunnel(request, this);
+            } else if (request.getLsp().isDelegate() != null && request.getLsp().isDelegate() && request.getEndpointsObj() == null) {
+                //take LSP delegation
+                this.tunnelManager.takeDelegation(request, this);
+            } else {
+                //create LSP
+                this.tunnelManager.addTunnel(request, this);
+            }
+        }
+    }
+
+    @Override
+    public void onSessionUp(final PCEPSession session) {
+        LOG.debug("Session up.");
+        this.session = session;
+        this.tunnelManager.onSessionUp(this);
+    }
+
+    @Override
+    public void onSessionDown(final PCEPSession session, final Exception e) {
+        LOG.info("Session down with cause : {} or exception: {}", e.getCause(), e, e);
+        this.tunnelManager.onSessionDown(this);
+        session.close();
+    }
+
+    @Override
+    public void onSessionTerminated(final PCEPSession session, final PCEPTerminationReason cause) {
+        LOG.info("Session terminated. Cause : {}", cause.toString());
+    }
+
+    @Override
+    public void sendReport(final Pcrpt reportMessage) {
+        this.session.sendMessage(reportMessage);
+    }
+
+    @Override
+    public void sendError(final Pcerr errorMessage) {
+        this.session.sendMessage(errorMessage);
+    }
+
+    @Override
+    public int getId() {
+        return this.sessionId;
+    }
+
+    private final Random rnd = new Random();
+
+    private PCEPErrors getRandomError() {
+        return PCEPErrors.values()[this.rnd.nextInt(PCEPErrors.values().length)];
+    }
+
+    private Pcerr createErrorMessage(final Message message) {
+        final Srp srp;
+        if (message instanceof Pcupd) {
+            srp = ((Pcupd) message).getPcupdMessage().getUpdates().get(0).getSrp();
+        } else {
+            srp = ((Pcinitiate) message).getPcinitiateMessage().getRequests().get(0).getSrp();
+        }
+        return MsgBuilderUtil.createErrorMsg(getRandomError(), srp.getOperationId().getValue());
+    }
+
+}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PccTunnelManagerImpl.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PccTunnelManagerImpl.java
new file mode 100644 (file)
index 0000000..7f6112b
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLsp;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLspTlvs;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPath;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPcRtpMessage;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createSrp;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.reqToRptPath;
+import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.updToRptPath;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.net.InetAddresses;
+import io.netty.util.Timeout;
+import io.netty.util.Timer;
+import io.netty.util.TimerTask;
+import java.net.InetAddress;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.Lsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.Path;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.PathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
+
+public class PccTunnelManagerImpl implements PccTunnelManager {
+
+    private static final Subobject DEFAULT_ENDPOINT_HOP = getDefaultEROEndpointHop();
+    private static final String ENDPOINT_ADDRESS = "1.1.1.1";
+    private static final String ENDPOINT_PREFIX = ENDPOINT_ADDRESS + "/32";
+    private static final Optional<Srp> NO_SRP = Optional.<Srp> absent();
+    private static final int PCC_DELEGATION = -1;
+
+    @GuardedBy("this")
+    private final Map<Integer, PccSession> sessions = new HashMap<>();
+
+    @GuardedBy("this")
+    private final Map<PlspId, Tunnel> tunnels = new HashMap<>();
+
+    private final AtomicLong plspIDsCounter;
+    private final String address;
+    private final Timer timer;
+    private final int redelegationTimeout;
+    private final int stateTimeout;
+
+    public PccTunnelManagerImpl(final int lspsCount, final InetAddress address, final int redelegationTimeout,
+            final int stateTimeout, final Timer timer) {
+        Preconditions.checkArgument(lspsCount >= 0);
+        Preconditions.checkNotNull(address);
+        this.redelegationTimeout = redelegationTimeout;
+        this.stateTimeout = stateTimeout;
+        this.plspIDsCounter = new AtomicLong(lspsCount);
+        this.address = InetAddresses.toAddrString(Preconditions.checkNotNull(address));
+        this.timer = Preconditions.checkNotNull(timer);
+        for (int i = 1; i <= lspsCount; i++) {
+            final Tunnel tunnel = new Tunnel(MsgBuilderUtil.getDefaultPathName(this.address, i), PCC_DELEGATION, LspType.PCC_LSP,
+                    createPath(Lists.newArrayList(DEFAULT_ENDPOINT_HOP)));
+            tunnels.put(new PlspId((long) i), tunnel);
+        }
+    }
+
+    @Override
+    public void reportToAll(final Updates update, final PccSession session) {
+        final PlspId plspId = update.getLsp().getPlspId();
+        final Tunnel tunnel = tunnels.get(plspId);
+        final long srpId = update.getSrp().getOperationId().getValue();
+        if (tunnel != null) {
+            if (hasDelegation(tunnel, session)) {
+                final Srp srp = createSrp(update.getSrp().getOperationId().getValue());
+                final Path path = updToRptPath(update.getPath());
+                final List<Subobject> subobjects = update.getPath().getEro().getSubobject();
+                final Lsp lsp = update.getLsp();
+                sendToAll(tunnel, plspId, subobjects, srp, path, lsp);
+                //update tunnel state
+                tunnel.setLspState(path);
+            } else {
+                session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
+            }
+        } else {
+            session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+        }
+    }
+
+    @Override
+    public void returnDelegation(final Updates update, final PccSession session) {
+        final PlspId plspId = update.getLsp().getPlspId();
+        final Tunnel tunnel = tunnels.get(plspId);
+        final long srpId = update.getSrp().getOperationId().getValue();
+        if (tunnel != null) {
+            //check if session really has a delegation
+            if (hasDelegation(tunnel, session)) {
+                //send report D=0
+                final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+                        getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address), this.address,
+                        this.address, Optional.of(tunnel.getPathName()));
+                session.sendReport(createPcRtpMessage(
+                        new LspBuilder(update.getLsp()).setSync(true).setOperational(OperationalStatus.Up).setDelegate(false).setTlvs(tlvs).build(),
+                        Optional.of(createSrp(srpId)), tunnel.getLspState()));
+                //start state timer
+                startStateTimeout(tunnel, plspId);
+                //if PCC's LSP, start re-delegation timer
+                if (tunnel.getType() == LspType.PCC_LSP) {
+                    startRedelegationTimer(tunnel, plspId, session);
+                } else {
+                    //if PCE-initiated LSP, revoke delegation instantly
+                    setDelegation(plspId, null);
+                }
+            } else {
+                session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
+            }
+        } else {
+            session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+        }
+    }
+
+    @Override
+    public synchronized void onSessionUp(final PccSession session) {
+        //first session - delegate all PCC's LSPs
+        //only when reporting at startup
+        if (! sessions.containsKey(session.getId()) && session.getId() == 0) {
+            for (final PlspId plspId : tunnels.keySet()) {
+                setDelegation(plspId, session);
+            }
+        }
+        sessions.put(session.getId(), session);
+        if (!tunnels.isEmpty()) {
+            //report all known LSPs
+            for (final Entry<PlspId, Tunnel> entry : tunnels.entrySet()) {
+                final Tunnel tunnel = entry.getValue();
+                final boolean delegation = hasDelegation(tunnel, session);
+                if (delegation) {
+                    tunnel.cancelTimeouts();
+                }
+                final long plspId = entry.getKey().getValue();
+                final Tlvs tlvs = MsgBuilderUtil.createLspTlvs(plspId, true,
+                        getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), PccTunnelManagerImpl.this.address), this.address,
+                        this.address, Optional.of(tunnel.getPathName()));
+                session.sendReport(createPcRtpMessage(
+                        createLsp(plspId, true, Optional.<Tlvs> fromNullable(tlvs), delegation, false), NO_SRP,
+                        tunnel.getLspState()));
+            }
+            //end-of-sync marker
+            session.sendReport(createPcRtpMessage(createLsp(0, false, Optional.<Tlvs> absent(), true, false), NO_SRP,
+                    createPath(Collections.<Subobject> emptyList())));
+        }
+    }
+
+    @Override
+    public void takeDelegation(final Requests request, final PccSession session) {
+        final PlspId plspId = request.getLsp().getPlspId();
+        final Tunnel tunnel = tunnels.get(plspId);
+        final long srpId = request.getSrp().getOperationId().getValue();
+        if (tunnel != null) {
+            //check if tunnel has no delegation
+            if (tunnel.type == LspType.PCE_LSP && (tunnel.getDelegationHolder() == -1 || tunnel.getDelegationHolder() == session.getId())) {
+                //set delegation
+                tunnel.cancelTimeouts();
+                setDelegation(plspId, session);
+                //send report
+                final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+                        getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address), this.address,
+                        this.address, Optional.of(tunnel.getPathName()));
+                session.sendReport(createPcRtpMessage(
+                        new LspBuilder(request.getLsp()).setSync(true).setOperational(OperationalStatus.Up).setDelegate(true).setTlvs(tlvs).build(),
+                        Optional.of(createSrp(srpId)), tunnel.getLspState()));
+            } else {
+                session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
+            }
+        } else {
+            session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+        }
+    }
+
+    @Override
+    public synchronized void onSessionDown(final PccSession session) {
+        for (final Entry<PlspId, Tunnel> entry : tunnels.entrySet()) {
+            final Tunnel tunnel = entry.getValue();
+            final PlspId plspId = entry.getKey();
+            //deal with delegations
+            if (hasDelegation(tunnel, session)) {
+                startStateTimeout(tunnel, entry.getKey());
+                startRedelegationTimer(tunnel, plspId, session);
+            }
+        }
+    }
+
+    @Override
+    public void addTunnel(final Requests request, final PccSession session) {
+        final PlspId plspId = new PlspId(this.plspIDsCounter.incrementAndGet());
+        final Tunnel tunnel = new Tunnel(request.getLsp().getTlvs().getSymbolicPathName().getPathName().getValue(),
+                session.getId(), LspType.PCE_LSP, reqToRptPath(request));
+        sendToAll(tunnel, plspId, request.getEro().getSubobject(), createSrp(request.getSrp().getOperationId().getValue()),
+                tunnel.getLspState(), new LspBuilder(request.getLsp()).addAugmentation(Lsp1.class, new Lsp1Builder().setCreate(true).build()).build());
+        tunnels.put(plspId, tunnel);
+    }
+
+    @Override
+    public void removeTunnel(final Requests request, final PccSession session) {
+        final PlspId plspId = request.getLsp().getPlspId();
+        final Tunnel tunnel = tunnels.get(plspId);
+        final long srpId = request.getSrp().getOperationId().getValue();
+        if (tunnel != null) {
+            if (tunnel.getType() == LspType.PCE_LSP) {
+                if (hasDelegation(tunnel, session)) {
+                    tunnels.remove(plspId);
+                    sendToAll(tunnel, plspId, tunnel.getLspState().getEro().getSubobject(),
+                            new SrpBuilder(request.getSrp()).addAugmentation(Srp1.class, new Srp1Builder().setRemove(true).build()).build(),
+                            reqToRptPath(request), request.getLsp());
+                } else {
+                    session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
+                }
+            } else {
+                session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
+            }
+        } else {
+            session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
+        }
+    }
+
+    private void sendToAll(final Tunnel tunnel, final PlspId plspId, final List<Subobject> subobjects, final Srp srp, final Path path, final Lsp lsp) {
+        for (final PccSession session : sessions.values()) {
+            final boolean isDelegated = hasDelegation(tunnel, session);
+            final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+                    getDestinationAddress(subobjects, this.address), this.address,
+                    this.address, Optional.of(tunnel.getPathName()));
+            final Pcrpt pcRpt = createPcRtpMessage(
+                    new LspBuilder(lsp).setPlspId(plspId).setOperational(OperationalStatus.Up).setDelegate(isDelegated).setTlvs(tlvs).build(),
+                    Optional.fromNullable(srp), path);
+            session.sendReport(pcRpt);
+        }
+    }
+
+    private void startStateTimeout(final Tunnel tunnel, final PlspId plspId) {
+        if (this.stateTimeout > -1) {
+            final Timeout stateTimeout = this.timer.newTimeout(new TimerTask() {
+                @Override
+                public void run(final Timeout timeout) throws Exception {
+                    if (tunnel.getType() == LspType.PCE_LSP) {
+                        PccTunnelManagerImpl.this.tunnels.remove(plspId);
+                        //report tunnel removal to all
+                        sendToAll(tunnel, plspId, Collections.<Subobject>emptyList(), createSrp(0), new PathBuilder().build(),
+                                createLsp(plspId.getValue(), false, Optional.<Tlvs>absent(), false, true));
+                    }
+                }
+            }, this.stateTimeout, TimeUnit.SECONDS);
+            tunnel.setStateTimeout(stateTimeout);
+        }
+    }
+
+    private void startRedelegationTimer(final Tunnel tunnel, final PlspId plspId, final PccSession session) {
+        final Timeout redelegationTimeout = this.timer.newTimeout(new TimerTask() {
+            @Override
+            public void run(final Timeout timeout) throws Exception {
+                //remove delegation
+                PccTunnelManagerImpl.this.setDelegation(plspId, null);
+                //delegate to another PCE
+                int index = session.getId();
+                for (int i = 1; i < sessions.size(); i++) {
+                    index++;
+                    if (index == sessions.size()) {
+                        index = 0;
+                    }
+                    final PccSession nextSession = sessions.get(index);
+                    if (nextSession != null) {
+                        tunnel.cancelTimeouts();
+                        final Tlvs tlvs = createLspTlvs(plspId.getValue(), true,
+                                getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), PccTunnelManagerImpl.this.address),
+                                PccTunnelManagerImpl.this.address, PccTunnelManagerImpl.this.address, Optional.of(tunnel.getPathName()));
+                        nextSession.sendReport(createPcRtpMessage(
+                                createLsp(plspId.getValue(), true, Optional.<Tlvs> fromNullable(tlvs), true, false), NO_SRP,
+                                tunnel.getLspState()));
+                        tunnel.setDelegationHolder(nextSession.getId());
+                        break;
+                    }
+                }
+            }
+        }, this.redelegationTimeout, TimeUnit.SECONDS);
+        tunnel.setRedelegationTimeout(redelegationTimeout);
+    }
+
+    private void setDelegation(final PlspId plspId, final PccSession session) {
+        final Tunnel tunnel = tunnels.get(plspId);
+        final int sessionId;
+        if (session != null) {
+            sessionId = session.getId();
+        } else {
+            sessionId = PCC_DELEGATION;
+        }
+        tunnel.setDelegationHolder(sessionId);
+    }
+
+    private static boolean hasDelegation(final Tunnel tunnel, final PccSession session) {
+        return tunnel.getDelegationHolder() == session.getId();
+    }
+
+    private static final class Tunnel {
+        private final byte[] pathName;
+        private int delegationHolder;
+        private final LspType type;
+        private Path lspState;
+        private Timeout redelegationTimeout;
+        private Timeout stateTimeout;
+
+        public Tunnel(final byte[] pathName, final int delegationHolder, final LspType type, final Path lspState) {
+            this.pathName = pathName;
+            this.delegationHolder = delegationHolder;
+            this.type = type;
+            this.lspState = lspState;
+        }
+
+        public byte[] getPathName() {
+            return pathName;
+        }
+
+        public int getDelegationHolder() {
+            return delegationHolder;
+        }
+
+        public LspType getType() {
+            return type;
+        }
+
+        public Path getLspState() {
+            return lspState;
+        }
+
+        public void setRedelegationTimeout(final Timeout redelegationTimeout) {
+            this.redelegationTimeout = redelegationTimeout;
+        }
+
+        public void setStateTimeout(final Timeout stateTimeout) {
+            this.stateTimeout = stateTimeout;
+        }
+
+        public void cancelTimeouts() {
+            if (this.redelegationTimeout != null) {
+                this.redelegationTimeout.cancel();
+            }
+            if (this.stateTimeout != null) {
+                this.stateTimeout.cancel();
+            }
+        }
+
+        public void setDelegationHolder(final int delegationHolder) {
+            this.delegationHolder = delegationHolder;
+        }
+
+        public void setLspState(final Path lspState) {
+            this.lspState = lspState;
+        }
+
+    }
+
+    enum LspType {
+        PCE_LSP, PCC_LSP
+    }
+
+    private static String getDestinationAddress(final List<Subobject> subobjects, final String defaultAddress) {
+        if (subobjects != null && !subobjects.isEmpty()) {
+            final String prefix = ((IpPrefixCase) subobjects.get(subobjects.size() - 1).getSubobjectType())
+                    .getIpPrefix().getIpPrefix().getIpv4Prefix().getValue();
+            return prefix.substring(0, prefix.indexOf('/'));
+        }
+        return defaultAddress;
+    }
+
+    private static Subobject getDefaultEROEndpointHop() {
+        final SubobjectBuilder builder = new SubobjectBuilder();
+        builder.setLoose(false);
+        builder.setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(new IpPrefixBuilder().setIpPrefix(
+                new IpPrefix(new Ipv4Prefix(ENDPOINT_PREFIX))).build()).build());
+        return builder.build();
+    }
+
+}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListener.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListener.java
deleted file mode 100644 (file)
index cb84261..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.protocol.pcep.pcc.mock;
-
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLsp;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createLspTlvs;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPath;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createPcRtpMessage;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.createSrp;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.reqToRptPath;
-import static org.opendaylight.protocol.pcep.pcc.mock.MsgBuilderUtil.updToRptPath;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import java.net.InetAddress;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicLong;
-import javax.annotation.concurrent.GuardedBy;
-import org.opendaylight.protocol.pcep.PCEPSession;
-import org.opendaylight.protocol.pcep.PCEPSessionListener;
-import org.opendaylight.protocol.pcep.PCEPTerminationReason;
-import org.opendaylight.protocol.pcep.spi.PCEPErrors;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Pcinitiate;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
-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.endpoints.address.family.Ipv4Case;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SimpleSessionListener implements PCEPSessionListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SimpleSessionListener.class);
-
-    private static final String ENDPOINT_ADDRESS = "1.1.1.1";
-    private static final String ENDPOINT_PREFIX = ENDPOINT_ADDRESS + "/32";
-
-    private static final Subobject DEFAULT_ENDPOINT_HOP = getDefaultEROEndpointHop();
-
-    private final int lspsCount;
-    private final boolean pcError;
-    private final String address;
-    private final AtomicLong plspIDs;
-    @GuardedBy("this")
-    private final Map<Long, byte[]> pathNames = new HashMap<>();
-
-    public SimpleSessionListener(final int lspsCount, final boolean pcError, final InetAddress address) {
-        Preconditions.checkArgument(lspsCount >= 0);
-        this.lspsCount = lspsCount;
-        this.pcError = pcError;
-        this.address = address.getHostAddress();
-        this.plspIDs = new AtomicLong(lspsCount);
-    }
-
-    @Override
-    public void onMessage(final PCEPSession session, final Message message) {
-        LOG.trace("Received message: {}", message);
-        if (message instanceof Pcupd) {
-            final Pcupd updMsg = (Pcupd) message;
-            final Updates updates = updMsg.getPcupdMessage().getUpdates().get(0);
-            final long srpId = updates.getSrp().getOperationId().getValue();
-            if (this.pcError) {
-                session.sendMessage(MsgBuilderUtil.createErrorMsg(getRandomError(), srpId));
-            } else {
-                final Tlvs tlvs = createLspTlvs(updates.getLsp().getPlspId().getValue(), true,
-                        getDestinationAddress(updates.getPath().getEro().getSubobject()), this.address, this.address,
-                        Optional.fromNullable(pathNames.get(updates.getLsp().getPlspId().getValue())));
-                final Pcrpt pcRpt = createPcRtpMessage(new LspBuilder(updates.getLsp()).setTlvs(tlvs).build(),
-                        Optional.fromNullable(createSrp(srpId)), updToRptPath(updates.getPath()));
-                session.sendMessage(pcRpt);
-            }
-        } else if (message instanceof Pcinitiate) {
-            final Pcinitiate initMsg = (Pcinitiate) message;
-            final Requests request = initMsg.getPcinitiateMessage().getRequests().get(0);
-            if (this.pcError) {
-                session.sendMessage(MsgBuilderUtil.createErrorMsg(getRandomError(), request.getSrp().getOperationId().getValue()));
-            } else {
-                final Pcrpt pcRpt;
-                if (request.getSrp().getAugmentation(Srp1.class) != null && request.getSrp().getAugmentation(Srp1.class).isRemove()) {
-                    pcRpt = createPcRtpMessage(request.getLsp(), Optional.fromNullable(request.getSrp()), reqToRptPath(request));
-                    this.pathNames.remove(request.getLsp().getPlspId().getValue());
-                } else {
-                    final LspBuilder lspBuilder = new LspBuilder(request.getLsp());
-                    lspBuilder.setPlspId(new PlspId(this.plspIDs.incrementAndGet()));
-                    lspBuilder.addAugmentation(Lsp1.class, new Lsp1Builder().setCreate(true).build());
-                    final Tlvs tlvs = createLspTlvs(lspBuilder.getPlspId().getValue(), true,
-                            ((Ipv4Case) request.getEndpointsObj().getAddressFamily()).getIpv4().getDestinationIpv4Address().getValue(), this.address, this.address,
-                            Optional.of(request.getLsp().getTlvs().getSymbolicPathName().getPathName().getValue()));
-                    lspBuilder.setTlvs(tlvs);
-                    pcRpt = createPcRtpMessage(lspBuilder.build(), Optional.fromNullable(request.getSrp()), reqToRptPath(request));
-                    this.pathNames.put(lspBuilder.getPlspId().getValue(), tlvs.getSymbolicPathName().getPathName().getValue());
-                }
-                session.sendMessage(pcRpt);
-            }
-        }
-    }
-
-    @Override
-    public void onSessionUp(final PCEPSession session) {
-        LOG.debug("Session up.");
-        for (int i = 1; i <= this.lspsCount; i++) {
-            final Tlvs tlvs = MsgBuilderUtil.createLspTlvs(i, true, ENDPOINT_ADDRESS, this.address,
-                    this.address, Optional.<byte[]>absent());
-            session.sendMessage(createPcRtpMessage(
-                    createLsp(i, true, Optional.<Tlvs> fromNullable(tlvs)), Optional.<Srp> absent(),
-                    createPath(Lists.newArrayList(DEFAULT_ENDPOINT_HOP))));
-        }
-        // end-of-sync marker
-        session.sendMessage(createPcRtpMessage(createLsp(0, false, Optional.<Tlvs> absent()), Optional.<Srp> absent(),
-                createPath(Collections.<Subobject> emptyList())));
-    }
-
-    @Override
-    public void onSessionDown(final PCEPSession session, final Exception e) {
-        LOG.info("Session down with cause : {} or exception: {}", e.getCause(), e, e);
-        session.close();
-    }
-
-    @Override
-    public void onSessionTerminated(final PCEPSession session, final PCEPTerminationReason cause) {
-        LOG.info("Session terminated. Cause : {}", cause.toString());
-    }
-
-    private String getDestinationAddress(final List<Subobject> subobjects) {
-        if (subobjects != null && !subobjects.isEmpty()) {
-            final String prefix = ((IpPrefixCase) subobjects.get(subobjects.size() - 1).getSubobjectType())
-                    .getIpPrefix().getIpPrefix().getIpv4Prefix().getValue();
-            return prefix.substring(0, prefix.indexOf('/'));
-        }
-        return this.address;
-    }
-
-    private static Subobject getDefaultEROEndpointHop() {
-        final SubobjectBuilder builder = new SubobjectBuilder();
-        builder.setLoose(false);
-        builder.setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(new IpPrefixBuilder().setIpPrefix(
-                new IpPrefix(new Ipv4Prefix(ENDPOINT_PREFIX))).build()).build());
-        return builder.build();
-    }
-
-    private Random rnd = new Random();
-
-    private PCEPErrors getRandomError() {
-        return PCEPErrors.values()[this.rnd.nextInt(PCEPErrors.values().length)];
-    }
-
-}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/api/PccSession.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/api/PccSession.java
new file mode 100644 (file)
index 0000000..9f0562e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock.api;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
+
+public interface PccSession {
+
+    void sendReport(Pcrpt reportMessage);
+
+    void sendError(Pcerr errorMessage);
+
+    int getId();
+
+}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/api/PccTunnelManager.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/api/PccTunnelManager.java
new file mode 100644 (file)
index 0000000..e46d726
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock.api;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+
+public interface PccTunnelManager {
+
+    void reportToAll(Updates updates, PccSession session);
+
+    void returnDelegation(Updates updates, PccSession session);
+
+    void takeDelegation(Requests request, PccSession session);
+
+    void onSessionUp(PccSession session);
+
+    void onSessionDown(PccSession session);
+
+    void addTunnel(Requests request, PccSession session);
+
+    void removeTunnel(Requests request, PccSession session);
+
+}
diff --git a/pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/PccSessionListenerTest.java b/pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/PccSessionListenerTest.java
new file mode 100644 (file)
index 0000000..3c96e64
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.protocol.pcep.PCEPSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.PcinitiateMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.PcinitiateMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.RequestsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcupdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.PcupdMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.UpdatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.PathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
+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.endpoints.object.EndpointsObjBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
+
+public class PccSessionListenerTest {
+
+    @Mock
+    private PCEPSession mockedSession;
+
+    @Mock
+    private PccTunnelManager tunnelManager;
+
+    private final List<Message> sendMessages = Lists.newArrayList();
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(final InvocationOnMock invocation) throws Throwable {
+                PccSessionListenerTest.this.sendMessages.add((Message) invocation.getArguments()[0]);
+                return null;
+            }
+        }).when(mockedSession).sendMessage(Mockito.any(Message.class));
+    }
+
+    @After
+    public void cleanup() {
+        this.sendMessages.clear();
+    }
+
+    @Test
+    public void testOnMessage() {
+        final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+        listener.onMessage(mockedSession, createUpdMsg(true));
+        Mockito.verify(tunnelManager).reportToAll(Mockito.any(Updates.class), Mockito.any(PccSession.class));
+        listener.onMessage(mockedSession, createUpdMsg(false));
+        Mockito.verify(tunnelManager).returnDelegation(Mockito.any(Updates.class), Mockito.any(PccSession.class));
+        listener.onMessage(mockedSession, createInitMsg(false, true));
+        Mockito.verify(tunnelManager).addTunnel(Mockito.any(Requests.class), Mockito.any(PccSession.class));
+        listener.onMessage(mockedSession, createInitMsg(true, false));
+        Mockito.verify(tunnelManager).removeTunnel(Mockito.any(Requests.class), Mockito.any(PccSession.class));
+        listener.onMessage(mockedSession, createInitMsg(false, false));
+        Mockito.verify(tunnelManager).takeDelegation(Mockito.any(Requests.class), Mockito.any(PccSession.class));
+    }
+
+    @Test
+    public void testOnMessageErrorMode() {
+        final PccSessionListener listener = new PccSessionListener(1, tunnelManager, true);
+        listener.onMessage(mockedSession, createUpdMsg(true));
+        Mockito.verify(mockedSession).sendMessage(Mockito.any(Message.class));
+    }
+
+    @Test
+    public void testOnSessionUp() {
+        final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+        listener.onSessionUp(mockedSession);
+        Mockito.verify(tunnelManager).onSessionUp(Mockito.any(PccSession.class));
+    }
+
+    @Test
+    public void testOnSessionDown() {
+        final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+        listener.onSessionDown(mockedSession, new Exception());
+        Mockito.verify(tunnelManager).onSessionDown(Mockito.any(PccSession.class));
+    }
+
+    @Test
+    public void testSendError() {
+        final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+        listener.onSessionUp(mockedSession);
+        listener.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.ATTEMPT_2ND_SESSION, 0));
+        Mockito.verify(mockedSession).sendMessage(Mockito.<Message>any());
+    }
+
+    @Test
+    public void testSendReport() {
+        final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+        listener.onSessionUp(mockedSession);
+        listener.sendReport(null);
+        Mockito.verify(mockedSession).sendMessage(Mockito.<Message>any());
+    }
+
+    @Test
+    public void testGetId() {
+        final PccSessionListener listener = new PccSessionListener(1, tunnelManager, false);
+        Assert.assertEquals(1, listener.getId());
+    }
+
+    private static PcinitiateMessage createInitMsg(final boolean remove, final boolean endpoint) {
+        // lsp with "unknown" plsp-id
+        final LspBuilder lspBuilder = new LspBuilder()
+            .setAdministrative(true)
+            .setDelegate(true)
+            .setIgnore(false)
+            .setOperational(OperationalStatus.Up)
+            .setPlspId(new PlspId(999L))
+            .setProcessingRule(false)
+            .setRemove(remove)
+            .setSync(true);
+
+        final List<Requests> requests = Lists.newArrayList();
+        final RequestsBuilder reqBuilder = new RequestsBuilder()
+            .setLsp(lspBuilder.build())
+            .setSrp(new SrpBuilder(MsgBuilderUtil.createSrp(123)).addAugmentation(Srp1.class, new Srp1Builder().setRemove(remove).build()).build());
+        if (endpoint) {
+            reqBuilder.setEndpointsObj(new EndpointsObjBuilder().build());
+        }
+        requests.add(reqBuilder.build());
+
+        final PcinitiateMessageBuilder initBuilder = new PcinitiateMessageBuilder()
+            .setRequests(requests);
+        return new PcinitiateBuilder().setPcinitiateMessage(initBuilder.build()).build();
+    }
+
+    private static Pcupd createUpdMsg(final boolean delegation) {
+        final PcupdMessageBuilder msgBuilder = new PcupdMessageBuilder();
+        final UpdatesBuilder updsBuilder = new UpdatesBuilder();
+        updsBuilder.setLsp(new LspBuilder().setDelegate(delegation).setPlspId(new PlspId(1L)).build());
+        final PathBuilder pathBuilder = new PathBuilder();
+        pathBuilder.setEro(
+                new EroBuilder()
+                    .setSubobject(Lists.newArrayList(new SubobjectBuilder().setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(
+                        new IpPrefixBuilder().setIpPrefix(new IpPrefix(new Ipv4Prefix("127.0.0.2/32"))).build()).build()).build())).build());
+        updsBuilder.setPath(pathBuilder.build());
+        updsBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
+        msgBuilder.setUpdates(Lists.newArrayList(updsBuilder.build()));
+        return new PcupdBuilder().setPcupdMessage(msgBuilder.build()).build();
+    }
+}
diff --git a/pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/PccTunnelManagerImplTest.java b/pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/PccTunnelManagerImplTest.java
new file mode 100644 (file)
index 0000000..623d9a2
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.pcep.pcc.mock;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.Lists;
+import com.google.common.net.InetAddresses;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timer;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccSession;
+import org.opendaylight.protocol.pcep.pcc.mock.api.PccTunnelManager;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.RequestsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SymbolicPathName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.UpdatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.PathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.EroBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
+
+public class PccTunnelManagerImplTest {
+
+    private static final InetAddress ADDRESS = InetAddresses.forString("1.2.4.5");
+    private static final Timer TIMER = new HashedWheelTimer();
+    private static final byte[] SYMBOLIC_NAME = "tets".getBytes(Charsets.UTF_8);
+    private static final Ero ERO = new EroBuilder()
+        .setSubobject(Lists.newArrayList(new SubobjectBuilder().setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(
+            new IpPrefixBuilder().setIpPrefix(new IpPrefix(new Ipv4Prefix("127.0.0.2/32"))).build()).build()).build())).build();
+
+    @Mock
+    private PccSession session1;
+    @Mock
+    private PccSession session2;
+
+    private final List<PCEPErrors> errorsSession1 = new ArrayList<>();
+
+    private final List<PCEPErrors> errorsSession2 = new ArrayList<>();
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Mockito.doNothing().when(session1).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(final InvocationOnMock invocation) throws Throwable {
+                errorsSession1.add(getError((Pcerr) invocation.getArguments()[0]));
+                return null;
+            }
+        }).when(session1).sendError(Mockito.any(Pcerr.class));
+        Mockito.doReturn(0).when(session1).getId();
+        Mockito.doNothing().when(session2).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(final InvocationOnMock invocation) throws Throwable {
+                errorsSession2.add(getError((Pcerr) invocation.getArguments()[0]));
+                return null;
+            }
+        }).when(session2).sendError(Mockito.any(Pcerr.class));
+        Mockito.doReturn(1).when(session2).getId();
+    }
+
+    @After
+    public void tearDown() {
+        this.errorsSession1.clear();
+        this.errorsSession2.clear();
+    }
+
+    @Test
+    public void testOnSessionUp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        //1 reported LSP + 1 end-of-sync marker
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        //1 reported LSP + 1 end-of-sync marker
+        Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testOnSessionDownAndDelegateBack() throws InterruptedException {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 1, 10, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        tunnelManager.onSessionDown(session1);
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        tunnelManager.onSessionUp(session1);
+        Mockito.verify(session1, Mockito.times(4)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testOnSessionDownAndDelegateToOther() throws InterruptedException {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, -1, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        tunnelManager.onSessionDown(session1);
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        //wait for re-delegation timeout expires
+        Thread.sleep(500);
+        Mockito.verify(session2, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+        tunnelManager.onSessionUp(session1);
+        Mockito.verify(session1, Mockito.times(4)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testReportToAll() throws InterruptedException {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.reportToAll(createUpdate(1), session1);
+        Mockito.verify(session1, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testReportToAllUnknownLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.reportToAll(createUpdate(2), session1);
+        Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+    }
+
+    @Test
+    public void testReportToAllNonDelegatedLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.reportToAll(createUpdate(1), session2);
+        Mockito.verify(session2, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, errorsSession2.get(0));
+    }
+
+    @Test
+    public void testReturnDelegationPccLsp() throws InterruptedException {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 1, -1, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.returnDelegation(createUpdate(1), session1);
+        Mockito.verify(session1, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        //wait for re-delegation timer expires
+        Thread.sleep(1200);
+        Mockito.verify(session2, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testReturnDelegationUnknownLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.returnDelegation(createUpdate(2), session1);
+        Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+    }
+
+    @Test
+    public void testReturnDelegationNonDelegatedLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.returnDelegation(createUpdate(1), session2);
+        Mockito.verify(session2, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, errorsSession2.get(0));
+    }
+
+    @Test
+    public void testAddTunnel() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.addTunnel(createRequests(1), session1);
+        Mockito.verify(session1, Mockito.times(1)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(1)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testRemoveTunnel() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.addTunnel(createRequests(1), session1);
+        tunnelManager.removeTunnel(createRequests(1), session1);
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testRemoveTunnelUnknownLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.removeTunnel(createRequests(1), session1);
+        Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+    }
+
+    @Test
+    public void testRemoveTunnelNotPceInitiatedLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.removeTunnel(createRequests(1), session1);
+        Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.LSP_NOT_PCE_INITIATED, errorsSession1.get(0));
+    }
+
+    @Test
+    public void testRemoveTunnelNotDelegated() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.addTunnel(createRequests(1), session1);
+        tunnelManager.removeTunnel(createRequests(1), session2);
+        Mockito.verify(session2, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, errorsSession2.get(0));
+    }
+
+    @Test
+    public void testTakeDelegation() throws InterruptedException {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, -1, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.addTunnel(createRequests(1), session1);
+        tunnelManager.returnDelegation(createUpdate(1), session1);
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(1)).sendReport(Mockito.any(Pcrpt.class));
+        Thread.sleep(500);
+        tunnelManager.takeDelegation(createRequests(1), session2);
+        Mockito.verify(session1, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    @Test
+    public void testTakeDelegationUnknownLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.takeDelegation(createRequests(1), session1);
+        Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.UNKNOWN_PLSP_ID, errorsSession1.get(0));
+    }
+
+    @Test
+    public void testTakeDelegationNotPceInitiatedLsp() {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(1, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.takeDelegation(createRequests(1), session1);
+        Mockito.verify(session1, Mockito.times(1)).sendError(Mockito.any(Pcerr.class));
+        assertEquals(PCEPErrors.LSP_NOT_PCE_INITIATED, errorsSession1.get(0));
+    }
+
+    @Test
+    public void testReturnDelegationNoRetake() throws InterruptedException {
+        final PccTunnelManager tunnelManager = new PccTunnelManagerImpl(0, ADDRESS, 0, 0, TIMER);
+        tunnelManager.onSessionUp(session1);
+        tunnelManager.onSessionUp(session2);
+        tunnelManager.addTunnel(createRequests(1), session1);
+        tunnelManager.returnDelegation(createUpdate(1), session1);
+        //wait for state timeout expires
+        Thread.sleep(500);
+        Mockito.verify(session1, Mockito.times(3)).sendReport(Mockito.any(Pcrpt.class));
+        Mockito.verify(session2, Mockito.times(2)).sendReport(Mockito.any(Pcrpt.class));
+    }
+
+    private static Updates createUpdate(final long plspId) {
+        final UpdatesBuilder updsBuilder = new UpdatesBuilder();
+        updsBuilder.setLsp(new LspBuilder().setPlspId(new PlspId(plspId)).build());
+        final PathBuilder pathBuilder = new PathBuilder();
+        pathBuilder.setEro(ERO);
+        updsBuilder.setPath(pathBuilder.build());
+        updsBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
+        return updsBuilder.build();
+    }
+
+    private static Requests createRequests(final long plspId) {
+        final RequestsBuilder reqBuilder = new RequestsBuilder();
+        reqBuilder.setEro(ERO);
+        reqBuilder.setLsp(new LspBuilder()
+            .setTlvs(new TlvsBuilder().setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(SYMBOLIC_NAME)).build()).build())
+            .setPlspId(new PlspId(plspId)).build());
+        reqBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
+        return reqBuilder.build();
+    }
+
+    private static PCEPErrors getError(final Pcerr errorMessage) {
+        final ErrorObject errorObject = errorMessage.getPcerrMessage().getErrors().get(0).getErrorObject();
+        return PCEPErrors.forValue(errorObject.getType(), errorObject.getValue());
+    }
+
+}
diff --git a/pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListenerTest.java b/pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListenerTest.java
deleted file mode 100644 (file)
index fb03a34..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.protocol.pcep.pcc.mock;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import com.google.common.collect.Lists;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.opendaylight.protocol.pcep.PCEPSession;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcupdBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.PcupdMessageBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.UpdatesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.PathBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcerr;
-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.explicit.route.object.EroBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.SubobjectBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
-
-public class SimpleSessionListenerTest {
-
-    private static final String IP_ADDRESS = "127.0.0.1";
-
-    @Mock
-    private PCEPSession mockedSession;
-
-    private final List<Message> sendMessages = Lists.newArrayList();
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        Mockito.doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                SimpleSessionListenerTest.this.sendMessages.add((Message) invocation.getArguments()[0]);
-                return null;
-            }
-        }).when(mockedSession).sendMessage(Mockito.any(Message.class));
-    }
-
-    @After
-    public void cleanup() {
-        this.sendMessages.clear();
-    }
-
-    @Test
-    public void testSessionListenerPcRpt() throws UnknownHostException {
-        final SimpleSessionListener sessionListser = new SimpleSessionListener(1, false, InetAddress.getByName(IP_ADDRESS));
-
-        sessionListser.onSessionUp(this.mockedSession);
-        // one lsp + end-of-sync marker
-        Mockito.verify(this.mockedSession, Mockito.times(2)).sendMessage(Mockito.any(Message.class));
-        assertEquals(2, this.sendMessages.size());
-        assertTrue(this.sendMessages.get(0) instanceof Pcrpt);
-        assertTrue(this.sendMessages.get(1) instanceof Pcrpt);
-
-        sessionListser.onMessage(this.mockedSession, createUpdMsg());
-        // send PcRpt as a response to PcUpd
-        Mockito.verify(this.mockedSession, Mockito.times(3)).sendMessage(Mockito.any(Message.class));
-        assertEquals(3, this.sendMessages.size());
-        assertTrue(this.sendMessages.get(2) instanceof Pcrpt);
-
-        sessionListser.onSessionDown(mockedSession, new Exception());
-        Mockito.verify(this.mockedSession, Mockito.times(1)).close();
-    }
-
-    @Test
-    public void testSessionListenerPcErr() throws UnknownHostException {
-        final SimpleSessionListener sessionListser = new SimpleSessionListener(1, true, InetAddress.getByName(IP_ADDRESS));
-
-        sessionListser.onMessage(this.mockedSession, createUpdMsg());
-        // send PcErr as a response to PcUpd
-        Mockito.verify(this.mockedSession, Mockito.times(1)).sendMessage(Mockito.any(Message.class));
-        assertEquals(1, this.sendMessages.size());
-        assertTrue(this.sendMessages.get(0) instanceof Pcerr);
-    }
-
-    private Pcupd createUpdMsg() {
-        final PcupdMessageBuilder msgBuilder = new PcupdMessageBuilder();
-        final UpdatesBuilder updsBuilder = new UpdatesBuilder();
-        updsBuilder.setLsp(new LspBuilder().setPlspId(new PlspId(1L)).build());
-        final PathBuilder pathBuilder = new PathBuilder();
-        pathBuilder.setEro(
-                new EroBuilder()
-                    .setSubobject(Lists.newArrayList(new SubobjectBuilder().setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(
-                        new IpPrefixBuilder().setIpPrefix(new IpPrefix(new Ipv4Prefix("127.0.0.2/32"))).build()).build()).build())).build());
-        updsBuilder.setPath(pathBuilder.build());
-        updsBuilder.setSrp(new SrpBuilder().setOperationId(new SrpIdNumber(0L)).build());
-        msgBuilder.setUpdates(Lists.newArrayList(updsBuilder.build()));
-        return new PcupdBuilder().setPcupdMessage(msgBuilder.build()).build();
-    }
-}
index 3598605fdaa2d9d0c03684ddf3bfcddd5e4f7661..fa2a20f6ef7f58a9e4de99362edd0f1a538b85b3 100644 (file)
@@ -324,7 +324,11 @@ public enum PCEPErrors {
      * No StartTLS message before StartTLSWait timer expired
      * TODO: error code to be assigned by IANA
      */
-    STARTTLS_TIMER_EXP(30, 5);
+    STARTTLS_TIMER_EXP(30, 5),
+    /**
+     * LSP is not PCE-initiated
+     */
+    LSP_NOT_PCE_INITIATED(19, 9);
 
     private PCEPErrorIdentifier errorId;
     private static final Map<PCEPErrorIdentifier, PCEPErrors> VALUE_MAP;