Add protection in portmapping connection-map loop
[transportpce.git] / common / src / main / java / org / opendaylight / transportpce / common / mapping / PortMappingVersion221.java
index 1a9af0b8bc33961963655cb9d0d1d094835db592..a908de054ae60bb514c866f344ae9111a6924d8e 100644 (file)
@@ -10,10 +10,7 @@ package org.opendaylight.transportpce.common.mapping;
 
 import com.google.common.util.concurrent.FluentFuture;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Base64;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -99,16 +96,14 @@ import org.opendaylight.yangtools.yang.common.Uint32;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+// FIXME: many common pieces of code between PortMapping Versions 121 and 221 and 710
+// some mutualization would be helpful
 public class PortMappingVersion221 {
     private static final Logger LOG = LoggerFactory.getLogger(PortMappingVersion221.class);
 
     private final DataBroker dataBroker;
     private final DeviceTransactionManager deviceTransactionManager;
     private final OpenRoadmInterfaces openRoadmInterfaces;
-    //FNV1 64 bit hash constants
-    private static final BigInteger FNV_PRIME = new BigInteger("100000001b3", 16);
-    private static final BigInteger FNV_INIT = new BigInteger("cbf29ce484222325", 16);
-    private static final BigInteger FNV_MOD = new BigInteger("2").pow(64);
 
     public PortMappingVersion221(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager,
         OpenRoadmInterfaces openRoadmInterfaces) {
@@ -125,14 +120,12 @@ public class PortMappingVersion221 {
         Optional<Info> deviceInfoOptional = this.deviceTransactionManager.getDataFromDevice(
                 nodeId, LogicalDatastoreType.OPERATIONAL, infoIID,
                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
-        Info deviceInfo;
-        NodeInfo nodeInfo;
         if (!deviceInfoOptional.isPresent()) {
             LOG.warn("Device info subtree is absent for {}", nodeId);
             return false;
         }
-        deviceInfo = deviceInfoOptional.get();
-        nodeInfo = createNodeInfo(deviceInfo, nodeId);
+        Info deviceInfo = deviceInfoOptional.get();
+        NodeInfo nodeInfo = createNodeInfo(deviceInfo);
         if (nodeInfo == null) {
             return false;
         }
@@ -215,25 +208,22 @@ public class PortMappingVersion221 {
         Optional<OrgOpenroadmDevice> deviceObject = deviceTransactionManager.getDataFromDevice(nodeId,
             LogicalDatastoreType.OPERATIONAL, deviceIID,
             Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
-        OrgOpenroadmDevice device = null;
         if (!deviceObject.isPresent()) {
             LOG.error("Impossible to get device configuration for node {}", nodeId);
             return false;
         }
-        device = deviceObject.get();
+        OrgOpenroadmDevice device = deviceObject.get();
+        if (device.getCircuitPacks() == null) {
+            LOG.warn("Circuit Packs are not present for {}", nodeId);
+            return false;
+        }
         // Variable to keep track of number of line ports
         int line = 1;
         // Variable to keep track of number of client ports
         int client = 1;
         Map<String, String> lcpMap = new HashMap<>();
         Map<String, Mapping> mappingMap = new HashMap<>();
-
-        List<CircuitPacks> circuitPackList = null;
-        if (device.getCircuitPacks() == null) {
-            LOG.warn("Circuit Packs are not present for {}", nodeId);
-            return false;
-        }
-        circuitPackList = new ArrayList<>(deviceObject.get().nonnullCircuitPacks().values());
+        List<CircuitPacks> circuitPackList = new ArrayList<>(device.nonnullCircuitPacks().values());
         circuitPackList.sort(Comparator.comparing(CircuitPack::getCircuitPackName));
 
         if (device.getXponder() == null) {
@@ -428,31 +418,33 @@ public class PortMappingVersion221 {
             }
         }
 
-        if (device.getConnectionMap() != null) {
+        if (device.getConnectionMap() == null) {
+            LOG.warn("No connection-map inside device configuration");
+        } else {
             Collection<ConnectionMap> connectionMap = deviceObject.get().nonnullConnectionMap().values();
-            String slcp = null;
-            String dlcp = null;
             for (ConnectionMap cm : connectionMap) {
+                String slcp = null;
+                String dlcp = null;
                 String skey = cm.getSource().getCircuitPackName() + "+" + cm.getSource().getPortName();
                 if (lcpMap.containsKey(skey)) {
                     slcp = lcpMap.get(skey);
                 }
                 Destination destination0 = cm.nonnullDestination().values().iterator().next();
                 String dkey = destination0.getCircuitPackName() + "+" + destination0.getPortName();
+                if (slcp == null) {
+                    LOG.error("Error in connection-map analysis for source {} and destination (circuitpack+port) {}",
+                        skey, dkey);
+                    continue;
+                }
                 if (lcpMap.containsKey(dkey)) {
                     dlcp = lcpMap.get(dkey);
                 }
-                if (slcp != null) {
-                    Mapping mapping = mappingMap.get(slcp);
-                    mappingMap.remove(slcp);
-                    portMapList.add(createXpdrMappingObject(nodeId, null, null, null, null, mapping, dlcp, null));
-                } else {
-                    LOG.error("Error in connection-map analysis");
-                }
+                Mapping mapping = mappingMap.get(slcp);
+                mappingMap.remove(slcp);
+                portMapList.add(createXpdrMappingObject(nodeId, null, null, null, null, mapping, dlcp, null));
             }
-        } else {
-            LOG.warn("No connection-map inside device configuration");
         }
+
         if (device.getOduSwitchingPools() != null) {
             Collection<OduSwitchingPools> oduSwithcingPools = device.nonnullOduSwitchingPools().values();
             List<SwitchingPoolLcp> switchingPoolList = new ArrayList<>();
@@ -841,11 +833,10 @@ public class PortMappingVersion221 {
         Nodes nodes = nodesBldr.build();
         nodesList.put(nodes.key(),nodes);
 
-        NetworkBuilder nwBldr = new NetworkBuilder().setNodes(nodesList);
+        Network network = new NetworkBuilder().setNodes(nodesList).build();
 
         final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
         InstanceIdentifier<Network> nodesIID = InstanceIdentifier.builder(Network.class).build();
-        Network network = nwBldr.build();
         writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodesIID, network);
         FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
         try {
@@ -916,11 +907,14 @@ public class PortMappingVersion221 {
     }
 
     private Mapping createMappingObject(String nodeId, Ports port, String circuitPackName,
-        String logicalConnectionPoint) {
-        MappingBuilder mpBldr = new MappingBuilder();
-        mpBldr.withKey(new MappingKey(logicalConnectionPoint)).setLogicalConnectionPoint(logicalConnectionPoint)
-            .setSupportingCircuitPackName(circuitPackName).setSupportingPort(port.getPortName())
-            .setPortDirection(port.getPortDirection().getName());
+            String logicalConnectionPoint) {
+
+        MappingBuilder mpBldr = new MappingBuilder()
+                .withKey(new MappingKey(logicalConnectionPoint))
+                .setLogicalConnectionPoint(logicalConnectionPoint)
+                .setSupportingCircuitPackName(circuitPackName)
+                .setSupportingPort(port.getPortName())
+                .setPortDirection(port.getPortDirection().getName());
 
         // Get OMS and OTS interface provisioned on the TTP's
         if ((logicalConnectionPoint.contains(StringConstants.TTP_TOKEN)
@@ -959,42 +953,42 @@ public class PortMappingVersion221 {
     private Mapping createXpdrMappingObject(String nodeId, Ports port, String circuitPackName,
             String logicalConnectionPoint, String partnerLcp, Mapping mapping, String connectionMapLcp,
             XpdrNodeTypes xpdrNodeType) {
-        MappingBuilder mpBldr;
+
         if (mapping != null && connectionMapLcp != null) {
             // update existing mapping
-            mpBldr = new MappingBuilder(mapping).setConnectionMapLcp(connectionMapLcp);
-        } else {
-            // create a new mapping
-            String nodeIdLcp = nodeId + "-" + logicalConnectionPoint;
-            mpBldr = new MappingBuilder()
+            return new MappingBuilder(mapping).setConnectionMapLcp(connectionMapLcp).build();
+        }
+
+        // create a new mapping
+        String nodeIdLcp = nodeId + "-" + logicalConnectionPoint;
+        MappingBuilder mpBldr = new MappingBuilder()
                 .withKey(new MappingKey(logicalConnectionPoint))
                 .setLogicalConnectionPoint(logicalConnectionPoint)
                 .setSupportingCircuitPackName(circuitPackName)
                 .setSupportingPort(port.getPortName())
                 .setPortDirection(port.getPortDirection().getName())
-                .setLcpHashVal(fnv(nodeIdLcp));
-            if (port.getPortQual() != null) {
-                mpBldr.setPortQual(port.getPortQual().getName());
-            }
-            if (xpdrNodeType != null) {
-                mpBldr.setXponderType(
-                    org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129
-                        .XpdrNodeTypes.forValue(xpdrNodeType.getIntValue()));
-            }
-            if (partnerLcp != null) {
-                mpBldr.setPartnerLcp(partnerLcp);
-            }
-            if (port.getSupportedInterfaceCapability() != null) {
-                List<Class<? extends org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev200327
-                    .SupportedIfCapability>> supportedIntf = new ArrayList<>();
-                for (Class<? extends SupportedIfCapability> sup: port.getSupportedInterfaceCapability()) {
-                    Class<? extends org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev200327
-                        .SupportedIfCapability> sup1 = (Class<? extends org.opendaylight.yang.gen.v1
+                .setLcpHashVal(FnvUtils.fnv1_64(nodeIdLcp));
+        if (port.getPortQual() != null) {
+            mpBldr.setPortQual(port.getPortQual().getName());
+        }
+        if (xpdrNodeType != null) {
+            mpBldr.setXponderType(
+                org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129
+                    .XpdrNodeTypes.forValue(xpdrNodeType.getIntValue()));
+        }
+        if (partnerLcp != null) {
+            mpBldr.setPartnerLcp(partnerLcp);
+        }
+        if (port.getSupportedInterfaceCapability() != null) {
+            List<Class<? extends org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev200327
+                .SupportedIfCapability>> supportedIntf = new ArrayList<>();
+            for (Class<? extends SupportedIfCapability> sup: port.getSupportedInterfaceCapability()) {
+                Class<? extends org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev200327
+                    .SupportedIfCapability> sup1 = (Class<? extends org.opendaylight.yang.gen.v1
                         .http.org.openroadm.port.types.rev200327.SupportedIfCapability>) sup;
-                    supportedIntf.add(sup1);
-                }
-                mpBldr.setSupportedInterfaceCapability(supportedIntf);
+                supportedIntf.add(sup1);
             }
+            mpBldr.setSupportedInterfaceCapability(supportedIntf);
         }
         return mpBldr.build();
     }
@@ -1139,30 +1133,28 @@ public class PortMappingVersion221 {
         return true;
     }
 
-    private NodeInfo createNodeInfo(Info deviceInfo, String nodeId) {
-        NodeInfoBuilder nodeInfoBldr = new NodeInfoBuilder();
+    private NodeInfo createNodeInfo(Info deviceInfo) {
+
         if (deviceInfo.getNodeType() == null) {
             // TODO make mandatory in yang
             LOG.error("Node type field is missing");
             return null;
         }
 
-        nodeInfoBldr.setOpenroadmVersion(OpenroadmVersion._221).setNodeType(NodeTypes.forValue(deviceInfo
-            .getNodeType().getIntValue()));
+        NodeInfoBuilder nodeInfoBldr = new NodeInfoBuilder()
+                .setOpenroadmVersion(OpenroadmVersion._221)
+                .setNodeType(NodeTypes.forValue(deviceInfo.getNodeType().getIntValue()));
         if (deviceInfo.getClli() != null && !deviceInfo.getClli().isEmpty()) {
             nodeInfoBldr.setNodeClli(deviceInfo.getClli());
         } else {
             nodeInfoBldr.setNodeClli("defaultCLLI");
         }
-
         if (deviceInfo.getModel() != null) {
             nodeInfoBldr.setNodeModel(deviceInfo.getModel());
         }
-
         if (deviceInfo.getVendor() != null) {
             nodeInfoBldr.setNodeVendor(deviceInfo.getVendor());
         }
-
         if (deviceInfo.getIpAddress() != null) {
             nodeInfoBldr.setNodeIpAddress(deviceInfo.getIpAddress());
         }
@@ -1170,24 +1162,4 @@ public class PortMappingVersion221 {
         return nodeInfoBldr.build();
     }
 
-    /**
-     * Implements the FNV-1 64bit algorithm.
-     * FNV-1 128bit would be ideal for 16 bytes but we need an overhead for Base64 encoding.
-     * Otherwise, the hash cannot be stored in a UTF-8 string.
-     * https://www.wikiwand.com/en/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#/FNV-1_hash
-     * https://github.com/pmdamora/fnv-cracker-app/blob/master/src/main/java/passwordcrack/cracking/HashChecker.java
-     * @param stringdata the String to be hashed
-     * @return the hash string
-     */
-    private String fnv(String stringdata) {
-        BigInteger hash = FNV_INIT;
-        byte[] data = stringdata.getBytes(StandardCharsets.UTF_8);
-
-        for (byte b : data) {
-            hash = hash.multiply(FNV_PRIME).mod(FNV_MOD);
-            hash = hash.xor(BigInteger.valueOf((int) b & 0xff));
-        }
-
-        return Base64.getEncoder().encodeToString(hash.toByteArray());
-    }
 }