[ONOS] Compute path with Explicit path objects

Change-Id: Ib487688e15db7056283feef7720f610b2f59ad84
diff --git a/apps/pce/app/pom.xml b/apps/pce/app/pom.xml
index abd61b6..f210de9 100644
--- a/apps/pce/app/pom.xml
+++ b/apps/pce/app/pom.xml
@@ -105,5 +105,10 @@
             <groupId>org.onosproject</groupId>
             <artifactId>onos-app-pcep-api</artifactId>
         </dependency>
+       <dependency>
+           <groupId>org.easymock</groupId>
+           <artifactId>easymock</artifactId>
+           <scope>test</scope>
+       </dependency>
     </dependencies>
 </project>
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java
index 09a396e..8994f47 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceQueryPathCommand.java
@@ -24,10 +24,13 @@
 import org.onosproject.incubator.net.tunnel.Tunnel;
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.AnnotationKeys;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.api.PceService;
 
 import org.slf4j.Logger;
 
+import java.util.List;
+
 /**
  * Supports quering PCE path.
  */
@@ -72,17 +75,28 @@
      * @param tunnel pce tunnel
      */
     void display(Tunnel tunnel) {
-        print("\npath-id            : %s \n" +
-                "source             : %s \n" +
-                "destination        : %s \n" +
-                "path-type          : %s \n" +
-                "symbolic-path-name : %s \n" +
+        List<ExplicitPathInfo> explicitPathInfoList = AbstractShellCommand.get(PceService.class)
+                .explicitPathInfoList(tunnel.tunnelName().value());
+
+        print("\npath-id                  : %s \n" +
+                "source                   : %s \n" +
+                "destination              : %s \n" +
+                "path-type                : %s \n" +
+                "symbolic-path-name       : %s \n" +
                 "constraints:            \n" +
-                "   cost            : %s \n" +
-                "   bandwidth       : %s",
+                "   cost                  : %s \n" +
+                "   bandwidth             : %s",
                 tunnel.tunnelId().id(), tunnel.path().src().deviceId().toString(),
                 tunnel.path().dst().deviceId().toString(),
                 tunnel.type().name(), tunnel.tunnelName(), tunnel.annotations().value(COST_TYPE),
                 tunnel.annotations().value(AnnotationKeys.BANDWIDTH));
+        if (explicitPathInfoList != null) {
+            for (ExplicitPathInfo e : explicitPathInfoList) {
+                print("explicitPathObjects      : \n" +
+                      "    type                 : %s \n" +
+                      "    value                : %s ",
+                      String.valueOf(e.type().type()), e.value().toString());
+            }
+        }
     }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java
index 7bd7970..6139004 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/cli/PceSetupPathCommand.java
@@ -15,27 +15,35 @@
  */
 package org.onosproject.pce.cli;
 
+import static org.onosproject.net.Link.State.ACTIVE;
+import static org.onosproject.net.Link.Type.DIRECT;
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.LinkedList;
 
+import com.google.common.collect.Lists;
+
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
-
 import org.onlab.util.DataRateUnit;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.incubator.net.tunnel.Tunnel;
 import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.intent.constraint.BandwidthConstraint;
 import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.constraint.CostConstraint;
 import org.onosproject.pce.pceservice.LspType;
 import org.onosproject.pce.pceservice.api.PceService;
-
 import org.slf4j.Logger;
 
 /**
@@ -44,6 +52,16 @@
 @Command(scope = "onos", name = "pce-setup-path", description = "Supports creating pce path.")
 public class PceSetupPathCommand extends AbstractShellCommand {
     private final Logger log = getLogger(getClass());
+    public static final byte SUBTYPE_DEVICEID = 0;
+    public static final byte SUBTYPE_LINK = 1;
+    public static final byte SUBTYPE_INDEX = 1;
+    public static final byte TYPE_INDEX = 0;
+
+    public static final byte DEVICEID_INDEX = 2;
+    public static final byte SOURCE_DEVICEID_INDEX = 2;
+    public static final byte SOURCE_PORTNO_INDEX = 3;
+    public static final byte DESTINATION_DEVICEID_INDEX = 4;
+    public static final byte DESTINATION_PORTNO_INDEX = 5;
 
     @Argument(index = 0, name = "src", description = "source device.", required = true, multiValued = false)
     String src = null;
@@ -69,6 +87,19 @@
             + "Data rate unit is in BPS.", required = false, multiValued = false)
     double bandwidth = 0.0;
 
+    @Option(name = "-e", aliases = "--explicitPathObjects", description = "List of strict and loose hopes"
+            + " explicitPathInfo format : Type/SubType/Value(DeviceId or Link info)\n" +
+            " If Value is Device : Type/SubType/deviceId\n" +
+            " If Value is Link : Type/SubType/SourceDeviceId/SourcePortNo/DestinationDeviceId/DestinationPortNo" +
+            "Type 0 - strict, 1 - loose \n" + "SubType 0 - deviceId, 1 - link \n",
+            required = false, multiValued = true)
+    String[] explicitPathInfoStrings;
+
+    //explicitPathInfo format : Type/SubType/Value(DeviceId or Link info)
+    //If Value is Device : Type/SubType/deviceId
+    //If Value is Link : Type/SubType/SourceDeviceId/SourcePortNo/DestinationDeviceId/DestinationPortNo
+    List<ExplicitPathInfo> explicitPathInfo = Lists.newLinkedList();
+
     @Override
     protected void execute() {
         log.info("executing pce-setup-path");
@@ -114,7 +145,50 @@
         CostConstraint.Type costType = CostConstraint.Type.values()[cost - 1];
         listConstrnt.add(CostConstraint.of(costType));
 
-        if (!service.setupPath(srcDevice, dstDevice, name, listConstrnt, lspType)) {
+        if (explicitPathInfoStrings != null)  {
+            for (String str : explicitPathInfoStrings) {
+                String[] splitted = str.split("/");
+                DeviceId deviceId;
+                NetworkResource res = null;
+                PortNumber portNo;
+                int explicitPathType = Integer.parseInt(splitted[TYPE_INDEX]);
+                if ((explicitPathType < 0) || (explicitPathType > 1)) {
+                    error("Explicit path validation failed");
+                    return;
+                }
+
+                //subtype 0 = deviceId, 1 = link
+                //subtype is required to store either as deviceId or Link
+                if (splitted[DEVICEID_INDEX] != null && Integer.parseInt(splitted[SUBTYPE_INDEX]) == SUBTYPE_DEVICEID) {
+                    res = DeviceId.deviceId(splitted[DEVICEID_INDEX]);
+                } else if (Integer.parseInt(splitted[SUBTYPE_INDEX]) == SUBTYPE_LINK
+                        && splitted[SOURCE_DEVICEID_INDEX] != null
+                        && splitted[SOURCE_PORTNO_INDEX] != null
+                        && splitted[DESTINATION_DEVICEID_INDEX] != null
+                        && splitted[DESTINATION_PORTNO_INDEX] != null) {
+
+                    deviceId = DeviceId.deviceId(splitted[SOURCE_DEVICEID_INDEX]);
+                    portNo = PortNumber.portNumber(splitted[SOURCE_PORTNO_INDEX]);
+                    ConnectPoint cpSrc = new ConnectPoint(deviceId, portNo);
+                    deviceId = DeviceId.deviceId(splitted[DESTINATION_DEVICEID_INDEX]);
+                    portNo = PortNumber.portNumber(splitted[DESTINATION_PORTNO_INDEX]);
+                    ConnectPoint cpDst = new ConnectPoint(deviceId, portNo);
+                    res = DefaultLink.builder()
+                            .providerId(ProviderId.NONE)
+                            .src(cpSrc)
+                            .dst(cpDst)
+                            .type(DIRECT)
+                            .state(ACTIVE)
+                            .build();
+                } else {
+                    error("Explicit path validation failed");
+                    return;
+                }
+                ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.values()[explicitPathType], res);
+                explicitPathInfo.add(obj);
+            }
+        }
+        if (!service.setupPath(srcDevice, dstDevice, name, listConstrnt, lspType, explicitPathInfo)) {
             error("Path creation failed.");
         }
     }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/DefaultPcePath.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/DefaultPcePath.java
index 10acd0a..4c85fd7 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/DefaultPcePath.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/DefaultPcePath.java
@@ -18,8 +18,11 @@
 
 import static com.google.common.base.MoreObjects.toStringHelper;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.Objects;
 
+import org.onlab.rest.BaseResource;
 import org.onlab.util.DataRateUnit;
 import org.onosproject.incubator.net.tunnel.Tunnel;
 import org.onosproject.incubator.net.tunnel.TunnelId;
@@ -39,6 +42,7 @@
     private String name; // symbolic-path-name
     private Constraint costConstraint; // cost constraint
     private Constraint bandwidthConstraint; // bandwidth constraint
+    private Collection<ExplicitPathInfo> explicitPathInfo; //list of explicit path info
 
     /**
      * Initializes PCE path attributes.
@@ -50,10 +54,11 @@
      * @param name symbolic-path-name
      * @param costConstrnt cost constraint
      * @param bandwidthConstrnt bandwidth constraint
+     * @param explicitPathInfo list of explicit path info
      */
     private DefaultPcePath(TunnelId id, String src, String dst, LspType lspType,
-                           String name, Constraint costConstrnt, Constraint bandwidthConstrnt) {
-
+                           String name, Constraint costConstrnt, Constraint bandwidthConstrnt,
+                           Collection<ExplicitPathInfo> explicitPathInfo) {
         this.id = id;
         this.source = src;
         this.destination = dst;
@@ -61,6 +66,7 @@
         this.name = name;
         this.costConstraint = costConstrnt;
         this.bandwidthConstraint = bandwidthConstrnt;
+        this.explicitPathInfo = explicitPathInfo;
     }
 
     @Override
@@ -114,6 +120,11 @@
     }
 
     @Override
