PCE Calculation on UNIDIR port 74/79074/7
authorMartial COULIBALY <martial.coulibaly@gfi.fr>
Wed, 26 Dec 2018 15:21:36 +0000 (16:21 +0100)
committerMartial COULIBALY <martial.coulibaly@gfi.fr>
Tue, 8 Jan 2019 15:06:08 +0000 (16:06 +0100)
- force PCE to calculate ZToA path on unidir ports.
- solve PCE calculation error with SRG-CP Bidirectionel with
SRG-PP unidir.
- solve NullPointerException cause by getting oppositeLink
for UNIDIR link, not present in topology.

JIRA: TRNSPRTPCE-70
Change-Id: I728cc081c7a40838349eef6481f82b6bf1349029
Signed-off-by: Martial COULIBALY <martial.coulibaly@gfi.fr>
12 files changed:
pce/src/main/java/org/opendaylight/transportpce/pce/PceCalculation.java
pce/src/main/java/org/opendaylight/transportpce/pce/PceNode.java
pce/src/main/java/org/opendaylight/transportpce/pce/PcePathDescription.java
pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java
pce/src/main/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImpl.java
pce/src/main/resources/org/opendaylight/blueprint/pce-blueprint.xml
pce/src/test/java/org/opendaylight/transportpce/pce/PceManyTests.java
pce/src/test/java/org/opendaylight/transportpce/pce/PceSingleTests.java
servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/ModelMappingUtilsTest.java
servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/impl/ServiceHandlerImplTest.java
servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/service/PCEServiceWrapperTest.java
servicehandler/src/test/java/org/opendaylight/transportpce/servicehandler/service/ServiceDataStoreOperationsImplTest.java

index 67e9b02cf21efa9a571fdea79a4899c7ae0300fd..6377c101e5df11ffe8b0a647b56d65ffc1795d58 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.transportpce.common.NetworkUtils;
 import org.opendaylight.transportpce.common.ResponseCodes;
