Magnesium platform upgrade
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / util / MappingMergeUtil.java
index 63f132c1cbf64ee1f67b5a8d3d04a20d69acf881..540d08a5500c47acbaf407f3a08ce3898500b4bf 100644 (file)
@@ -7,23 +7,30 @@
  */
 package org.opendaylight.lispflowmapping.implementation.util;
 
-import java.net.InetAddress;
+import static org.opendaylight.yangtools.yang.common.UintConversions.fromJava;
+
+import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.LinkedHashMap;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKey;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKeyBuilder;
+import org.opendaylight.lispflowmapping.config.ConfigIni;
+import org.opendaylight.lispflowmapping.lisp.type.MappingData;
 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKeyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
@@ -32,18 +39,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rl
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 /**
- * Utility class to implement merging of locator sets
+ * Utility class to implement merging of locator sets.
  *
  * @author Lorand Jakab
  *
  */
 public final class MappingMergeUtil {
-    protected static final Logger LOG = LoggerFactory.getLogger(MappingMergeUtil.class);
-    // A mapping registration is valid for this many milliseconds
-    private static final long REGISTRATION_VALIDITY = 200000L;
+    private static final Logger LOG = LoggerFactory.getLogger(MappingMergeUtil.class);
 
     // Utility class, should not be instantiated
     private MappingMergeUtil() {
@@ -73,10 +76,10 @@ public final class MappingMergeUtil {
         return newLocator;
     }
 
-    private static int compareLocators(LocatorRecord a, LocatorRecord b) {
-        InetAddress aInet = LispAddressUtil.ipAddressToInet(a.getRloc().getAddress());
-        InetAddress bInet = LispAddressUtil.ipAddressToInet(b.getRloc().getAddress());
-        return LispAddressUtil.compareInetAddresses(aInet, bInet);
+    private static int compareLocators(LocatorRecord one, LocatorRecord two) {
+        byte[] oneIp = LispAddressUtil.ipAddressToByteArray(one.getRloc().getAddress());
+        byte[] twoIp = LispAddressUtil.ipAddressToByteArray(two.getRloc().getAddress());
+        return LispAddressUtil.compareIpAddressByteArrays(oneIp, twoIp);
     }
 
     private static void mergeLocatorRecords(MappingRecordBuilder mrb, MappingRecord newRecord) {
@@ -97,9 +100,7 @@ public final class MappingMergeUtil {
             Rloc newRloc = newLocator.getRloc();
             if (locatorMap.containsKey(newRloc)) {
                 // overlapping locator
-                if (locatorMap.get(newRloc).equals(newLocator)) {
-                    continue;
-                } else {
+                if (!locatorMap.get(newRloc).equals(newLocator)) {
                     LocatorRecord mergedLocator = mergeLocators(locatorMap.get(newRloc), newLocator);
                     newLocatorList.add(mergedLocator);
                 }
@@ -110,39 +111,40 @@ public final class MappingMergeUtil {
         }
 
         // Build new merged and sorted locator set if need be
-        if (newLocatorList.size() != 0) {
+        if (!newLocatorList.isEmpty()) {
             List<LocatorRecord> mergedLocators = new ArrayList<LocatorRecord>();
 
-            int mlIt = 0, lIt = 0;
-            while (mlIt < newLocatorList.size() && lIt < locators.size()) {
-                int cmp = compareLocators(locators.get(lIt), newLocatorList.get(mlIt));
+            int mlocIt = 0;
+            int locIt = 0;
+            while (mlocIt < newLocatorList.size() && locIt < locators.size()) {
+                int cmp = compareLocators(locators.get(locIt), newLocatorList.get(mlocIt));
                 if (cmp < 0) {
-                    mergedLocators.add(locators.get(lIt));
-                    lIt++;
+                    mergedLocators.add(locators.get(locIt));
+                    locIt++;
                 } else if (cmp > 0) {
-                    mergedLocators.add(newLocatorList.get(mlIt));
-                    mlIt++;
+                    mergedLocators.add(newLocatorList.get(mlocIt));
+                    mlocIt++;
                 } else {
                     // when a locator appears in both lists, keep the new (merged) one and skip the old
-                    mergedLocators.add(newLocatorList.get(mlIt));
-                    mlIt++;
-                    lIt++;
+                    mergedLocators.add(newLocatorList.get(mlocIt));
+                    mlocIt++;
+                    locIt++;
                 }
             }
-            while (lIt < locators.size()) {
-                mergedLocators.add(locators.get(lIt));
-                lIt++;
+            while (locIt < locators.size()) {
+                mergedLocators.add(locators.get(locIt));
+                locIt++;
             }
-            while (mlIt < newLocatorList.size()) {
-                mergedLocators.add(newLocatorList.get(mlIt));
-                mlIt++;
+            while (mlocIt < newLocatorList.size()) {
+                mergedLocators.add(newLocatorList.get(mlocIt));
+                mlocIt++;
             }
             mrb.setLocatorRecord(mergedLocators);
         }
     }
 
     public static MappingRecord mergeMappings(MappingRecord currentMergedMapping, MappingRecord newMapping,
-            byte[] xtrId, Date regdate) {
+            XtrId xtrId, Date regdate) {
         if (currentMergedMapping == null) {
             return newMapping;
         }
@@ -159,29 +161,30 @@ public final class MappingMergeUtil {
         return mrb.build();
     }
 
-    public static MappingRecord mergeXtrIdMappings(List<Object> records, List<byte[]> expiredMappings,
-            Set<IpAddress> sourceRlocs) {
+    public static MappingData mergeXtrIdMappings(List<Object> mappingDataList, List<MappingData> expiredMappingDataList,
+            Set<IpAddressBinary> sourceRlocs) {
         MappingRecordBuilder mrb = null;
-        byte[] xtrId = {};
+        XtrId xtrId = null;
         Long timestamp = Long.MAX_VALUE;
 
-        for (int i = 0; i < records.size(); i++) {
-            MappingRecord record = (MappingRecord) records.get(i);
+        for (int i = 0; i < mappingDataList.size(); i++) {
+            MappingData mappingData = (MappingData) mappingDataList.get(i);
+            MappingRecord record = mappingData.getRecord();
 
             // Skip expired mappings and add them to a list to be returned to the caller
-            if (timestampIsExpired(record.getTimestamp())) {
-                expiredMappings.add(record.getXtrId());
+            if (timestampIsExpired(mappingData.getTimestamp())) {
+                expiredMappingDataList.add(mappingData);
                 continue;
             }
 
             if (mrb == null) {
-                mrb = new MappingRecordBuilder((MappingRecord) records.get(i));
+                mrb = new MappingRecordBuilder(record);
             }
 
             // Save the oldest valid timestamp
-            if (record.getTimestamp() < timestamp) {
-                timestamp = record.getTimestamp();
-                xtrId = record.getXtrId();
+            if (mappingData.getTimestamp().getTime() < timestamp) {
+                timestamp = mappingData.getTimestamp().getTime();
+                xtrId = mappingData.getXtrId();
             }
 
             // Merge record fields and locators
@@ -194,11 +197,24 @@ public final class MappingMergeUtil {
 
         if (mrb == null) {
             LOG.warn("All mappings expired when merging! Unexpected!");
+            return null;
         }
         mrb.setXtrId(xtrId);
-        mrb.setTimestamp(timestamp);
 
-        return mrb.build();
+        return new MappingData(mrb.build(), new Date(timestamp));
+    }
+
+    /*
+     * The following three methods intentionally throw an exception when their argument is null, because they can't
+     * decide based on that to return true or false, so the calling function should do that and only call these with
+     * non-null arguments
+     */
+    public static boolean mappingIsExpired(MappingData mappingData) {
+        Preconditions.checkNotNull(mappingData, "mapping should not be null!");
+        if (mappingData.getTimestamp() != null) {
+            return timestampIsExpired(mappingData.getTimestamp());
+        }
+        return false;
     }
 
     public static boolean timestampIsExpired(Date timestamp) {
@@ -206,15 +222,20 @@ public final class MappingMergeUtil {
         return timestampIsExpired(timestamp.getTime());
     }
 
-    public static boolean timestampIsExpired(Long timestamp) {
+    private static boolean timestampIsExpired(Long timestamp) {
         Preconditions.checkNotNull(timestamp, "timestamp should not be null!");
-        if ((System.currentTimeMillis() - timestamp) > REGISTRATION_VALIDITY) {
+        if ((System.currentTimeMillis() - timestamp) > ConfigIni.getInstance().getRegistrationValiditySb()) {
             return true;
         }
         return false;
     }
 
-    public static Object computeNbSbIntersection(MappingRecord nbMapping, MappingRecord sbMapping) {
+    public static MappingData computeNbSbIntersection(MappingData nbMappingData,
+            MappingData sbMappingData) {
+        return new MappingData(computeNbSbIntersection(nbMappingData.getRecord(), sbMappingData.getRecord()));
+    }
+
+    private static MappingRecord computeNbSbIntersection(MappingRecord nbMapping, MappingRecord sbMapping) {
         // returns a MappingRecord which has the more specific EID, and intersection of locator records.
         // If locators intersection is empty, original NB mapping is returned.
         // The intersection is only computed for mappings with maskable EIDs.
@@ -228,26 +249,28 @@ public final class MappingMergeUtil {
             short sbMask = MaskUtil.getMaskForAddress(sbMapping.getEid().getAddress());
             short nbMask = MaskUtil.getMaskForAddress(nbMapping.getEid().getAddress());
 
-            if (nbMapping.getEid().getAddress() instanceof SourceDestKey) {
+            if (nbMapping.getEid().getAddress() instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
+                    .ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey) {
                 nbMask = SourceDestKeyHelper.getDstMask(nbMapping.getEid());
-                if ( nbMask < sbMask) {
+                if (nbMask < sbMask) {
                     // We have to create a new SourceDest EID, where the source is same as the
                     // one in NB record, and dest EID is the more specific from SB mapping record.
 
-                    SourceDestKeyBuilder sdb = new SourceDestKeyBuilder(
-                            ((SourceDestKey) nbMapping.getEid().getAddress()));
-                    sdb.setDest(new SimpleAddress ((IpPrefix) sbMapping.getEid().getAddress()));
+                    SourceDestKey srcDstKey = ((org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp
+                            .address.types.rev151105.lisp.address.address.SourceDestKey) nbMapping.getEid()
+                            .getAddress()).getSourceDestKey();
+                    SourceDestKeyBuilder sdb = new SourceDestKeyBuilder(srcDstKey);
+                    sdb.setDest(new SimpleAddress(getIpPrefix(sbMapping.getEid().getAddress())));
                     mrb.setEid(LispAddressUtil.asSrcDstEid(sdb.build(), nbMapping.getEid().getVirtualNetworkId()));
                 }
             } else if (nbMask < sbMask) {
                 // Both EIDs are IP prefixes. SB mapping is a subprefix so we have to update EID intersection
                 mrb.setEid(sbMapping.getEid());
-                mrb.setMaskLength(sbMask);
             }
         }
         // find and update locators intersection if not empty
         List<LocatorRecord> commonLocators = getCommonLocatorRecords(nbMapping, sbMapping);
-        if (!commonLocators.isEmpty()) {
+        if (commonLocators != null && !commonLocators.isEmpty()) {
             mrb.setLocatorRecord(commonLocators);
         }
 
@@ -259,6 +282,11 @@ public final class MappingMergeUtil {
         // from the two mappings. NB mapping records fields have precedence, only Priority is updated
         // from SB mapping if p is 255.
 
+        // Return null when NB is a negative mapping
+        if (nbMapping.getLocatorRecord() == null || nbMapping.getLocatorRecord().isEmpty()) {
+            return null;
+        }
+
         List<LocatorRecord> sbLocators = sbMapping.getLocatorRecord();
 
         // We assume locators are unique and don't show up several times (with different or identical p/w/mp/mw),
@@ -276,11 +304,11 @@ public final class MappingMergeUtil {
             if (sbLocatorMap.containsKey(nbRloc)) {
                 // common locator found. use the NB record as the common locator.
 
-                if (sbLocatorMap.get(nbRloc).getPriority() == (short) 255) {
+                if (sbLocatorMap.get(nbRloc).getPriority().toJava() == (short) 255) {
                     // if SB locator has p == 255 then common locator takes all NB fields except for p
                     // which must be set to 255
                     LocatorRecordBuilder lrb = new LocatorRecordBuilder(nbLocator);
-                    lrb.setPriority((short) 255);
+                    lrb.setPriority(fromJava((short) 255));
                     commonLocators.add(lrb.build());
                 } else {
                     commonLocators.add(nbLocator);
@@ -290,4 +318,28 @@ public final class MappingMergeUtil {
         return commonLocators;
     }
 
+    private static IpPrefix getIpPrefix(Address address) {
+        IpPrefix ipPrefix = null;
+
+        if (address instanceof org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns
+                .yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix) {
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp
+                    .address.address.Ipv4Prefix lispPrefix = (org.opendaylight.yang.gen.v1.urn.ietf.params
+                    .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix) address;
+
+            Ipv4Prefix inetPrefix = new Ipv4Prefix(lispPrefix.getIpv4Prefix());
+            ipPrefix = new IpPrefix(inetPrefix);
+        } else if (address instanceof org.opendaylight.yang.gen.v1.urn.ietf.params
+                .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix) {
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp
+                    .address.address.Ipv6Prefix lispPrefix = (org.opendaylight.yang.gen.v1.urn.ietf.params
+                    .xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix) address;
+
+            Ipv6Prefix inetPrefix = new Ipv6Prefix(lispPrefix.getIpv6Prefix());
+            ipPrefix = new IpPrefix(inetPrefix);
+        } else {
+            LOG.warn("Southbound mapping address is not an IpPrefix");
+        }
+        return ipPrefix;
+    }
 }