+    public Collection<ExplicitPathInfo> explicitPathInfo() {
+        return explicitPathInfo;
+    }
+
+    @Override
     public PcePath copy(PcePath path) {
         if (null != path.source()) {
             this.source = path.source();
@@ -138,7 +149,8 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(id, source, destination, lspType, name, costConstraint, bandwidthConstraint);
+        return Objects.hash(id, source, destination, lspType, name, costConstraint, bandwidthConstraint,
+                explicitPathInfo);
     }
 
     @Override
@@ -154,7 +166,8 @@
                     && Objects.equals(lspType, that.lspType)
                     && Objects.equals(name, that.name)
                     && Objects.equals(costConstraint, that.costConstraint)
-                    && Objects.equals(bandwidthConstraint, that.bandwidthConstraint);
+                    && Objects.equals(bandwidthConstraint, that.bandwidthConstraint)
+                    && Objects.equals(explicitPathInfo, that.explicitPathInfo);
         }
         return false;
     }
@@ -170,6 +183,7 @@
                 .add("name", name)
                 .add("costConstraint", costConstraint)
                 .add("bandwidthConstraint", bandwidthConstraint)
+                .add("explicitPathInfo", explicitPathInfo)
                 .toString();
     }
 
@@ -185,7 +199,7 @@
     /**
      * Builder class for pce path.
      */
-    public static final class Builder implements PcePath.Builder {
+    public static final class Builder extends BaseResource implements PcePath.Builder {
         private TunnelId id;
         private String source;
         private String destination;
@@ -193,6 +207,7 @@
         private String name;
         private Constraint costConstraint;
         private Constraint bandwidthConstraint;
+        private Collection<ExplicitPathInfo> explicitPathInfo;
 
         @Override
         public Builder id(String id) {
@@ -240,7 +255,13 @@
         }
 
         @Override
-        public Builder of(Tunnel tunnel) {
+        public Builder explicitPathInfo(Collection<ExplicitPathInfo> explicitPathInfo) {
+            this.explicitPathInfo = explicitPathInfo;
+            return this;
+        }
+
+        @Override
+        public Builder of(Tunnel tunnel, List<ExplicitPathInfo> explicitPathInfoList) {
             this.id = TunnelId.valueOf(tunnel.tunnelId().id());
             this.source = tunnel.path().src().deviceId().toString();
             this.destination = tunnel.path().dst().deviceId().toString();
@@ -264,13 +285,18 @@
                                                                   DataRateUnit.valueOf("BPS"));
             }
 
+            // Explicit Path
+            if (explicitPathInfoList != null) {
+                this.explicitPathInfo = explicitPathInfoList;
+            }
+
             return this;
         }
 
         @Override
         public PcePath build() {
             return new DefaultPcePath(id, source, destination, lspType, name,
-                                      costConstraint, bandwidthConstraint);
+                                      costConstraint, bandwidthConstraint, explicitPathInfo);
         }
     }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/ExplicitPathInfo.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/ExplicitPathInfo.java
new file mode 100644
index 0000000..52ef270
--- /dev/null
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/ExplicitPathInfo.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.pce.pceservice;
+
+import org.onosproject.net.NetworkResource;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Objects;
+
+/**
+ * Representation of explicit path info consists of contraints (strict / loose) to compute path.
+ */
+@Beta
+public final class ExplicitPathInfo {
+
+    private final Type type;
+
+    //Can be Link or DeviceId
+    private final NetworkResource value;
+
+    public enum Type {
+        /**
+         * Signifies that path includes strict node or link.
+         */
+        STRICT(0),
+
+        /**
+         * Signifies that path includes loose node or link.
+         */
+        LOOSE(1);
+
+        int value;
+
+        /**
+         * Assign val with the value as the type.
+         *
+         * @param val type
+         */
+        Type(int val) {
+            value = val;
+        }
+
+        /**
+         * Returns value of type.
+         *
+         * @return type
+         */
+        public byte type() {
+            return (byte) value;
+        }
+    }
+
+    /**
+     * Creates instance of explicit path object.
+     *
+     * @param type specifies whether strict or loose node/link
+     * @param value specifies deviceId or link
+     */
+    public ExplicitPathInfo(Type type, NetworkResource value) {
+        this.type = type;
+        this.value = value;
+    }
+
+    /**
+     * Returns explicit path type.
+     *
+     * @return explicit path type as strict/loose
+     */
+    public Type type() {
+        return type;
+    }
+
+    /**
+     * Returns deviceId or link.
+     *
+     * @return deviceId or link
+     */
+    public NetworkResource value() {
+        return value;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, value);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ExplicitPathInfo) {
+            final ExplicitPathInfo other = (ExplicitPathInfo) obj;
+            return Objects.equals(this.type, other.type)
+                    && Objects.equals(this.value, other.value);
+        }
+        return false;
+    }
+}
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
index a4c2aa6..ecc1d72 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
@@ -48,9 +48,11 @@
 import org.onosproject.net.config.NetworkConfigService;
 import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.DefaultAnnotations.Builder;
+import org.onosproject.net.DefaultPath;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Link;
+import org.onosproject.net.NetworkResource;
 import org.onosproject.net.Path;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.intent.Constraint;
@@ -86,6 +88,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 
 import static org.onosproject.incubator.net.tunnel.Tunnel.State.INIT;
 import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
@@ -223,17 +226,196 @@
         if (pathService == null) {
             return ImmutableSet.of();
         }
+
         Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
+        log.info("paths in computePath ::" + paths);
         if (!paths.isEmpty()) {
             return paths;
         }
         return ImmutableSet.of();
     }
 