+import org.opendaylight.transportpce.common.mapping.PortMapping;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.PathComputationRequestInput;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmNodeType;
@@ -41,6 +42,7 @@ public class PceCalculation {
     /* Logging. */
     private static final Logger LOG = LoggerFactory.getLogger(PceCalculation.class);
     private DataBroker dataBroker = null;
+    private PortMapping portMapping = null;
     ///////////// data parsed from Input/////////////////
     private PathComputationRequestInput input;
     private String anodeId = "";
@@ -72,9 +74,10 @@ public class PceCalculation {
 
     // private static final String NETWORK_ID = "Transport Overlay";
     public PceCalculation(PathComputationRequestInput input, DataBroker dataBroker, PceConstraints pceHardConstraints,
-            PceConstraints pceSoftConstraints, PceResult rc) {
+            PceConstraints pceSoftConstraints, PceResult rc, PortMapping portMapping) {
         this.input = input;
         this.dataBroker = dataBroker;
+        this.portMapping = portMapping;
         this.returnStructure = rc;
         this.pceHardConstraints = pceHardConstraints;
         this.pceSoftConstraints = pceSoftConstraints;
@@ -325,7 +328,7 @@ public class PceCalculation {
             default:
                 break;
         }
-        PceNode pceNode = new PceNode(node, nodeType, nodeId);
+        PceNode pceNode = new PceNode(node, nodeType, nodeId, portMapping);
         if (!pceNode.isValid()) {
             LOG.error(" validateNode: Node is ignored due errors in network data ");
             return false;
index 28372ffb5b6bd94a91c7fef2d3e22dd812db2446..906887235239caa36ca6f17d127bbdf37fc5bdc6 100644 (file)
@@ -13,7 +13,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.TreeMap;
+import java.util.stream.Collectors;
 
+import org.opendaylight.transportpce.common.mapping.PortMapping;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev170228.network.nodes.Mapping;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.Direction;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.pp.attributes.UsedWavelength;
@@ -41,8 +45,10 @@ public class PceNode {
     private List<String> usedXpndrNWTps = new ArrayList<String>();
     private List<PceLink> outgoingLinks = new ArrayList<PceLink>();
     private Map<String, String> clientPerNwTp = new HashMap<String, String>();
+    private PortMapping portMapping;
+    private boolean isUnidir;
 
-    public PceNode(Node node, OpenroadmNodeType nodeType, NodeId nodeId) {
+    public PceNode(Node node, OpenroadmNodeType nodeType, NodeId nodeId, PortMapping portMapping) {
         this.node = node;
         this.nodeId = nodeId;
         this.nodeType = nodeType;
@@ -50,6 +56,8 @@ public class PceNode {
             LOG.error("PceNode: one of parameters is not populated : nodeId, node type");
             this.valid = false;
         }
+        this.portMapping = portMapping;
+        this.isUnidir = false;
     }
 
     public void initSrgTps() {
@@ -113,6 +121,7 @@ public class PceNode {
         }
         LOG.info("initSrgTpList: availableSrgPp size = {} && availableSrgCp size = {} in {}", this.availableSrgPp
                 .size(), this.availableSrgCp.size(), this.toString());
+        this.isUnidir();
         return;
     }
 
@@ -210,6 +219,41 @@ public class PceNode {
             LOG.error("initXndrTps: XPONDER doesn't have available wavelengths for node  {}", this.toString());
             return;
         }
+        this.isUnidir();
+    }
+
+    private void isUnidir() {
+        LOG.info("isUnidir: getting port direction...");
+        switch (nodeType) {
+            case XPONDER:
+                LOG.info("isUnidir: getting port direction on XPONDER-NETWORK port ...");
+                Optional<String> tp = this.clientPerNwTp.keySet().stream().findFirst();
+                Mapping mapping = this.portMapping.getMapping(node.getSupportingNode().get(0).getNodeRef().getValue(),
+                    tp.get());
+                if (mapping != null) {
+                    if (mapping.getPortDirection().compareTo(Direction.Bidirectional) != 0) {
+                        this.isUnidir = true;
+                        LOG.warn("isUnidir: XPONDER NETWORK have UNIDIR port...");
+                    }
+                } else {
+                    LOG.error("isUnidir: Cannot get mapping for tp '{}'", tp.get());
+                }
+                break;
+            case SRG:
+                LOG.info("isUnidir: getting port direction on ROADM SRG-PP port ...");
+                List<OpenroadmTpType> resultTx = this.availableSrgPp.values().stream()
+                        .filter(pp -> pp == OpenroadmTpType.SRGTXPP).collect(Collectors.toList());
+                List<OpenroadmTpType> resultRx = this.availableSrgPp.values().stream()
+                        .filter(pp -> pp == OpenroadmTpType.SRGRXPP).collect(Collectors.toList());
+                if (!resultTx.isEmpty() && !resultRx.isEmpty()) {
+                    this.isUnidir = true;
+                    LOG.warn("isUnidir: SRG node have UNIDIR port...");
+                }
+                break;
+            default:
+                this.isUnidir = false;
+                break;
+        }
     }
 
     public String getRdmSrgClient(String tp, Boolean aend) {
@@ -222,8 +266,20 @@ public class PceNode {
         }
         switch (cpType) {
             case SRGTXRXCP:
-                LOG.info("getRdmSrgClient: Getting BI Directional PP port ...");
-                srgType = OpenroadmTpType.SRGTXRXPP;
+                LOG.info("getRdmSrgClient: Getting BI or UNI Directional PP port ...");
+                if (this.isUnidir) {
+                    LOG.info("getRdmSrgClient: Getting UNI PP Port");
+                    if (aend) {
+                        LOG.info("getRdmSrgClient: Getting UNI Rx PP port ...");
+                        srgType = OpenroadmTpType.SRGRXPP;
+                    } else {
+                        LOG.info("getRdmSrgClient: Getting UNI Tx PP port ...");
+                        srgType = OpenroadmTpType.SRGTXPP;
+                    }
+                } else {
+                    LOG.info("getRdmSrgClient: Getting BI PP Port");
+                    srgType = OpenroadmTpType.SRGTXRXPP;
+                }
                 break;
             case SRGTXCP:
                 LOG.info("getRdmSrgClient: Getting UNI Rx PP port ...");
@@ -290,6 +346,14 @@ public class PceNode {
         return this.clientPerNwTp.get(tp);
     }
 
+    public OpenroadmNodeType getPceNodeType() {
+        return this.nodeType;
+    }
+
+    public boolean getUnidir() {
+        return this.isUnidir;
+    }
+
     @Override
     public String toString() {
         return "PceNode type=" + this.nodeType + " ID=" + this.nodeId.getValue();
index a65a0773d346ec7ea655acfffdb0b572f59f5316..41bdc2d2c332141e3ff0f647a8f1dd98f26e161b 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.transportpce.pce;
 
 import com.google.common.collect.ImmutableList;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+
 import org.opendaylight.transportpce.common.ResponseCodes;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirectionBuilder;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirectionBuilder;
@@ -196,106 +198,110 @@ public class PcePathDescription {
         Integer index = 0;
         PceLink lastLink = null;
         ZToA lastResource = null;
+        LinkId oppositeLinkId;
 
         // build Z size Client TP
-        PceLink pcelink = this.allPceLinks.get(path.get(0).getOppositeLink());
-        String tpName = pcelink.getClient();
-        String xname = pcelink.getSourceId().getValue();
-        TerminationPoint stp = new TerminationPointBuilder()
-                .setTpNodeId(xname).setTpId(tpName)
-                .build();
-
-        ZToAKey clientKey = new ZToAKey(index.toString());
-        Resource clientResource = new ResourceBuilder().setResource(stp).build();
-        ZToA firstResource = new ZToABuilder().setId(tpName).withKey(clientKey).setResource(clientResource).build();
-        etoelist.add(firstResource);
-        index++;
-
-        for (PceLink pcelinkAtoZ : path) {
-
-            pcelink = this.allPceLinks.get(pcelinkAtoZ.getOppositeLink());
-            LOG.debug("link to oppsite: {} to {}", pcelinkAtoZ.toString(), pcelink.toString());
-
-            String srcName = pcelink.getSourceId().getValue();
-
-
-            // Nodes
-            org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
-                .resource.resource.resource.Node sourceNode = new NodeBuilder()
-                .setNodeId(srcName).build();
-
-
-            // Source Resource
-            ZToAKey sourceKey = new ZToAKey(index.toString());
-            Resource nodeResource1 = new ResourceBuilder().setResource(sourceNode).build();
-            ZToA srcResource = new ZToABuilder().setId(srcName).withKey(sourceKey).setResource(nodeResource1).build();
-            index++;
-            etoelist.add(srcResource);
-
-            // source TP
-            tpName = pcelink.getSourceTP().toString();
-            stp = new TerminationPointBuilder()
-                    .setTpNodeId(srcName).setTpId(tpName)
+        try {
+            oppositeLinkId = path.get(0).getOppositeLink();
+        } catch (NullPointerException e) {
+            LOG.warn("buildZtoA : OppositeLink for link '{}' is null, maybe UNIDIR Link ...", path.get(0));
+            return;
+        }
+        PceLink pcelink = this.allPceLinks.get(oppositeLinkId);
+        if (pcelink != null) {
+            String tpName = pcelink.getClient();
+            String xname = pcelink.getSourceId().getValue();
+            TerminationPoint stp = new TerminationPointBuilder()
+                    .setTpNodeId(xname).setTpId(tpName)
                     .build();
-
-            // Resource
-            ZToAKey srcTPKey = new ZToAKey(index.toString());
-            Resource tpResource1 = new ResourceBuilder().setResource(stp).build();
-            ZToA stpResource = new ZToABuilder().setId(tpName).withKey(srcTPKey).setResource(tpResource1).build();
+            ZToAKey clientKey = new ZToAKey(index.toString());
+            Resource clientResource = new ResourceBuilder().setResource(stp).build();
+            ZToA firstResource = new ZToABuilder().setId(tpName).withKey(clientKey).setResource(clientResource).build();
+            etoelist.add(firstResource);
             index++;
-            etoelist.add(stpResource);
-
-            String linkName = pcelink.getLinkId().getValue();
-            // Link
-            org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
-                .resource.resource.resource.Link ztoaLink = new LinkBuilder()
-                .setLinkId(linkName).build();
-
-            // Link Resource
-            ZToAKey linkKey = new ZToAKey(index.toString());
-            Resource nodeResource2 = new ResourceBuilder().setResource(ztoaLink).build();
-            ZToA linkResource = new ZToABuilder().setId(linkName).withKey(linkKey).setResource(nodeResource2).build();
-            index++;
-            etoelist.add(linkResource);
-
-            String destName = pcelink.getDestId().getValue();
-            // target TP
-            tpName = pcelink.getDestTP().toString();
-            TerminationPoint ttp = new TerminationPointBuilder()
-                    .setTpNodeId(destName).setTpId(tpName).build();
+            for (PceLink pcelinkAtoZ : path) {
+                pcelink = this.allPceLinks.get(pcelinkAtoZ.getOppositeLink());
+                LOG.debug("link to oppsite: {} to {}", pcelinkAtoZ.toString(), pcelink.toString());
+                String srcName = pcelink.getSourceId().getValue();
+                // Nodes
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.Node sourceNode = new NodeBuilder()
+                    .setNodeId(srcName).build();
+
+                // Source Resource
+                ZToAKey sourceKey = new ZToAKey(index.toString());
+                Resource nodeResource1 = new ResourceBuilder().setResource(sourceNode).build();
+                ZToA srcResource = new ZToABuilder().setId(srcName).withKey(sourceKey).setResource(nodeResource1)
+                    .build();
+                index++;
+                etoelist.add(srcResource);
+
+                // source TP
+                tpName = pcelink.getSourceTP().toString();
+                stp = new TerminationPointBuilder()
+                        .setTpNodeId(srcName).setTpId(tpName)
+                        .build();
+
+                // Resource
+                ZToAKey srcTPKey = new ZToAKey(index.toString());
+                Resource tpResource1 = new ResourceBuilder().setResource(stp).build();
+                ZToA stpResource = new ZToABuilder().setId(tpName).withKey(srcTPKey).setResource(tpResource1).build();
+                index++;
+                etoelist.add(stpResource);
+
+                String linkName = pcelink.getLinkId().getValue();
+                // Link
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.Link ztoaLink = new LinkBuilder()
+                    .setLinkId(linkName).build();
+
+                // Link Resource
+                ZToAKey linkKey = new ZToAKey(index.toString());
+                Resource nodeResource2 = new ResourceBuilder().setResource(ztoaLink).build();
+                ZToA linkResource = new ZToABuilder().setId(linkName).withKey(linkKey).setResource(nodeResource2)
+                    .build();
+                index++;
+                etoelist.add(linkResource);
+
+                String destName = pcelink.getDestId().getValue();
+                // target TP
+                tpName = pcelink.getDestTP().toString();
+                TerminationPoint ttp = new TerminationPointBuilder()
+                        .setTpNodeId(destName).setTpId(tpName).build();
+
+                // Resource
+                ZToAKey destTPKey = new ZToAKey(index.toString());
+                Resource tpResource2 = new ResourceBuilder().setResource(ttp).build();
+                ZToA ttpResource = new ZToABuilder().setId(tpName).withKey(destTPKey).setResource(tpResource2).build();
+                index++;
+                etoelist.add(ttpResource);
+
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.Node targetNode = new NodeBuilder()
+                    .setNodeId(destName).build();
+                // Target Resource
+                ZToAKey targetKey = new ZToAKey(index.toString());
+                Resource nodeResource3 = new ResourceBuilder().setResource(targetNode).build();
+                lastResource = new ZToABuilder().setId(destName).withKey(targetKey).setResource(nodeResource3).build();
+
+                lastLink = pcelink;
+            }
+            etoelist.add(lastResource);
+
+            // build Z side Client TP
+            tpName = lastLink.getClient();
+            xname = lastLink.getDestId().getValue();
+            stp = new TerminationPointBuilder()
+                    .setTpNodeId(xname).setTpId(tpName).build();
 
-            // Resource
-            ZToAKey destTPKey = new ZToAKey(index.toString());
-            Resource tpResource2 = new ResourceBuilder().setResource(ttp).build();
-            ZToA ttpResource = new ZToABuilder().setId(tpName).withKey(destTPKey).setResource(tpResource2).build();
             index++;
-            etoelist.add(ttpResource);
-
-
-            org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
-                .resource.resource.resource.Node targetNode = new NodeBuilder()
-                .setNodeId(destName).build();
-            // Target Resource
-            ZToAKey targetKey = new ZToAKey(index.toString());
-            Resource nodeResource3 = new ResourceBuilder().setResource(targetNode).build();
-            lastResource = new ZToABuilder().setId(destName).withKey(targetKey).setResource(nodeResource3).build();
-
-            lastLink = pcelink;
+            clientKey = new ZToAKey(index.toString());
+            clientResource = new ResourceBuilder().setResource(stp).build();
+            lastResource = new ZToABuilder().setId(tpName).withKey(clientKey).setResource(clientResource).build();
+            etoelist.add(lastResource);
+        } else {
+            LOG.warn("buildZtoA : OppositeLink for link '{}' is null, maybe UNIDIR Link ...", path.get(0));
         }
-        etoelist.add(lastResource);
-
-        // build Z side Client TP
-        tpName = lastLink.getClient();
-        xname = lastLink.getDestId().getValue();
-        stp = new TerminationPointBuilder()
-                .setTpNodeId(xname).setTpId(tpName).build();
-
-
-        index++;
-        clientKey = new ZToAKey(index.toString());
-        clientResource = new ResourceBuilder().setResource(stp).build();
-        lastResource = new ZToABuilder().setId(tpName).withKey(clientKey).setResource(clientResource).build();
-        etoelist.add(lastResource);
 
     }
 
index 324b022608b51b717c0d5a5c9f6abccabf4bed87..20d7a60f0af919b37d2fea81662438c81bd26e86 100644 (file)
@@ -8,12 +8,25 @@
 
 package org.opendaylight.transportpce.pce;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.transportpce.common.mapping.PortMapping;
 import org.opendaylight.transportpce.pce.PceResult.LocalCause;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.PathComputationRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.PathComputationRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.path.computation.request.input.ServiceAEnd;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.path.computation.request.input.ServiceAEndBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.path.computation.request.input.ServiceZEnd;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.path.computation.request.input.ServiceZEndBuilder;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.service.path.rpc.result.PathDescriptionBuilder;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirection;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirection;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirectionBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.atoz.direction.AToZ;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ztoa.direction.ZToA;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ztoa.direction.ZToABuilder;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.RoutingConstraintsSp.PceMetric;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,6 +45,7 @@ public class PceSendingPceRPCs {
     private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
     /* define procedure success (or not ). */
     private PceResult rc = new PceResult();
+    private PceResult reverseRc = new PceResult();
 
     /*
      * define type of request<br> <code>true</code> pathcomputation <br>
@@ -40,7 +54,9 @@ public class PceSendingPceRPCs {
     private PathDescriptionBuilder pathDescription;
 
     private PathComputationRequestInput input;
+    private PathComputationRequestInput reverseInput;
     private DataBroker dataBroker;
+    private PortMapping portMapping;
 
     private PceConstraints pceHardConstraints = new PceConstraints();
     private PceConstraints pceSoftConstraints = new PceConstraints();
@@ -49,15 +65,18 @@ public class PceSendingPceRPCs {
         setPathDescription(null);
 
         this.input = null;
+        this.reverseInput = null;
         this.dataBroker = null;
     }
 
-    public PceSendingPceRPCs(PathComputationRequestInput input, DataBroker dataBroker) {
+    public PceSendingPceRPCs(PathComputationRequestInput input, DataBroker dataBroker, PortMapping portMapping) {
         setPathDescription(null);
 
         // TODO compliance check to check that input is not empty
         this.input = input;
+        this.reverseInput = null;
         this.dataBroker = dataBroker;
+        this.portMapping = portMapping;
     }
 
     public void cancelResourceReserve() {
@@ -70,6 +89,16 @@ public class PceSendingPceRPCs {
         LOG.info("cancelResourceReserve ...");
     }
 
+    private void reverseInput() {
+        LOG.info("reverseInput: reversing input endNode ...");
+        ServiceAEnd serviceAEnd = new ServiceAEndBuilder(this.input.getServiceZEnd()).build();
+        ServiceZEnd serviceZEnd = new ServiceZEndBuilder(this.input.getServiceAEnd()).build();
+        this.reverseInput = new PathComputationRequestInputBuilder(this.input)
+                .setServiceAEnd(serviceAEnd)
+                .setServiceZEnd(serviceZEnd)
+                .build();
+    }
+
     public void pathComputation() {
         LOG.info("PathComputation ...");
 
@@ -77,16 +106,19 @@ public class PceSendingPceRPCs {
         pceHardConstraints = constraints.getPceHardConstraints();
         pceSoftConstraints = constraints.getPceSoftConstraints();
 
-
         LOG.info("nwAnalizer ...");
         PceCalculation nwAnalizer = new PceCalculation(input, dataBroker,
-                pceHardConstraints, pceSoftConstraints, rc);
+                pceHardConstraints, pceSoftConstraints, rc, portMapping);
         nwAnalizer.calcPath();
         rc = nwAnalizer.getReturnStructure();
         if (!rc.getStatus()) {
             LOG.error("In pathComputation nwAnalizer: result = {}", rc.toString());
             return;
         }
+        if (nwAnalizer.getaPceNode().getUnidir() || nwAnalizer.getzPceNode().getUnidir()) {
+            LOG.warn("PathComputation: PceNodes contains unidir ports ...");
+            reverseInput();
+        }
 
         LOG.info("PceGraph ...");
         LOG.warn("PathComputation: aPceNode '{}' - zPceNode '{}'", nwAnalizer.getaPceNode(), nwAnalizer.getzPceNode());
@@ -144,6 +176,94 @@ public class PceSendingPceRPCs {
                 .setAToZDirection(atoz)
                 .setZToADirection(ztoa));
         LOG.info("In pathComputation Graph is Found");
+        if (reverseInput != null) {
+            reversePathComputation();
+        }
+    }
+
+    public void reversePathComputation() {
+        LOG.info("reversePathComputation ...");
+
+        PceConstraintsCalc constraints = new PceConstraintsCalc(reverseInput, dataBroker);
+        pceHardConstraints = constraints.getPceHardConstraints();
+        pceSoftConstraints = constraints.getPceSoftConstraints();
+
+        LOG.info("nwAnalizer ...");
+        PceCalculation nwAnalizer = new PceCalculation(reverseInput, dataBroker,
+                pceHardConstraints, pceSoftConstraints, rc, portMapping);
+        nwAnalizer.calcPath();
+        rc = nwAnalizer.getReturnStructure();
+        if (!rc.getStatus()) {
+            LOG.error("In reversePathComputation nwAnalizer: result = {}", rc.toString());
+            return;
+        }
+
+        LOG.info("PceGraph ...");
+        LOG.warn("reversePathComputation: aPceNode '{}' - zPceNode '{}'", nwAnalizer.getaPceNode(),
+                nwAnalizer.getzPceNode());
+        PceGraph graph = new PceGraph(
+                nwAnalizer.getaPceNode(),
+                nwAnalizer.getzPceNode(),
+                nwAnalizer.getAllPceNodes(),
+                pceHardConstraints, pceSoftConstraints, rc);
+        graph.calcPath();
+        rc = graph.getReturnStructure();
+        if (!rc.getStatus()) {
+            LOG.warn("In reversePathComputation : Graph return without Path ");
+            // TODO fix. This is quick workaround for algorithm problem
+            if ((rc.getLocalCause() == LocalCause.TOO_HIGH_LATENCY)
+                && (pceHardConstraints.getPceMetrics() == PceMetric.HopCount)
+                && (pceHardConstraints.getMaxLatency() != -1)) {
+                pceHardConstraints.setPceMetrics(PceMetric.PropagationDelay);
+                graph = patchRerunGraph(graph);
+            }
+
+            if (!rc.getStatus()) {
+                LOG.error("In reversePathComputation graph.calcPath: result = {}", rc.toString());
+                return;
+            }
+        }
+
+        LOG.info("PcePathDescription ...");
+        PcePathDescription description = new PcePathDescription(
+                graph.getPathAtoZ(),
+                nwAnalizer.getAllPceLinks(), rc);
+        description.buildDescriptions();
+        rc = description.getReturnStructure();
+        if (!rc.getStatus()) {
+            LOG.error("In pathComputation description: result = {}", rc.toString());
+            return;
+        }
+
+        LOG.info("setPathDescription ...");
+        AToZDirection atoz = rc.getAtoZDirection();
+        ZToADirection ztoa = rc.getZtoADirection();
+        if ((atoz == null) || (atoz.getAToZ() == null)) {
+            rc.setRC("400");
+            LOG.error("In reversePathComputation empty atoz path after description: result = {}", rc.toString());
+            return;
+        }
+        if ((ztoa == null) || (ztoa.getZToA() == null)) {
+            rc.setRC("400");
+            LOG.error("In reversePathComputation empty ztoa path after description: result = {}", rc.toString());
+            return;
+        }
+        setPathDescription(this.pathDescription
+                .setZToADirection(convertDirection(atoz)));
+        LOG.info("In reversePathComputation Graph is Found");
+    }
+
+    private ZToADirection convertDirection(AToZDirection atozDir) {
+        LOG.info("convertDirection : converting Direction ...");
+        ZToADirectionBuilder result = new ZToADirectionBuilder();
+        List<ZToA> ztoaList = new ArrayList<ZToA>();
+        for (AToZ atoz : atozDir.getAToZ()) {
+            ZToA ztoa = new ZToABuilder().setId(atoz.getId()).setResource(atoz.getResource()).build();
+            ztoaList.add(ztoa);
+        }
+        result.setZToA(ztoaList).setModulationFormat(atozDir.getModulationFormat()).setRate(atozDir.getRate())
+                .setZToAWavelengthNumber(atozDir.getAToZWavelengthNumber());
+        return result.build();
     }
 
     private PceGraph patchRerunGraph(PceGraph graph) {
index e93ea094ba9625ecfe8b0054dcdfa34f2a75a2f7..8d06b1fc51125e208ef406ed16085834008dd3f0 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.transportpce.pce.service;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.transportpce.common.mapping.PortMapping;
 import org.opendaylight.transportpce.pce.PceComplianceCheck;
 import org.opendaylight.transportpce.pce.PceComplianceCheckResult;
 import org.opendaylight.transportpce.pce.PceSendingPceRPCs;
@@ -37,11 +38,13 @@ public class PathComputationServiceImpl implements PathComputationService {
 
     private final NotificationPublishService notificationPublishService;
     private final DataBroker dataBroker;
+    private final PortMapping portMapping;
 
-    public PathComputationServiceImpl(DataBroker dataBroker,
-                                      NotificationPublishService notificationPublishService) {
+    public PathComputationServiceImpl(DataBroker dataBroker, NotificationPublishService notificationPublishService,
+            PortMapping portMapping) {
         this.notificationPublishService = notificationPublishService;
         this.dataBroker = dataBroker;
+        this.portMapping = portMapping;
     }
 
     public void init() {
@@ -124,7 +127,7 @@ public class PathComputationServiceImpl implements PathComputationService {
 
         String message = "";
         String responseCode = "";
-        PceSendingPceRPCs sendingPCE = new PceSendingPceRPCs(input, dataBroker);
+        PceSendingPceRPCs sendingPCE = new PceSendingPceRPCs(input, dataBroker, portMapping);
         sendingPCE.pathComputation();
         message = sendingPCE.getMessage();
         responseCode = sendingPCE.getResponseCode();
index 93d2fa7be6f21b68c7fa0974517497119574d23a..dc8440da12a3dd8a31b5f860533af61c211f9b8c 100755 (executable)
@@ -24,11 +24,14 @@ Author: Martial Coulibaly <martial.coulibaly@gfi.com> on behalf of Orange
         interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService"\r
         odl:type="default" />\r
 \r
+  <reference id="portMapping" interface="org.opendaylight.transportpce.common.mapping.PortMapping" />\r
+\r
   <bean id="pceServiceImpl"\r
         class="org.opendaylight.transportpce.pce.service.PathComputationServiceImpl"\r
         init-method="init" destroy-method="close">\r
     <argument ref="dataBroker"/>\r
     <argument ref="notificationPublishService" />\r
+    <argument ref="portMapping" />\r
   </bean>\r
 \r
   <bean id="provider"\r
index 846210fa95e3d63bbfc9381189b7e982a7355222..8b9e00570f5a59969dfb7e3b1e0e298bb6c22b95 100644 (file)
@@ -75,7 +75,7 @@ public class PceManyTests extends AbstractTest {
         LOG.info("testPathCalculations");
 
         PathComputationService pathComputationService =
-            new PathComputationServiceImpl(getDataBroker(), notificationPublishService);
+            new PathComputationServiceImpl(getDataBroker(), notificationPublishService, null);
         PathComputationRequestOutput output = pathComputationService.pathComputationRequest(input);
 
         PceTestUtils.checkConfigurationResponse(output, expectedOutput);
index bcf40e3860e3a36368196bbbe7f0db8e4a1f8932..cb3f83b3ac8c6fc4e6ba85debb202d81d5bfa598 100644 (file)
@@ -84,7 +84,7 @@ public class PceSingleTests extends AbstractTest {
         PceTestUtils.writeTopologyIntoDataStore(getDataBroker(), getDataStoreContextUtil(), this.topologyDataPath);
 
         PathComputationService pathComputationService =
-            new PathComputationServiceImpl(getDataBroker(), this.notificationPublishService);
+            new PathComputationServiceImpl(getDataBroker(), this.notificationPublishService, null);
         PathComputationRequestOutput output = pathComputationService.pathComputationRequest(this.input);
 
         PceTestUtils.checkConfigurationResponse(output, this.expectedOutput);
index ebc7294ce9f5f5d6f38c6494ae5e90a89cbd21cc..78b162b4ad6984fc5b122dddca6efaa1ff7f5995 100644 (file)
@@ -11,6 +11,7 @@ import java.time.OffsetDateTime;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
+
 import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
@@ -43,7 +44,7 @@ public class ModelMappingUtilsTest extends AbstractTest {
     public ModelMappingUtilsTest() {
         NotificationPublishService notificationPublishService = new NotificationPublishServiceMock();
         PathComputationService pathComputationService = new PathComputationServiceImpl(getDataBroker(),
-            notificationPublishService);
+                notificationPublishService, null);
         pceServiceWrapper = new PCEServiceWrapper(pathComputationService);
         this.pathComputationRequestOutput = pceServiceWrapper.performPCE(ServiceDataUtils.buildServiceCreateInput(),
             true);
index 685a4fcc6cab135448c4924877b90d7e27625ed0..0b7bc015e1cc14dfca50df9d408e631684649c23 100644 (file)
@@ -120,7 +120,7 @@ public class ServiceHandlerImplTest extends AbstractTest {
 
     public ServiceHandlerImplTest() throws Exception {
         NotificationPublishService notificationPublishService = new NotificationPublishServiceMock();
-        this.pathComputationService = new PathComputationServiceImpl(getDataBroker(), notificationPublishService);
+        this.pathComputationService = new PathComputationServiceImpl(getDataBroker(), notificationPublishService, null);
         PceTestUtils.writeTopologyIntoDataStore(getDataBroker(), getDataStoreContextUtil(),
                 "topologyData/NW-simple-topology.xml");
         this.rendererServiceOperations =
index eec103d6999ee945b0ed569443792a6da03d4c6f..83f9cb6ec95d5c5422f7ab1ec0df13218da8c037 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.transportpce.servicehandler.service;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -40,7 +41,7 @@ public class PCEServiceWrapperTest extends AbstractTest {
 
     public PCEServiceWrapperTest() {
         NotificationPublishService notificationPublishService = new NotificationPublishServiceMock();
-        this.pathComputationService = new PathComputationServiceImpl(getDataBroker(), notificationPublishService);
+        this.pathComputationService = new PathComputationServiceImpl(getDataBroker(), notificationPublishService, null);
     }
 
     @Before
index 8a9ae22275bb1c35818b2e346b873b127cf2b65e..6b8d85f55a293baca92b5ee078fe0e430acacd23 100644 (file)
@@ -38,7 +38,7 @@ public class ServiceDataStoreOperationsImplTest extends AbstractTest {
     public ServiceDataStoreOperationsImplTest() {
         NotificationPublishService notificationPublishService = new NotificationPublishServiceMock();
         PathComputationService pathComputationService = new PathComputationServiceImpl(getDataBroker(),
-            notificationPublishService);
+                notificationPublishService, null);
         this.pceServiceWrapper = new PCEServiceWrapper(pathComputationService);
         this.rendererServiceOperations =
                 new StubRendererServiceOperations(this.networkModelWavelengthService, getDataBroker());