Bug-1516: Introduce PCC mock. 05/10005/5
authorMilos Fabian <milfabia@cisco.com>
Fri, 15 Aug 2014 11:42:50 +0000 (13:42 +0200)
committerMilos Fabian <milfabia@cisco.com>
Mon, 18 Aug 2014 08:58:27 +0000 (10:58 +0200)
-dummy PCC responder
-contains executable jar
-input parameters:
--address <inet address> (the first PCC's address, mandatory argument)
--pcc <count> (a number of PCC mocks to connect ODL's PCE, 1 by default)
--lsp <count> (a number of LSPs per PCC, 1 by default)
--pcerr (optional flag - PCC returns random PCError Msg as a response to PCUpd)
-PCC mock can establish connection with PCE, periodically (30s) sends keep-alive msg
-creates dummy LSPs and sync with PCE, responses to PCE requests (PCUpd Msg) - with PCRpt Msg

Change-Id: I5f7eff957375be53f48bc169cf85a22a19ff60b1
Signed-off-by: Milos Fabian <milfabia@cisco.com>
pcep/pcc-mock/.project [new file with mode: 0644]
pcep/pcc-mock/pom.xml [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/Main.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/MsgBuilderUtil.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCActivator.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCMock.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCSrpObjectParser.java [new file with mode: 0644]
pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListener.java [new file with mode: 0644]
pcep/pcc-mock/src/test/java/org/opendaylight/protocol/pcep/pcc/mock/SimpleSessionListenerTest.java [new file with mode: 0644]
pcep/pom.xml

diff --git a/pcep/pcc-mock/.project b/pcep/pcc-mock/.project
new file mode 100644 (file)
index 0000000..c3e5dfc
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>pcep-pcc-mock</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/pcep/pcc-mock/pom.xml b/pcep/pcc-mock/pom.xml
new file mode 100644 (file)
index 0000000..74ad428
--- /dev/null
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.bgpcep</groupId>
+    <artifactId>pcep-parent</artifactId>
+    <version>0.3.1-SNAPSHOT</version>
+  </parent>
+  <artifactId>pcep-pcc-mock</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pcep-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pcep-impl</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>concepts</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>protocol-framework</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pcep-ietf-stateful07</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>pcep-ietf-stateful02</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-transport</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+
+    <!-- Testing dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifest>
+              <mainClass>org.opendaylight.protocol.pcep.pcc.mock.Main</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>${maven.shade.version}</version>
+        <configuration>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <transformers>
+                <transformer
+                  implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  <mainClass>org.opendaylight.protocol.pcep.pcc.mock.Main</mainClass>
+                </transformer>
+              </transformers>
+              <shadedArtifactAttached>true</shadedArtifactAttached>
+              <shadedClassifierName>executable</shadedClassifierName>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/Main.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/Main.java
new file mode 100644 (file)
index 0000000..a5889c1
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.base.Preconditions;
+import com.google.common.net.InetAddresses;
+import io.netty.util.concurrent.DefaultPromise;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.SessionListenerFactory;
+import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
+import org.opendaylight.protocol.pcep.PCEPSessionListener;
+import org.opendaylight.protocol.pcep.ietf.stateful07.StatefulActivator;
+import org.opendaylight.protocol.pcep.impl.DefaultPCEPSessionNegotiatorFactory;
+import org.opendaylight.protocol.pcep.impl.PCEPHandlerFactory;
+import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
+import org.opendaylight.protocol.pcep.spi.pojo.ServiceLoaderPCEPExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.open.object.OpenBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class Main {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Main.class);
+
+    private static final int DEFAULT_PORT = 4189;
+    private static final short DEFAULT_KEEP_ALIVE = 30;
+    private static final short DEFAULT_DEAD_TIMER = 120;
+    private static final int RECONNECT_STRATEGY_TIMEOUT = 2000;
+
+    public static void main(String[] args) throws InterruptedException, ExecutionException, UnknownHostException {
+
+        if (args.length < 2) {
+            LOG.info("Insufficient number of arguments {}.", args.length);
+            return;
+        }
+
+        InetAddress address = null;
+        int pccCount = 1;
+        int lsps = 1;
+        boolean pcError = false;
+
+        int argIdx = 0;
+        while (argIdx < args.length) {
+            if (args[argIdx].equals("--address")) {
+                address = InetAddress.getByName(args[argIdx + 1]);
+                argIdx++;
+            } else if (args[argIdx].equals("--pcc")) {
+                pccCount = Integer.valueOf(args[argIdx + 1]);
+                argIdx++;
+            } else if (args[argIdx].equals("--lsp")) {
+                lsps = Integer.valueOf(args[argIdx + 1]);
+                argIdx++;
+            } else if (args[argIdx].equals("--pcerr")) {
+                pcError = true;
+                argIdx++;
+            } else {
+                LOG.warn("WARNING: Unrecognized argument: {}", args[argIdx]);
+            }
+            argIdx++;
+        }
+        Preconditions.checkState(address != null, "Missing mandatory address parameter.");
+        createPCCs(lsps, pcError, pccCount, address);
+    }
+
+    public static void createPCCs(final int lspsPerPcc, final boolean pcerr, final int pccCount,
+            final InetAddress address) throws InterruptedException, ExecutionException {
+        final SessionNegotiatorFactory<Message, PCEPSessionImpl, PCEPSessionListener> snf = new DefaultPCEPSessionNegotiatorFactory(
+                new OpenBuilder().setKeepalive(DEFAULT_KEEP_ALIVE).setDeadTimer(DEFAULT_DEAD_TIMER).setSessionId((short) 0).build(), 0);
+
+        final StatefulActivator activator07 = new StatefulActivator();
+        final PCCActivator activator = new PCCActivator();
+        activator07.start(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance());
+        activator.start(ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance());
+        final PCCMock<Message, PCEPSessionImpl, PCEPSessionListener> pcc = new PCCMock<>(snf, new PCEPHandlerFactory(
+                ServiceLoaderPCEPExtensionProviderContext.getSingletonInstance().getMessageHandlerRegistry()),
+                new DefaultPromise<PCEPSessionImpl>(GlobalEventExecutor.INSTANCE));
+
+        InetAddress inetAddress = address;
+        int i = 0;
+        while (i < pccCount) {
+            final int pccNumber = i + 1;
+            final InetAddress pccAddress = inetAddress;
+            pcc.createClient(new InetSocketAddress(pccAddress, DEFAULT_PORT),
+                    new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, RECONNECT_STRATEGY_TIMEOUT),
+                    new SessionListenerFactory<PCEPSessionListener>() {
+
+                        @Override
+                        public PCEPSessionListener getSessionListener() {
+                            return new SimpleSessionListener(lspsPerPcc, pcerr, pccNumber, pccAddress);
+                        }
+                    }).get();
+            i++;
+            inetAddress = InetAddresses.increment(inetAddress);
+        }
+    }
+
+}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/MsgBuilderUtil.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/MsgBuilderUtil.java
new file mode 100644 (file)
index 0000000..6da21e5
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.List;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+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.PcrptBuilder;
+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.identifiers.tlv.LspIdentifiersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.lsp.identifiers.address.family.Ipv4CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.lsp.identifiers.address.family.ipv4._case.Ipv4Builder;
+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.lsp.object.lsp.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcerr.pcerr.message.error.type.StatefulCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcerr.pcerr.message.error.type.stateful._case.StatefulBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcerr.pcerr.message.error.type.stateful._case.stateful.SrpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.PcrptMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.ReportsBuilder;
+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.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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.ErrorsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.Ipv4ExtendedTunnelId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.LspId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.TunnelId;
+
+public final class MsgBuilderUtil {
+
+    private MsgBuilderUtil() {
+    }
+
+    public static Pcrpt createPcRtpMessage(final Lsp lsp, final Optional<Srp> srp, final Path path) {
+        final PcrptBuilder rptBuilder = new PcrptBuilder();
+        final PcrptMessageBuilder msgBuilder = new PcrptMessageBuilder();
+        final ReportsBuilder reportBuilder = new ReportsBuilder();
+        reportBuilder.setLsp(lsp);
+        reportBuilder.setSrp(srp.orNull());
+        reportBuilder.setPath(path);
+        msgBuilder.setReports(Lists.newArrayList(reportBuilder.build()));
+        rptBuilder.setPcrptMessage(msgBuilder.build());
+        return rptBuilder.build();
+    }
+
+    public static Lsp createLsp(final long plspId, final boolean sync, final Optional<Tlvs> tlvs) {
+        final LspBuilder lspBuilder = new LspBuilder();
+        lspBuilder.setAdministrative(true);
+        lspBuilder.setDelegate(true);
+        lspBuilder.setIgnore(false);
+        lspBuilder.setOperational(OperationalStatus.Up);
+        lspBuilder.setPlspId(new PlspId(plspId));
+        lspBuilder.setProcessingRule(false);
+        lspBuilder.setRemove(false);
+        lspBuilder.setSync(sync);
+        lspBuilder.setTlvs(tlvs.orNull());
+        return lspBuilder.build();
+    }
+
+    public static Path createPath(final List<Subobject> subobjects) {
+        final PathBuilder pathBuilder = new PathBuilder();
+        pathBuilder.setEro(new EroBuilder().setSubobject(subobjects).build());
+        return pathBuilder.build();
+    }
+
+    public static Srp createSrp(final long srpId) {
+        final SrpBuilder srpBuilder = new SrpBuilder();
+        srpBuilder.setProcessingRule(false);
+        srpBuilder.setIgnore(false);
+        srpBuilder.setOperationId(new SrpIdNumber(srpId));
+        return srpBuilder.build();
+    }
+
+    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 PathBuilder pathBuilder = new PathBuilder();
+        pathBuilder.setBandwidth(path.getBandwidth());
+        pathBuilder.setClassType(path.getClassType());
+        pathBuilder.setEro(path.getEro());
+        pathBuilder.setIro(path.getIro());
+        pathBuilder.setLspa(path.getLspa());
+        pathBuilder.setMetrics(path.getMetrics());
+        pathBuilder.setOf(path.getOf());
+        pathBuilder.setRro(path.getRro());
+        pathBuilder.setXro(path.getXro());
+        return pathBuilder.build();
+    }
+
+    public static Tlvs createLspTlvs(final long lspId, final boolean symbolicPathName, InetAddress tunnelEndpoint,
+            InetAddress tunnelSender, InetAddress extendedTunnelAddress) {
+        final TlvsBuilder tlvs = new TlvsBuilder().setLspIdentifiers(new LspIdentifiersBuilder()
+                .setLspId(new LspId(lspId))
+                .setAddressFamily(
+                        new Ipv4CaseBuilder().setIpv4(
+                                new Ipv4Builder()
+                                        .setIpv4TunnelEndpointAddress(new Ipv4Address(tunnelEndpoint.getHostAddress()))
+                                        .setIpv4TunnelSenderAddress(new Ipv4Address(tunnelSender.getHostAddress()))
+                                        .setIpv4ExtendedTunnelId(
+                                                new Ipv4ExtendedTunnelId(extendedTunnelAddress.getHostAddress()))
+                                        .build()).build()).setTunnelId(new TunnelId((int) lspId)).build());
+        if (symbolicPathName) {
+            tlvs.setSymbolicPathName(new SymbolicPathNameBuilder().setPathName(
+                    new SymbolicPathName(Charsets.UTF_8.encode("tunnel" + lspId).array())).build());
+        }
+        return tlvs.build();
+    }
+
+    public static Message createErrorMsg(final PCEPErrors e, final long srpId) {
+        final PcerrMessageBuilder msgBuilder = new PcerrMessageBuilder();
+        return new PcerrBuilder().setPcerrMessage(
+                msgBuilder
+                        .setErrorType(
+                                new StatefulCaseBuilder().setStateful(
+                                        new StatefulBuilder().setSrps(
+                                                Lists.newArrayList(new SrpsBuilder().setSrp(
+                                                        new SrpBuilder().setProcessingRule(false).setIgnore(false)
+                                                                .setOperationId(new SrpIdNumber(srpId)).build())
+                                                        .build())).build()).build())
+                        .setErrors(
+                                Arrays.asList(new ErrorsBuilder().setErrorObject(
+                                        new ErrorObjectBuilder().setType(e.getErrorType()).setValue(e.getErrorValue())
+                                                .build()).build())).build()).build();
+    }
+
+}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCActivator.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCActivator.java
new file mode 100644 (file)
index 0000000..aa4836c
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+import org.opendaylight.protocol.pcep.ietf.stateful07.Stateful07SrpObjectParser;
+import org.opendaylight.protocol.pcep.spi.PCEPExtensionProviderContext;
+import org.opendaylight.protocol.pcep.spi.pojo.AbstractPCEPExtensionProviderActivator;
+
+public class PCCActivator extends AbstractPCEPExtensionProviderActivator {
+
+    @Override
+    protected List<AutoCloseable> startImpl(PCEPExtensionProviderContext context) {
+        final List<AutoCloseable> regs = new ArrayList<>();
+        regs.add(context.registerObjectParser(Stateful07SrpObjectParser.CLASS, Stateful07SrpObjectParser.TYPE,
+                new PCCSrpObjectParser(context.getTlvHandlerRegistry(), context.getVendorInformationTlvRegistry())));
+        return regs;
+    }
+}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCMock.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCMock.java
new file mode 100644 (file)
index 0000000..392bdd7
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.base.Preconditions;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.util.concurrent.DefaultPromise;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import io.netty.util.concurrent.Promise;
+import java.net.InetSocketAddress;
+import org.opendaylight.protocol.framework.AbstractDispatcher;
+import org.opendaylight.protocol.framework.ProtocolSession;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.SessionListener;
+import org.opendaylight.protocol.framework.SessionListenerFactory;
+import org.opendaylight.protocol.framework.SessionNegotiatorFactory;
+import org.opendaylight.protocol.pcep.impl.PCEPHandlerFactory;
+import org.opendaylight.protocol.pcep.impl.PCEPSessionImpl;
+
+public class PCCMock<M, S extends ProtocolSession<M>, L extends SessionListener<M, ?, ?>> extends
+        AbstractDispatcher<S, L> {
+
+    private final SessionNegotiatorFactory<M, S, L> negotiatorFactory;
+    private final PCEPHandlerFactory factory;
+
+    public PCCMock(final SessionNegotiatorFactory<M, S, L> negotiatorFactory, final PCEPHandlerFactory factory,
+            final DefaultPromise<PCEPSessionImpl> defaultPromise) {
+        super(GlobalEventExecutor.INSTANCE, new NioEventLoopGroup(), new NioEventLoopGroup());
+        this.negotiatorFactory = Preconditions.checkNotNull(negotiatorFactory);
+        this.factory = Preconditions.checkNotNull(factory);
+    }
+
+    public Future<S> createClient(final InetSocketAddress address, final ReconnectStrategy strategy,
+            final SessionListenerFactory<L> listenerFactory) {
+        return super.createClient(address, strategy, new PipelineInitializer<S>() {
+            @Override
+            public void initializeChannel(final SocketChannel ch, final Promise<S> promise) {
+                ch.pipeline().addLast(PCCMock.this.factory.getDecoders());
+                ch.pipeline().addLast("negotiator",
+                        PCCMock.this.negotiatorFactory.getSessionNegotiator(listenerFactory, ch, promise));
+                ch.pipeline().addLast(PCCMock.this.factory.getEncoders());
+            }
+        });
+    }
+}
diff --git a/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCSrpObjectParser.java b/pcep/pcc-mock/src/main/java/org/opendaylight/protocol/pcep/pcc/mock/PCCSrpObjectParser.java
new file mode 100644 (file)
index 0000000..a77e36b
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.pcep.ietf.stateful07.Stateful07SrpObjectParser;
+import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
+import org.opendaylight.protocol.pcep.spi.TlvRegistry;
+import org.opendaylight.protocol.pcep.spi.VendorInformationTlvRegistry;
+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.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.srp.object.srp.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.ObjectHeader;
+
+public class PCCSrpObjectParser extends Stateful07SrpObjectParser {
+
+    protected PCCSrpObjectParser(TlvRegistry tlvReg, VendorInformationTlvRegistry viTlvReg) {
+        super(tlvReg, viTlvReg);
+    }
+
+    @Override
+    public Srp parseObject(ObjectHeader header, ByteBuf bytes) throws PCEPDeserializerException {
+        Preconditions.checkArgument(bytes != null && bytes.isReadable(),
+                "Array of bytes is mandatory. Can't be null or empty.");
+        if (bytes.readableBytes() < MIN_SIZE) {
+            throw new PCEPDeserializerException("Wrong length of array of bytes. Passed: " + bytes.readableBytes()
+                    + "; Expected: >=" + MIN_SIZE + ".");
+        }
+        final SrpBuilder builder = new SrpBuilder();
+        builder.setIgnore(header.isIgnore());
+        builder.setProcessingRule(header.isProcessingRule());
+        bytes.readerIndex(bytes.readerIndex() + FLAGS_SIZE);
+        builder.setOperationId(new SrpIdNumber(bytes.readUnsignedInt()));
+        final TlvsBuilder tlvsBuilder = new TlvsBuilder();
+        parseTlvs(tlvsBuilder, bytes.slice());
+        builder.setTlvs(tlvsBuilder.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
new file mode 100644 (file)
index 0000000..555411a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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.updToRptPath;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.List;
+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.spi.PCEPErrors;
+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.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.explicit.route.object.ero.Subobject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev130820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SimpleSessionListener implements PCEPSessionListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SimpleSessionListener.class);
+
+    private final int pccNumber;
+    private final int lspsCount;
+    private final boolean pcError;
+    private final InetAddress address;
+
+    public SimpleSessionListener(final int lspsCount, final boolean pcError, final int pccNumber,
+            final InetAddress address) {
+        Preconditions.checkArgument(lspsCount > 0);
+        this.lspsCount = lspsCount;
+        this.pcError = pcError;
+        this.pccNumber = pccNumber;
+        this.address = address;
+    }
+
+    @Override
+    public void onMessage(final PCEPSession session, final Message message) {
+        LOG.debug("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 (pcError) {
+                session.sendMessage(MsgBuilderUtil.createErrorMsg(getRandomError(), srpId));
+            } else {
+                final Tlvs tlvs = createLspTlvs(updates.getLsp().getPlspId().getValue(), false,
+                        getDestinationAddress(updates.getPath().getEro().getSubobject()), this.address, this.address);
+                final Pcrpt pcRpt = createPcRtpMessage(new LspBuilder(updates.getLsp()).setTlvs(tlvs).build(),
+                        Optional.fromNullable(createSrp(srpId)), updToRptPath(updates.getPath()));
+                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 * this.pccNumber, true, this.address, this.address,
+                    this.address);
+            session.sendMessage(createPcRtpMessage(
+                    createLsp(i * this.pccNumber, true, Optional.<Tlvs> fromNullable(tlvs)), Optional.<Srp> absent(),
+                    createPath(Collections.<Subobject> emptyList())));
+        }
+        // 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.debug("Session down with cause : {} or exception: {}", e.getCause(), e, e);
+        session.close();
+    }
+
+    @Override
+    public void onSessionTerminated(final PCEPSession session, final PCEPTerminationReason cause) {
+        LOG.debug("Session terminated. Cause : {}", cause.toString());
+    }
+
+    private InetAddress getDestinationAddress(final List<Subobject> subobjects) {
+        if (subobjects != null && !subobjects.isEmpty()) {
+            final String prefix = ((IpPrefixCase) subobjects.get(subobjects.size() - 1).getSubobjectType())
+                    .getIpPrefix().getIpPrefix().getIpv4Prefix().getValue();
+            try {
+                return InetAddress.getByName(prefix.substring(0, prefix.indexOf('/')));
+            } catch (UnknownHostException e) {
+                LOG.debug("Unknown host name {}", prefix);
+            }
+        }
+        return this.address;
+    }
+
+    private Random rnd = new Random();
+
+    private PCEPErrors getRandomError() {
+        return PCEPErrors.values()[rnd.nextInt(PCEPErrors.values().length)];
+    }
+
+}
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
new file mode 100644 (file)
index 0000000..a94f854
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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 junit.framework.Assert.assertEquals;
+import static junit.framework.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.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;
+
+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, 1,
+                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);
+    }
+
+    @Test
+    public void testSessionListenerPcErr() throws UnknownHostException {
+        final SimpleSessionListener sessionListser = new SimpleSessionListener(1, true, 1,
+                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().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 d4be672ffae946f059c639cde7a691257fa7e43c..b9545239b354550fcb92ba707484ff60a2d98712 100644 (file)
@@ -48,6 +48,7 @@
 
         <module>controller-config</module>
         <module>segment-routing</module>
+        <module>pcc-mock</module>
     </modules>
 
     <dependencyManagement>