-    //[TODO:] handle requests in queue
+    //Computes the partial path from partial computed path to specified dst.
+    private List<Path> computePartialPath(List<Path> computedPath, DeviceId src, DeviceId dst,
+                                    List<Constraint> constraints) {
+        int size = computedPath.size();
+        Path path = null;
+        DeviceId deviceId = size == 0 ? src :
+                computedPath.get(size - 1).dst().deviceId();
+
+        Set<Path> tempComputePath = computePath(deviceId, dst, constraints);
+
+        if (tempComputePath.isEmpty()) {
+            return null;
+        }
+
+        //if path validation fails return null
+        //Validate computed path to avoid loop in the path
+        for (Path p : tempComputePath) {
+            if (pathValidation(computedPath, p)) {
+                path = p;
+                break;
+            }
+        }
+        if (path == null) {
+            return null;
+        }
+
+        //Store the partial path result in a list
+        computedPath.add(path);
+        return computedPath;
+    }
+
+    private List<DeviceId> createListOfDeviceIds(List<? extends NetworkResource> list) {
+        List<Link> links = new LinkedList<>();
+        if (!list.isEmpty() && list.iterator().next() instanceof Path) {
+            for (Path path : (List<Path>) list) {
+                links.addAll(path.links());
+            }
+        } else if (!list.isEmpty() && list.iterator().next() instanceof Link) {
+            links.addAll((List<Link>) list);
+        }
+
+        //List of devices for new path computed
+        DeviceId source = null;
+        DeviceId destination = null;
+        List<DeviceId> devList = new LinkedList<>();
+
+        for (Link l : links) {
+            if (!devList.contains(l.src().deviceId())) {
+                devList.add(l.src().deviceId());
+            }
+            if (!devList.contains(l.dst().deviceId())) {
+                devList.add(l.dst().deviceId());
+            }
+        }
+
+        return devList;
+    }
+
+    //To dectect loops in the path i.e if the partial paths has intersection node avoid it.
+    private boolean pathValidation(List<Path> partialPath, Path path) {
+
+        //List of devices in new path computed
+        List<DeviceId> newPartialPathDevList;
+        newPartialPathDevList = createListOfDeviceIds(path.links());
+
+        //List of devices in partial computed path
+        List<DeviceId> partialComputedPathDevList;
+        partialComputedPathDevList = createListOfDeviceIds(partialPath);
+
+        for (DeviceId deviceId : newPartialPathDevList) {
+            for (DeviceId devId : partialComputedPathDevList) {
+                if (!newPartialPathDevList.get(0).equals(deviceId) &&
+                        !partialComputedPathDevList.get(partialComputedPathDevList.size() - 1).equals(devId)
+                        && deviceId.equals(devId)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    //Returns final computed explicit path (list of partial computed paths).
+    private List<Path> computeExplicitPath(List<ExplicitPathInfo> explicitPathInfo, DeviceId src, DeviceId dst,
+            List<Constraint> constraints) {
+        List<Path> finalComputedPath = new LinkedList<>();
+        for (ExplicitPathInfo info : explicitPathInfo) {
+            /*
+             * If explicit path object is LOOSE,
+             * 1) If specified as DeviceId (node) :
+             * If it is source , compute from source to destination (partial computation not required),
+             * otherwise compute from specified source to specified device
+             * 2) If specified as Link :
+             * Compute partial path from source to link's source , if path exists compute from link's source to dst
+             */
+            if (info.type().equals(ExplicitPathInfo.Type.LOOSE)) {
+                if (info.value() instanceof DeviceId) {
+                    // If deviceId is source no need to compute
+                    if (!(info.value()).equals(src)) {
+                        log.debug("computeExplicitPath :: Loose , device");
+                        finalComputedPath = computePartialPath(finalComputedPath, src, (DeviceId) info.value(),
+                                constraints);
+                        log.debug("finalComputedPath in computeExplicitPath ::" + finalComputedPath);
+                    }
+
+                } else if (info.value() instanceof Link) {
+                    if ((((Link) info.value()).src().deviceId().equals(src))
+                            || (!finalComputedPath.isEmpty()
+                            && finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId().equals(
+                                    ((Link) info.value()).src().deviceId()))) {
+
+                        finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).dst()
+                                .deviceId(), constraints);
+                    } else {
+
+                        finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).src()
+                                .deviceId(), constraints) != null ? computePartialPath(finalComputedPath, src,
+                                ((Link) info.value()).dst().deviceId(), constraints) : null;
+                    }
+                }
+                /*
+                 * If explicit path object is STRICT,
+                 * 1) If specified as DeviceId (node) :
+                 * Check whether partial computed path has reachable to strict specified node orde
+                 * strict node is the source, if no set path as null else do nothing
+                 * 2) If specified as Link :
+                 * Check whether partial computed path has reachable to strict link's src, if yes compute
+                 * path from strict link's src to link's dst (to include specified link)
+                 */
+            } else if (info.type().equals(ExplicitPathInfo.Type.STRICT)) {
+                if (info.value() instanceof DeviceId) {
+                    log.debug("computeExplicitPath :: Strict , device");
+                    if (!(!finalComputedPath.isEmpty() && finalComputedPath.get(finalComputedPath.size() - 1).dst()
+                            .deviceId().equals(info.value()))
+                            && !info.value().equals(src)) {
+                        finalComputedPath = null;
+                    }
+
+                } else if (info.value() instanceof Link) {
+                    log.info("computeExplicitPath :: Strict");
+                    finalComputedPath = ((Link) info.value()).src().deviceId().equals(src)
+                            || !finalComputedPath.isEmpty()
+                            && finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId()
+                                    .equals(((Link) info.value()).src().deviceId()) ? computePartialPath(
+                            finalComputedPath, src, ((Link) info.value()).dst().deviceId(), constraints) : null;
+
+                    //Log.info("computeExplicitPath :: (Link) info.value() " + (Link) info.value());
+                    //Log.info("computeExplicitPath :: finalComputedPath " + finalComputedPath);
+
+                    if (finalComputedPath != null && !finalComputedPath.get(finalComputedPath.size() - 1).links()
+                            .contains((Link) info.value())) {
+                        finalComputedPath = null;
+                    }
+                }
+            }
+            if (finalComputedPath == null) {
+                return null;
+            }
+        }
+        // Destination is not reached in Partial computed path then compute till destination
+        if (finalComputedPath.isEmpty() || !finalComputedPath.isEmpty()
+                && !finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId().equals(dst)) {
+
+            finalComputedPath = computePartialPath(finalComputedPath, src, dst, constraints);
+            if (finalComputedPath == null) {
+                return null;
+            }
+        }
+
+        return finalComputedPath;
+    }
+
     @Override
     public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
                              LspType lspType) {
+        return setupPath(src, dst, tunnelName, constraints, lspType, null);
+    }
+
+    //[TODO:] handle requests in queue
+    @Override
+    public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
+                             LspType lspType, List<ExplicitPathInfo> explicitPathInfo) {
         checkNotNull(src);
         checkNotNull(dst);
         checkNotNull(tunnelName);
@@ -245,7 +427,7 @@
 
         if (srcDevice == null || dstDevice == null) {
             // Device is not known.
-            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
             return false;
         }
 
@@ -255,7 +437,7 @@
 
         if (srcLsrId == null || dstLsrId == null) {
             // LSR id is not known.
-            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
             return false;
         }
 
@@ -263,7 +445,7 @@
         DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(srcLsrId), DeviceCapability.class);
         if (cfg == null) {
             log.debug("No session to ingress.");
-            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
             return false;
         }
 
@@ -299,12 +481,30 @@
             constraints = new LinkedList<>();
             constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
         }
+        Set<Path> computedPathSet = Sets.newLinkedHashSet();
 
-        Set<Path> computedPathSet = computePath(src, dst, constraints);
+        if (explicitPathInfo != null && !explicitPathInfo.isEmpty()) {
+            List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo, src, dst, constraints);
+            if (finalComputedPath == null) {
+                return false;
+            }
+
+            pceStore.tunnelNameExplicitPathInfoMap(tunnelName, explicitPathInfo);
+            List<Link> links = new LinkedList<>();
+            double totalCost = 0;
+            // Add all partial computed paths
+            for (Path path : finalComputedPath) {
+                links.addAll(path.links());
+                totalCost = totalCost + path.cost();
+            }
+            computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(), links, totalCost));
+        } else {
+            computedPathSet = computePath(src, dst, constraints);
+        }
 
         // NO-PATH
         if (computedPathSet.isEmpty()) {
-            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
             return false;
         }
 
@@ -339,14 +539,15 @@
         if (bwConstraintValue != 0) {
             consumerId = reserveBandwidth(computedPath, bwConstraintValue, null);
             if (consumerId == null) {
-                pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+                pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints,
+                        lspType, explicitPathInfo));
                 return false;
             }
         }
 
         TunnelId tunnelId = tunnelService.setupTunnel(appId, src, tunnel, computedPath);
         if (tunnelId == null) {
-            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
+            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
             if (consumerId != null) {
                 resourceService.release(consumerId);
             }
@@ -363,7 +564,7 @@
     @Override
     public boolean updatePath(TunnelId tunnelId, List<Constraint> constraints) {
         checkNotNull(tunnelId);
-        Set<Path> computedPathSet = null;
+        Set<Path> computedPathSet = Sets.newLinkedHashSet();
         Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
 
         if (tunnel == null) {
@@ -441,8 +642,30 @@
             constraints.add(costConstraint);
         }
 
-        computedPathSet = computePath(links.get(0).src().deviceId(), links.get(links.size() - 1).dst().deviceId(),
-                                      constraints);
+        List<ExplicitPathInfo> explicitPathInfo = pceStore
+                .getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value());
+        if (explicitPathInfo != null) {
+            List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo,
+                    tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
+                    constraints);
+
+            if (finalComputedPath == null) {
+                return false;
+            }
+
+            List<Link> totalLinks = new LinkedList<>();
+            double totalCost = 0;
+            //Add all partial computed paths
+            for (Path path : finalComputedPath) {
+                totalLinks.addAll(path.links());
+                totalCost = totalCost + path.cost();
+            }
+            computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(),
+                    totalLinks, totalCost));
+        } else {
+            computedPathSet = computePath(tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
+                    constraints);
+        }
 
         // NO-PATH
         if (computedPathSet.isEmpty()) {
@@ -636,7 +859,8 @@
                 // then PCInitiate (Remove)
                 pceStore.addFailedPathInfo(new PcePathInfo(tunnel.path().src().deviceId(), tunnel
                         .path().dst().deviceId(), tunnel.tunnelName().value(), constraintList,
-                        LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));
+                        LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)),
+                         pceStore.getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value())));
                 //Release that tunnel calling PCInitiate
                 releasePath(tunnel.tunnelId());
             }
@@ -832,7 +1056,9 @@
                     List<Link> links = tunnel.path().links();
                     pceStore.addFailedPathInfo(new PcePathInfo(links.get(0).src().deviceId(),
                                                                   links.get(links.size() - 1).dst().deviceId(),
-                                                                  tunnel.tunnelName().value(), constraints, lspType));
+                                                                  tunnel.tunnelName().value(), constraints, lspType,
+                                                                  pceStore.getTunnelNameExplicitPathInfoMap(tunnel
+                                                                          .tunnelName().value())));
                 }
 
                 break;
@@ -861,6 +1087,11 @@
         }
     }
 
+    @Override
+    public List<ExplicitPathInfo> explicitPathInfoList(String tunnelName) {
+        return pceStore.getTunnelNameExplicitPathInfoMap(tunnelName);
+    }
+
     //Computes path from tunnel store and also path failed to setup.
     private void callForOptimization() {
         //Recompute the LSPs which it was delegated [LSPs stored in PCE store (failed paths)]
@@ -880,7 +1111,7 @@
          */
         if (mastershipService.isLocalMaster(failedPathInfo.src())) {
             if (setupPath(failedPathInfo.src(), failedPathInfo.dst(), failedPathInfo.name(),
-                    failedPathInfo.constraints(), failedPathInfo.lspType())) {
+                    failedPathInfo.constraints(), failedPathInfo.lspType(), failedPathInfo.explicitPathInfo())) {
                 // If computation is success remove that path
                 pceStore.removeFailedPathInfo(failedPathInfo);
                 return true;
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcePath.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcePath.java
index 807b233..4886b97 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcePath.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PcePath.java
@@ -19,7 +19,9 @@
 import org.onosproject.incubator.net.tunnel.Tunnel;
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.intent.Constraint;
-import org.onosproject.pce.pceservice.DefaultPcePath.Builder;
+
+import java.util.Collection;
+import java.util.List;
 
 /**
  * Abstraction of an entity which provides functionalities of pce path.
@@ -97,6 +99,13 @@
     Constraint bandwidthConstraint();
 
     /**
+     * Returns the list of explicit path objects.
+     *
+     * @return list of explicit path objects
+     */
+    Collection<ExplicitPathInfo> explicitPathInfo();
+
+    /**
      * Copies only non-null or non-zero member variables.
      *
      * @param id path-id
@@ -169,9 +178,18 @@
          * Copies tunnel information to local.
          *
          * @param tunnel pcc tunnel
+         * @param explicitPathInfoList list of explicit path objects info
          * @return object of pce-path
          */
-        Builder of(Tunnel tunnel);
+        Builder of(Tunnel tunnel, List<ExplicitPathInfo> explicitPathInfoList);
+
+        /**
+         * Returns the builder object of ExplicitPathInfo.
+         *
+         * @param explicitPathInfo list of explicit path obj
+         * @return builder object of ExplicitPathInfo
+         */
+        Builder explicitPathInfo(Collection<ExplicitPathInfo> explicitPathInfo);
 
         /**
          * Builds object of pce path.
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/api/PceService.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/api/PceService.java
index f2d3622..fdfdb73 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/api/PceService.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/api/PceService.java
@@ -19,6 +19,7 @@
 
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.intent.Constraint;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.LspType;
 import org.onosproject.incubator.net.tunnel.Tunnel;
 import org.onosproject.incubator.net.tunnel.TunnelId;
@@ -42,6 +43,20 @@
     boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints, LspType lspType);
 
     /**
+     * Creates new path based on constraints and LSP type.
+     *
+     * @param src source device
+     * @param dst destination device
+     * @param tunnelName name of the tunnel
+     * @param constraints list of constraints to be applied on path
+     * @param lspType type of path to be setup
+     * @param explicitPathInfo list of explicit path info
+     * @return false on failure and true on successful path creation
+     */
+    boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints, LspType lspType,
+                      List<ExplicitPathInfo> explicitPathInfo);
+
+    /**
      * Updates an existing path.
      *
      * @param tunnelId tunnel identifier
@@ -72,4 +87,12 @@
      * @return tunnel if path exists, otherwise null
      */
     Tunnel queryPath(TunnelId tunnelId);
+
+    /**
+     * Returns list of explicit path info.
+     *
+     * @param tunnelName tunnel name
+     * @return list of explicit path info
+     */
+    List<ExplicitPathInfo> explicitPathInfoList(String tunnelName);
 }
\ No newline at end of file
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
index 9b2941f..001f74b 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/DistributedPceStore.java
@@ -19,6 +19,7 @@
 
 import com.google.common.collect.ImmutableSet;
 
+import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
@@ -33,6 +34,7 @@
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.intent.constraint.BandwidthConstraint;
 import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
 import org.onosproject.pce.pceservice.constraint.CostConstraint;
 import org.onosproject.pce.pceservice.TunnelConsumerId;
@@ -69,9 +71,14 @@
     // List of Failed path info
     private DistributedSet<PcePathInfo> failedPathSet;
 
+    // Maintains tunnel name mapped to explicit path info
+    private ConsistentMap<String, List<ExplicitPathInfo>> tunnelNameExplicitPathInfoMap;
+
     private static final Serializer SERIALIZER = Serializer
             .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
                     .register(PcePathInfo.class)
+                    .register(ExplicitPathInfo.class)
+                    .register(ExplicitPathInfo.Type.class)
                     .register(CostConstraint.class)
                     .register(CostConstraint.Type.class)
                     .register(BandwidthConstraint.class)
@@ -99,6 +106,16 @@
                 .build()
                 .asDistributedSet();
 
+        tunnelNameExplicitPathInfoMap = storageService.<String, List<ExplicitPathInfo>>consistentMapBuilder()
+                .withName("onos-pce-explicitpathinfo")
+                .withSerializer(Serializer.using(
+                        new KryoNamespace.Builder()
+                                .register(KryoNamespaces.API)
+                                .register(ExplicitPathInfo.class)
+                                .register(ExplicitPathInfo.Type.class)
+                                .build()))
+                .build();
+
         log.info("Started");
     }
 
@@ -181,4 +198,21 @@
         }
         return true;
     }
+
+    @Override
+    public boolean tunnelNameExplicitPathInfoMap(String tunnelName, List<ExplicitPathInfo> explicitPathInfo) {
+        checkNotNull(tunnelName);
+        checkNotNull(explicitPathInfo);
+        return tunnelNameExplicitPathInfoMap.put(tunnelName, explicitPathInfo) != null ? true : false;
+    }
+
+    @Override
+    public List<ExplicitPathInfo> getTunnelNameExplicitPathInfoMap(String tunnelName) {
+        checkNotNull(tunnelName);
+        if (tunnelNameExplicitPathInfoMap.get(tunnelName) != null) {
+            return tunnelNameExplicitPathInfoMap.get(tunnelName).value();
+        }
+        return null;
+    }
+
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/PcePathInfo.java b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/PcePathInfo.java
index 3b7b47e..6497e36 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/PcePathInfo.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/PcePathInfo.java
@@ -22,6 +22,7 @@
 
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.intent.Constraint;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.LspType;
 
 /**
@@ -40,6 +41,8 @@
 
     private LspType lspType; // lsp type
 
+    private List<ExplicitPathInfo> explicitPathInfo; //Explicit path info to compute explicit path
+
     /**
      * Initialization of member variables.
      *
@@ -48,17 +51,20 @@
      * @param name tunnel name
      * @param constraints list of constraints
      * @param lspType lsp type
+     * @param explicitPathInfo explicit path info
      */
     public PcePathInfo(DeviceId src,
                     DeviceId dst,
                     String name,
                     List<Constraint> constraints,
-                    LspType lspType) {
+                    LspType lspType,
+                    List<ExplicitPathInfo> explicitPathInfo) {
        this.src = src;
        this.dst = dst;
        this.name = name;
        this.constraints = constraints;
        this.lspType = lspType;
+       this.explicitPathInfo = explicitPathInfo;
     }
 
     /**
@@ -70,6 +76,7 @@
        this.name = null;
        this.constraints = null;
        this.lspType = null;
+       this.explicitPathInfo = null;
     }
 
     /**
@@ -162,9 +169,27 @@
         this.lspType = lspType;
     }
 
+    /**
+     * Returns list of explicit path info.
+     *
+     * @return list of explicit path info
+     */
+    public List<ExplicitPathInfo> explicitPathInfo() {
+        return explicitPathInfo;
+    }
+
+    /**
+     * Sets list of explicit path info.
+     *
+     * @param explicitPathInfo list of explicit path info
+     */
+    public void explicitPathInfo(List<ExplicitPathInfo> explicitPathInfo) {
+        this.explicitPathInfo = explicitPathInfo;
+    }
+
     @Override
     public int hashCode() {
-        return Objects.hash(src, dst, name, constraints, lspType);
+        return Objects.hash(src, dst, name, constraints, lspType, explicitPathInfo);
     }
 
     @Override
@@ -178,7 +203,8 @@
                     Objects.equals(this.dst, other.dst) &&
                     Objects.equals(this.name, other.name) &&
                     Objects.equals(this.constraints, other.constraints) &&
-                    Objects.equals(this.lspType, other.lspType);
+                    Objects.equals(this.lspType, other.lspType) &&
+                    Objects.equals(this.explicitPathInfo, other.explicitPathInfo);
         }
         return false;
     }
@@ -187,11 +213,12 @@
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .omitNullValues()
-                .add("Source", src.toString())
-                .add("Destination", dst.toString())
-                .add("Name", name.toString())
-                .add("Constraints", constraints.toString())
-                .add("LspType", lspType.toString())
+                .add("Source", src)
+                .add("Destination", dst)
+                .add("Name", name)
+                .add("Constraints", constraints)
+                .add("explicitPathInfo", explicitPathInfo)
+                .add("LspType", lspType)
                 .toString();
     }
 }
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java
index 3fdef15..0a7fa94 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pcestore/api/PceStore.java
@@ -15,8 +15,11 @@
  */
 package org.onosproject.pce.pcestore.api;
 
+import java.util.List;
+
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pcestore.PcePathInfo;
 
 import java.util.Map;
@@ -107,4 +110,21 @@
      * @return success or failure
      */
     boolean removeFailedPathInfo(PcePathInfo failedPathInfo);
+
+    /**
+     * Adds explicit path info to the map with corresponding tunnel name.
+     *
+     * @param tunnelName tunnel name as key
+     * @param explicitPathInfo list of explicit path objects
+     * @return whether it is added to map
+     */
+    boolean tunnelNameExplicitPathInfoMap(String tunnelName, List<ExplicitPathInfo> explicitPathInfo);
+
+    /**
+     * Gets explicit path info based on tunnel name.
+     *
+     * @param tunnelName tunnel name as key
+     * @return list of explicit path info
+     */
+    List<ExplicitPathInfo> getTunnelNameExplicitPathInfoMap(String tunnelName);
 }
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
index 455e36a..3a5eff4 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
@@ -16,21 +16,46 @@
 
 package org.onosproject.pce.pceservice;
 
+import com.google.common.collect.Lists;
+
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
+import static org.onosproject.pce.pceservice.PathComputationTest.D2;
+import static org.easymock.EasyMock.createMock;
 
 import com.google.common.testing.EqualsTester;
 
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.pce.pceservice.constraint.CostConstraint;
+import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.net.intent.constraint.BandwidthConstraint;
 
+import java.util.List;
+
 /**
  * Unit tests for DefaultPcePath class.
  */
 public class DefaultPcePathTest {
+    private PceStore pceStore = createMock(PceStore.class);
+
+    @Before
+    public void setup() {
+
+       ServiceDirectory testDirectory = new TestServiceDirectory()
+                   .add(PceStore.class, pceStore);
+       BaseResource.setServiceDirectory(testDirectory);
+    }
+
+    @After
+    public void tearDownTest() {
+    }
     /**
      * Checks the operation of equals() methods.
      */
@@ -43,7 +68,9 @@
         final String dst1 = "bee";
         final String type1 = "1";
         final String name1 = "pcc";
-
+        final List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+        explicitPathInfoList.add(obj);
         PcePath path1 = DefaultPcePath.builder()
                 .source(src1)
                 .destination(dst1)
@@ -51,6 +78,7 @@
                 .name(name1)
                 .costConstraint(cost1)
                 .bandwidthConstraint(bandwidth1)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
         path1.id(TunnelId.valueOf("1"));
 
@@ -62,6 +90,7 @@
                 .name(name1)
                 .costConstraint(cost1)
                 .bandwidthConstraint(bandwidth1)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
         samePath1.id(TunnelId.valueOf("1"));
 
@@ -80,6 +109,7 @@
                 .name(name2)
                 .costConstraint(cost2)
                 .bandwidthConstraint(bandwidth2)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
         path2.id(TunnelId.valueOf("2"));
 
@@ -97,7 +127,9 @@
         final String dst = "deccan";
         final String type = "2";
         final String name = "pcc4";
-
+        final List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+        explicitPathInfoList.add(obj);
         PcePath path = DefaultPcePath.builder()
                 .source(src)
                 .destination(dst)
@@ -105,6 +137,7 @@
                 .name(name)
                 .costConstraint(cost)
                 .bandwidthConstraint(bandwidth)
+                .explicitPathInfo(explicitPathInfoList)
                 .build();
 
         assertThat(path.source(), is(src));
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
index f78ce9d..54cc1a9 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
@@ -29,10 +29,12 @@
 import static org.onosproject.pce.pceservice.PathComputationTest.D2;
 import static org.onosproject.pce.pceservice.PathComputationTest.D3;
 import static org.onosproject.pce.pceservice.PathComputationTest.D4;
+import static org.onosproject.pce.pceservice.PathComputationTest.D5;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE1;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE2;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE3;
 import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE4;
+import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE5;
 import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
 import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
 import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
@@ -47,6 +49,8 @@
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
+import com.google.common.collect.Lists;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -135,9 +139,9 @@
     private static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
 
     private TopologyGraph graph = null;
-    private Device deviceD1, deviceD2, deviceD3, deviceD4;
+    private Device deviceD1, deviceD2, deviceD3, deviceD4, deviceD5;
     private Device pcepDeviceD1, pcepDeviceD2, pcepDeviceD3, pcepDeviceD4;
-    private Link link1, link2, link3, link4;
+    private Link link1, link2, link3, link4, link5, link6;
     protected static int flowsDownloaded;
     private TunnelListener tunnelListener;
     private TopologyListener listener;
@@ -179,12 +183,15 @@
         link2 = PathComputationTest.addLink(DEVICE2, 30, DEVICE4, 40, setCost, 20);
         link3 = PathComputationTest.addLink(DEVICE1, 80, DEVICE3, 70, setCost, 100);
         link4 = PathComputationTest.addLink(DEVICE3, 60, DEVICE4, 50, setCost, 80);
+        link5 = PathComputationTest.addLink(DEVICE2, 60, DEVICE5, 50, setCost, 80);
+        link6 = PathComputationTest.addLink(DEVICE4, 60, DEVICE5, 50, setCost, 80);
 
         Set<TopologyVertex> vertexes = new HashSet<TopologyVertex>();
         vertexes.add(D1);
         vertexes.add(D2);
         vertexes.add(D3);
         vertexes.add(D4);
+        vertexes.add(D5);
 
         this.vertexes = vertexes;
 
@@ -201,6 +208,12 @@
         TopologyEdge edge4 = new DefaultTopologyEdge(D3, D4, link4);
         edges.add(edge4);
 
+        TopologyEdge edge5 = new DefaultTopologyEdge(D2, D5, link5);
+        edges.add(edge5);
+
+        TopologyEdge edge6 = new DefaultTopologyEdge(D4, D5, link6);
+        edges.add(edge6);
+
         this.edges = edges;
 
         graph = new DefaultTopologyGraph(vertexes, edges);
@@ -209,6 +222,7 @@
         DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder();
         DefaultAnnotations.Builder builderDev3 = DefaultAnnotations.builder();
         DefaultAnnotations.Builder builderDev4 = DefaultAnnotations.builder();
+        DefaultAnnotations.Builder builderDev5 = DefaultAnnotations.builder();
 
         // Making L3 devices
         builderDev1.set(AnnotationKeys.TYPE, L3);
@@ -223,15 +237,20 @@
         builderDev4.set(AnnotationKeys.TYPE, L3);
         builderDev4.set(LSRID, "4.4.4.4");
 
+        builderDev5.set(AnnotationKeys.TYPE, L3);
+        builderDev5.set(LSRID, "5.5.5.5");
+
         deviceD1 = new MockDevice(D1.deviceId(), builderDev1.build());
         deviceD2 = new MockDevice(D2.deviceId(), builderDev2.build());
         deviceD3 = new MockDevice(D3.deviceId(), builderDev3.build());
         deviceD4 = new MockDevice(D4.deviceId(), builderDev4.build());
+        deviceD5 = new MockDevice(D5.deviceId(), builderDev5.build());
 
         deviceService.addDevice(deviceD1);
         deviceService.addDevice(deviceD2);
         deviceService.addDevice(deviceD3);
         deviceService.addDevice(deviceD4);
+        deviceService.addDevice(deviceD5);
 
         DeviceCapability device1Cap = netConfigRegistry.addConfig(DeviceId.deviceId("1.1.1.1"), DeviceCapability.class);
         device1Cap.setLabelStackCap(setLabelStackCap)
@@ -257,17 +276,25 @@
         .setSrCap(setSrCap)
         .apply();
 
+        DeviceCapability device5Cap = netConfigRegistry.addConfig(DeviceId.deviceId("5.5.5.5"), DeviceCapability.class);
+        device4Cap.setLabelStackCap(setLabelStackCap)
+                .setLocalLabelCap(setPceccCap)
+                .setSrCap(setSrCap)
+                .apply();
+
         if (bandwidth != 0) {
             List<Resource> resources = new LinkedList<>();
             resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link5.src().deviceId(), link5.src().port(), Bandwidth.class).resource(bandwidth));
 
             resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(bandwidth));
             resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link5.dst().deviceId(), link5.dst().port(), Bandwidth.class).resource(bandwidth));
 
             resourceService.allocate(IntentId.valueOf(bandwidth), resources);
         }
@@ -283,7 +310,7 @@
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -297,7 +324,7 @@
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -312,7 +339,7 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -327,7 +354,7 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -343,7 +370,7 @@
         constraints.add(costConstraint);
 
         boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(result, is(true));
     }
 
@@ -359,7 +386,7 @@
         constraints.add(costConstraint);
 
         boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(result, is(true));
     }
 
@@ -375,7 +402,7 @@
         constraints.add(costConstraint);
 
         boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(result, is(false));
     }
 
@@ -392,7 +419,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
+                WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -409,7 +437,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -423,7 +452,8 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
+             SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -440,7 +470,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -451,11 +482,144 @@
     public void setupPathTest13() {
         build4RouterTopo(false, false, false, false, 0);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
     /**
+     * Tests path setup with explicit path with loose node D2.
+     */
+   @Test
+    public void setupPathTest14() {
+        build4RouterTopo(false, false, false, false, 0);
+
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", null, WITH_SIGNALLING,
+                explicitPathInfoList);
+
+        Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link2);
+
+        assertThat(result, is(true));
+        assertThat(tunnel.path().links().equals(links), is(true));
+    }
+
+    /**
+     * Tests path setup with explicit path with loose node D3.
+     */
+   @Test
+   public void setupPathTest15() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+       List<Link> links = new LinkedList<>();
+       links.add(link3);
+       links.add(link4);
+       links.add(link6);
+
+       assertThat(result, is(true));
+       assertThat(tunnel.path().links().equals(links), is(true));
+   }
+
+    /**
+     * Tests path setup with explicit path with loose node D4 , D3 - path fails.
+     */
+   @Test
+   public void setupPathTest16() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D4.deviceId());
+       explicitPathInfoList.add(obj);
+       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       assertThat(result, is(false));
+   }
+
+    /**
+     * Tests path setup with explicit path with strict node D2 - without reacble to src - path fails.
+     */
+   @Test
+   public void setupPathTest17() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       assertThat(result, is(false));
+   }
+
+    /**
+     * Tests path setup with explicit path with loose node D2, strict D2.
+     */
+   @Test
+   public void setupPathTest18() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+       explicitPathInfoList.add(obj);
+       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+       List<Link> links = new LinkedList<>();
+       links.add(link1);
+       links.add(link5);
+
+       assertThat(result, is(true));
+       assertThat(tunnel.path().links().equals(links), is(true));
+   }
+
+    /**
+     * Tests path setup with explicit path with loose D1-D2, strict D2.
+     */
+   @Test
+   public void setupPathTest19() {
+       build4RouterTopo(false, false, false, false, 0);
+
+       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+       explicitPathInfoList.add(obj);
+       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+       explicitPathInfoList.add(obj);
+
+       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
+               explicitPathInfoList);
+
+       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+       List<Link> links = new LinkedList<>();
+       links.add(link1);
+       links.add(link5);
+
+       assertThat(result, is(true));
+       assertThat(tunnel.path().links().equals(links), is(true));
+   }
+
+    /**
      * Tests path update with increase in bandwidth.
      */
     @Test
@@ -469,7 +633,8 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         // Change constraint and update it.
@@ -507,7 +672,8 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(true));
 
         // Change constraint and update it.
@@ -538,7 +704,8 @@
         List<Constraint> constraints = new LinkedList<Constraint>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
@@ -554,6 +721,51 @@
     }
 
     /**
+     * Tests path update without cost/bandwidth constraints and with explicit path object.
+     */
+    @Test
+    public void updatePathTest4() {
+        build4RouterTopo(false, true, true, true, 100);
+
+        // Setup tunnel.
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
+        constraints.add(bwConstraint);
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        constraints.add(costConstraint);
+
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, explicitPathInfoList);
+        assertThat(result, is(true));
+
+        // Change constraint and update it.
+        constraints = new LinkedList<>();
+        bwConstraint = new BandwidthConstraint(Bandwidth.bps(50.0));
+        constraints.add(bwConstraint);
+        constraints.add(costConstraint);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+
+        Tunnel tunnel = tunnels.iterator().next();
+
+        // Stimulate the effect of LSP ids from protocol msg.
+        tunnelService.updateTunnelWithLspIds(tunnel, "123", "1", State.ACTIVE);
+
+        result = pceManager.updatePath(tunnel.tunnelId(), constraints);
+        assertThat(result, is(true));
+
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(2));
+    }
+
+    /**
      * Tests path release.
      */
     @Test
@@ -565,7 +777,13 @@
         constraints.add(bwConst);
         constraints.add(costConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, explicitPathInfoList);
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
         assertThat(tunnels.size(), is(1));
@@ -588,7 +806,7 @@
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
         assertThat(tunnels.size(), is(1));
@@ -602,6 +820,31 @@
     }
 
     /**
+     * Tests path release failure.
+     */
+    @Test
+    public void releasePathTest3() {
+        build4RouterTopo(false, false, false, false, 5);
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(TE_COST);
+        BandwidthConstraint bwConst = new BandwidthConstraint(Bandwidth.bps(3));
+        constraints.add(bwConst);
+        constraints.add(costConstraint);
+
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+
+        Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(1));
+        boolean result;
+        for (Tunnel tunnel : tunnels) {
+            result = pceManager.releasePath(tunnel.tunnelId());
+            assertThat(result, is(true));
+        }
+        tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
+        assertThat(tunnels.size(), is(0));
+    }
+
+    /**
      * Tests tunnel events added and removed.
      */
     @Test
@@ -614,7 +857,7 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(pceStore.getTunnelInfoCount(), is(1));
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
@@ -645,7 +888,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints,
+                WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(pceStore.getTunnelInfoCount(), is(1));
 
         TunnelEvent event;
@@ -685,7 +929,8 @@
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints,
+                WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
         assertThat(pceStore.getTunnelInfoCount(), is(1));
         assertThat(pceStore.getFailedPathInfoCount(), is(0));
 
@@ -723,7 +968,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
         assertThat(pceStore.getTunnelInfoCount(), is(1));
         assertThat(pceStore.getFailedPathInfoCount(), is(0));
@@ -765,7 +1011,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -803,7 +1050,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -846,7 +1094,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -884,7 +1133,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -932,7 +1182,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -973,7 +1224,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1014,7 +1266,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1060,7 +1313,8 @@
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1092,6 +1346,54 @@
         assertThat(pathService.paths().iterator().next().cost(), is((double) 180));
     }
 
+    /**
+     * Tests resilency when link2 availability is changed.
+     */
+    @Test
+    public void resilencyTest12() {
+        build4RouterTopo(true, false, false, false, 10);
+
+        List<Constraint> constraints = new LinkedList<Constraint>();
+        CostConstraint costConstraint = new CostConstraint(COST);
+        constraints.add(costConstraint);
+        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        constraints.add(localBwConst);
+
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
+
+        //Setup the path , tunnel created
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
+                constraints, WITH_SIGNALLING, explicitPathInfoList);
+        assertThat(result, is(true));
+        assertThat(pceStore.getTunnelInfoCount(), is(1));
+        assertThat(pceStore.getFailedPathInfoCount(), is(0));
+
+        List<Event> reasons = new LinkedList<>();
+        final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link2);
+        reasons.add(linkEvent);
+        final TopologyEvent event = new TopologyEvent(
+                TopologyEvent.Type.TOPOLOGY_CHANGED,
+                topology,
+                reasons);
+
+        //Change Topology : remove link2
+        Set<TopologyEdge> tempEdges = new HashSet<>();
+        tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
+        topologyService.changeInTopology(getGraph(null,  tempEdges));
+        listener.event(event);
+
+        List<Link> links = new LinkedList<>();
+        links.add(link3);
+        links.add(link4);
+
+        //Path fails - no alternate path
+        assertThat(pathService.paths().iterator().hasNext(), is(false));
+    }
+
     @After
     public void tearDown() {
         pceManager.deactivate();
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java
index e0916a8..c7e6ac9 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/DistributedPceStoreTest.java
@@ -120,7 +120,7 @@
        Constraint bandwidth1 = BandwidthConstraint.of(200, DataRateUnit.BPS);
        constraints1.add(bandwidth1);
 
-       failedPathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
+       failedPathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
 
        // Creates failedPathInfo2
        DeviceId src2 = DeviceId.deviceId("foo2");
@@ -131,7 +131,7 @@
        Constraint bandwidth2 = BandwidthConstraint.of(400, DataRateUnit.BPS);
        constraints2.add(bandwidth2);
 
-       failedPathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2);
+       failedPathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2, null);
 
        // Creates failedPathInfo3
        DeviceId src3 = DeviceId.deviceId("foo3");
@@ -142,7 +142,7 @@
        Constraint bandwidth3 = BandwidthConstraint.of(500, DataRateUnit.BPS);
        constraints3.add(bandwidth3);
 
-       failedPathInfo3 = new PcePathInfo(src3, dst3, name3, constraints3, lspType3);
+       failedPathInfo3 = new PcePathInfo(src3, dst3, name3, constraints3, lspType3, null);
 
        // Creates failedPathInfo4
        DeviceId src4 = DeviceId.deviceId("foo4");
@@ -153,7 +153,7 @@
        Constraint bandwidth4 = BandwidthConstraint.of(600, DataRateUnit.BPS);
        constraints4.add(bandwidth4);
 
-       failedPathInfo4 = new PcePathInfo(src4, dst4, name4, constraints4, lspType4);
+       failedPathInfo4 = new PcePathInfo(src4, dst4, name4, constraints4, lspType4, null);
     }
 
     @After
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java
index 09b60ab..a13c634 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pcestore/PcePathInfoTest.java
@@ -53,10 +53,10 @@
         Constraint bandwidth13 = BandwidthConstraint.of(300, DataRateUnit.BPS);
         constraints1.add(bandwidth13);
 
-        PcePathInfo pathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
+        PcePathInfo pathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
 
         // create same object as above object
-        PcePathInfo samePathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
+        PcePathInfo samePathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
 
         // Create different object.
         DeviceId src2 = DeviceId.deviceId("foo2");
@@ -69,7 +69,7 @@
         Constraint bandwidth22 = BandwidthConstraint.of(800, DataRateUnit.BPS);
         constraints2.add(bandwidth22);
 
-        PcePathInfo pathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2);
+        PcePathInfo pathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2, null);
 
         new EqualsTester().addEqualityGroup(pathInfo1, samePathInfo1)
                           .addEqualityGroup(pathInfo2)
@@ -93,7 +93,7 @@
         Constraint bandwidth3 = BandwidthConstraint.of(300, DataRateUnit.BPS);
         constraints.add(bandwidth3);
 
-        PcePathInfo pathInfo = new PcePathInfo(src, dst, name, constraints, lspType);
+        PcePathInfo pathInfo = new PcePathInfo(src, dst, name, constraints, lspType, null);
 
         assertThat(src, is(pathInfo.src()));
         assertThat(dst, is(pathInfo.dst()));
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java b/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
index 80f62a5..cba8801 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/util/PceStoreAdapter.java
@@ -22,13 +22,14 @@
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import org.onosproject.incubator.net.tunnel.TunnelId;
-import org.onosproject.net.DeviceId;
 import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pcestore.PcePathInfo;
 import org.onosproject.pce.pcestore.api.PceStore;
 
@@ -43,8 +44,8 @@
     // Set of Path info
     private Set<PcePathInfo> failedPathInfoSet = new HashSet<>();
 
-    // Locally maintain LSRID to device id mapping for better performance.
-    private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
+    // Locally maintain with tunnel name as key and corresponding list of explicit path object
+    private Map<String, List<ExplicitPathInfo>> tunnelNameExplicitPathInfoMap = new HashMap<>();
 
     @Override
     public boolean existsTunnelInfo(TunnelId tunnelId) {
@@ -108,4 +109,15 @@
         }
         return true;
     }
+
+    @Override
+    public boolean tunnelNameExplicitPathInfoMap(String tunnelName, List<ExplicitPathInfo> explicitPathInfo) {
+        tunnelNameExplicitPathInfoMap.put(tunnelName, explicitPathInfo);
+        return false;
+    }
+
+    @Override
+    public List<ExplicitPathInfo> getTunnelNameExplicitPathInfoMap(String tunnelName) {
+        return tunnelNameExplicitPathInfoMap.get(tunnelName);
+    }
 }
diff --git a/apps/pce/pcerest/BUCK b/apps/pce/pcerest/BUCK
new file mode 100644
index 0000000..cf442f6
--- /dev/null
+++ b/apps/pce/pcerest/BUCK
@@ -0,0 +1,25 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:javax.ws.rs-api',
+    '//utils/rest:onlab-rest',
+    '//apps/pce/app:onos-apps-pce-app',
+    '//core/store/serializers:onos-core-serializers',
+    '//core/api:onos-api',
+    '//incubator/api:onos-incubator-api',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_REST',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS
+)
+
+onos_app (
+    title = 'PCE Rest application',
+    category = 'Utility',
+    url = 'http://onosproject.org',
+    description = 'Tunnel Service between network devices via REST interface',
+)
diff --git a/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathCodec.java b/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathCodec.java
index 7692c7d..92b9e5e 100644
--- a/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathCodec.java
+++ b/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathCodec.java
@@ -16,9 +16,22 @@
 package org.onosproject.pcerest;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.Link.State.ACTIVE;
+import static org.onosproject.net.Link.Type.DIRECT;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 
 import org.onosproject.codec.CodecContext;
 import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.PcePath;
 import org.onosproject.pce.pceservice.DefaultPcePath;
 import org.onosproject.net.intent.constraint.BandwidthConstraint;
@@ -29,6 +42,11 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.JsonNode;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
 /**
  * PCE path json codec.
  */
@@ -42,7 +60,13 @@
     private static final String COST = "cost";
     private static final String BANDWIDTH = "bandwidth";
     private static final String PATH_ID = "pathId";
+    private static final String EXPLICIT_PATH_INFO = "explicitPathInfo";
     private static final String MISSING_MEMBER_MESSAGE = " member is required in pce-path";
+    public static final String JSON_NOT_NULL = "JsonNode can not be null";
+    public static final byte SOURCE_DEVICEID_INDEX = 0;
+    public static final byte SOURCE_PORTNO_INDEX = 1;
+    public static final byte DESTINATION_DEVICEID_INDEX = 2;
+    public static final byte DESTINATION_PORTNO_INDEX = 3;
 
     @Override
     public PcePath decode(ObjectNode json, CodecContext context) {
@@ -114,9 +138,87 @@
             }
         }
 
+        // Retrieve explicit path info
+        JsonNode explicitPathInfo = json.get(EXPLICIT_PATH_INFO);
+        if (explicitPathInfo != null) {
+            List<ExplicitPathInfo> explicitPathInfoList =
+                    ImmutableList.copyOf(jsonNodeToExplicitPathInfo(explicitPathInfo));
+            if (explicitPathInfoList != null) {
+                resultBuilder.explicitPathInfo(explicitPathInfoList);
+            }
+        }
+
         return resultBuilder.build();
     }
 
+    private ExplicitPathInfo createListOfExplicitPathObj(JsonNode node) {
+        int explicitPathType = Integer.parseInt(node.get("type").asText());
+        DeviceId deviceId;
+        PortNumber portNo;
+        NetworkResource res;
+        LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
+        if ((explicitPathType < 0) || (explicitPathType > 1)) {
+            return null;
+        }
+        ExplicitPathInfo.Type type = ExplicitPathInfo.Type.values()[explicitPathType];
+        String subType = node.get("subtype").asText();
+        if (Integer.parseInt(subType) == 0) {
+            res = DeviceId.deviceId(node.get("value").asText());
+        } else if (Integer.parseInt(subType) == 1) {
+
+            String[] splitted = node.get("value").asText().split("/");
+
+            if (splitted[SOURCE_DEVICEID_INDEX] != null
+                    && splitted[SOURCE_PORTNO_INDEX] != null
+                    && splitted[DESTINATION_DEVICEID_INDEX] != null
+                    && splitted[DESTINATION_PORTNO_INDEX] != null) {
+                return null;
+            }
+            deviceId = DeviceId.deviceId(splitted[SOURCE_DEVICEID_INDEX]);
+            portNo = PortNumber.portNumber(splitted[SOURCE_PORTNO_INDEX]);
+            ConnectPoint cpSrc = new ConnectPoint(deviceId, portNo);
+            deviceId = DeviceId.deviceId(splitted[DESTINATION_DEVICEID_INDEX]);
+            portNo = PortNumber.portNumber(splitted[DESTINATION_PORTNO_INDEX]);
+            ConnectPoint cpDst = new ConnectPoint(deviceId, portNo);
+            res = DefaultLink.builder()
+                    .providerId(ProviderId.NONE)
+                    .src(cpSrc)
+                    .dst(cpDst)
+                    .type(DIRECT)
+                    .state(ACTIVE)
+                    .build();
+        } else {
+            return null;
+        }
+
+        return new ExplicitPathInfo(type, res);
+    }
+
+    private Collection<ExplicitPathInfo> jsonNodeToExplicitPathInfo(JsonNode explicitPathInfo) {
+        checkNotNull(explicitPathInfo, JSON_NOT_NULL);
+
+        Integer i = 0;
+        NetworkResource res;
+        LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
+        if (explicitPathInfo.isArray()) {
+            for (JsonNode node : explicitPathInfo) {
+                ExplicitPathInfo obj = createListOfExplicitPathObj(node);
+                if (obj == null) {
+                    return null;
+                }
+                list.add(obj);
+            }
+        } else {
+            ExplicitPathInfo obj = createListOfExplicitPathObj(explicitPathInfo);
+            if (obj == null) {
+                return null;
+            }
+            list.add(obj);
+        }
+
+        return Collections.unmodifiableCollection(list);
+    }
+
     @Override
     public ObjectNode encode(PcePath path, CodecContext context) {
         checkNotNull(path, "path output cannot be null");
@@ -133,6 +235,18 @@
                 .put(COST, ((CostConstraint) path.costConstraint()).type().type())
                 .put(BANDWIDTH, ((BandwidthConstraint) path.bandwidthConstraint()).bandwidth().bps());
 
+        if (path.explicitPathInfo() != null && !path.explicitPathInfo().isEmpty()) {
+            ArrayNode arrayNode = context.mapper().createArrayNode();
+            for (ExplicitPathInfo e : path.explicitPathInfo()) {
+                ObjectNode node = context.mapper()
+                        .createObjectNode()
+                        .put("type", e.type().toString())
+                        .put("value", e.value().toString());
+                arrayNode.add(node);
+            }
+            result.set(EXPLICIT_PATH_INFO, arrayNode);
+        }
+
         result.set(CONSTRAINT, constraintNode);
         return result;
     }
diff --git a/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathWebResource.java b/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathWebResource.java
index a3cd11e..75a3a77 100644
--- a/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathWebResource.java
+++ b/apps/pce/pcerest/src/main/java/org/onosproject/pcerest/PcePathWebResource.java
@@ -35,11 +35,13 @@
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
+import com.google.common.collect.ImmutableList;
 import org.onosproject.incubator.net.tunnel.Tunnel;
 import org.onosproject.incubator.net.tunnel.TunnelId;
 import org.onosproject.incubator.net.tunnel.TunnelService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.intent.Constraint;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.api.PceService;
 import org.onosproject.pce.pceservice.PcePath;
 import org.onosproject.pce.pceservice.DefaultPcePath;
@@ -74,12 +76,16 @@
     @Consumes(MediaType.APPLICATION_JSON)
     public Response queryAllPath() {
         log.debug("Query all paths.");
-        Iterable<Tunnel> tunnels = get(PceService.class).queryAllPath();
+        PceService pceService = get(PceService.class);
+        Iterable<Tunnel> tunnels = pceService.queryAllPath();
+
         ObjectNode result = mapper().createObjectNode();
         ArrayNode pathEntry = result.putArray("paths");
         if (tunnels != null) {
             for (final Tunnel tunnel : tunnels) {
-                PcePath path = DefaultPcePath.builder().of(tunnel).build();
+                PcePath path = DefaultPcePath.builder().of(tunnel, pceService.explicitPathInfoList(tunnel
+                        .tunnelName().value()))
+                        .build();
                 pathEntry.add(codec(PcePath.class).encode(path, this));
             }
         }
@@ -98,9 +104,12 @@
     @Consumes(MediaType.APPLICATION_JSON)
     public Response queryPath(@PathParam("path_id") String id) {
         log.debug("Query path by identifier {}.", id);
-        Tunnel tunnel = nullIsNotFound(get(PceService.class).queryPath(TunnelId.valueOf(id)),
-                                       PCE_PATH_NOT_FOUND);
-        PcePath path = DefaultPcePath.builder().of(tunnel).build();
+        PceService pceService = get(PceService.class);
+
+        Tunnel tunnel = nullIsNotFound(pceService.queryPath(TunnelId.valueOf(id)),
+                PCE_PATH_NOT_FOUND);
+        PcePath path = DefaultPcePath.builder().of(tunnel, pceService.explicitPathInfoList(tunnel
+                .tunnelName().value())).build();
         if (path == null) {
             return Response.status(OK).entity(PCE_SETUP_PATH_FAILED).build();
         }
@@ -150,8 +159,14 @@
             // Add cost
             listConstrnt.add(path.costConstraint());
 
+            List<ExplicitPathInfo> explicitPathInfoList = null;
+            if (path.explicitPathInfo() != null) {
+                explicitPathInfoList = ImmutableList.copyOf(path.explicitPathInfo());
+            }
+
             Boolean issuccess = nullIsNotFound(get(PceService.class)
-                                               .setupPath(srcDevice, dstDevice, path.name(), listConstrnt, lspType),
+                                               .setupPath(srcDevice, dstDevice, path.name(), listConstrnt,
+                                                       lspType, explicitPathInfoList),
                                                PCE_SETUP_PATH_FAILED);
             return Response.status(OK).entity(issuccess.toString()).build();
         } catch (IOException e) {
diff --git a/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java b/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java
index 862fb14..ae2e32c 100644
--- a/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java
+++ b/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java
@@ -40,6 +40,7 @@
 import javax.ws.rs.core.Response;
 import javax.ws.rs.NotFoundException;
 
+import com.google.common.collect.Lists;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -62,8 +63,10 @@
 import org.onosproject.net.DefaultPath;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Link;
+import org.onosproject.pce.pceservice.ExplicitPathInfo;
 import org.onosproject.pce.pceservice.api.PceService;
 import org.onosproject.pce.pceservice.PcepAnnotationKeys;
+import org.onosproject.pce.pcestore.api.PceStore;
 import org.onosproject.net.Path;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.provider.ProviderId;
@@ -73,6 +76,7 @@
  */
 public class PcePathResourceTest extends PceResourceTest {
     private final PceService pceService = createMock(PceService.class);
+    private final PceStore pceStore = createMock(PceStore.class);
     private final TunnelService tunnelService = createMock(TunnelService.class);
     private final TunnelEndPoint src = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(23423));
     private final TunnelEndPoint dst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(32421));
@@ -82,6 +86,7 @@
     private final ProviderId producerName = new ProviderId("producer1", "13");
     private Path path;
     private Tunnel tunnel;
+    private List<ExplicitPathInfo> explicitPathInfoList;
     private DeviceId deviceId1;
     private DeviceId deviceId2;
     private DeviceId deviceId3;
@@ -102,6 +107,7 @@
        MockPceCodecContext context = new MockPceCodecContext();
        ServiceDirectory testDirectory = new TestServiceDirectory().add(PceService.class, pceService)
                                                                   .add(TunnelService.class, tunnelService)
+                                                                  .add(PceStore.class, pceStore)
                                                                   .add(CodecService.class, context.codecManager());
        BaseResource.setServiceDirectory(testDirectory);
 
@@ -170,6 +176,11 @@
        tunnel = new DefaultTunnel(producerName, src, dst, Tunnel.Type.VXLAN,
                                   Tunnel.State.ACTIVE, groupId, tunnelId,
                                   tunnelName, path, builderAnn.build());
+
+        explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, deviceId2);
+        explicitPathInfoList.add(obj);
+
     }
 
     /**
@@ -201,6 +212,10 @@
         expect(pceService.queryPath(anyObject()))
                          .andReturn(tunnel)
                          .anyTimes();
+
+        expect(pceService.explicitPathInfoList(tunnel.tunnelName().value()))
+                .andReturn(explicitPathInfoList)
+                .anyTimes();
         replay(pceService);
 
         WebTarget wt = target();
@@ -233,7 +248,7 @@
      */
     @Test
     public void testPost() {
-        expect(pceService.setupPath(anyObject(), anyObject(), anyObject(), anyObject(), anyObject()))
+        expect(pceService.setupPath(anyObject(), anyObject(), anyObject(), anyObject(), anyObject(), anyObject()))
                          .andReturn(true)
                          .anyTimes();
         replay(pceService);
diff --git a/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/pcePath.json b/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/pcePath.json
index 4e6084e..a68c4d7 100644
--- a/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/pcePath.json
+++ b/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/pcePath.json
@@ -7,5 +7,10 @@
    "constraint":
     {  "cost":2,
        "bandwidth":200.0
-    }
+    },
+   "explicitPathInfo" :
+   {"type":1,
+    "subtype":0,
+    "value":"11.0.0.2"
+   }
 }
diff --git a/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/post-PcePath.json b/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/post-PcePath.json
index fcd99e2..479e4f1 100644
--- a/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/post-PcePath.json
+++ b/apps/pce/pcerest/src/test/resources/org/onosproject/pcerest/post-PcePath.json
@@ -1,11 +1,15 @@
 {"path": {"source":"11.0.0.1",
           "destination":"11.0.0.2",
-          "pathType":"2",
-          "name":"pcc2",
-          "description":"path-create",
+          "pathType":"0",
+          "name":"rsvp11",
           "constraint":
-            {"cost":2,
-             "bandwidth":200.0
+            {"cost":1,
+             "bandwidth":300
+            },
+          "explicitPathInfo" :
+            {"type":1,
+             "subtype":0,
+             "value":"11.0.0.2"
             }
          }
 }
diff --git a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
index 4b848a6..8282d8c 100644
--- a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
+++ b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
@@ -507,7 +507,9 @@
                 break;
         }
 
-        path = pceService.setupPath((DeviceId) src, (DeviceId) dst, tunnelName, listConstrnt, lspTypeVal);
+        //TODO: need to get explicit paths [temporarily using null as the value]
+        path = pceService.setupPath((DeviceId) src, (DeviceId) dst, tunnelName, listConstrnt, lspTypeVal,
+                null);
         if (!path) {
              log.error("setup path is failed");
              return;