Bug 5270: Fix merging 71/34271/6
authorFlorin Coras <fcoras@cisco.com>
Mon, 8 Feb 2016 17:01:46 +0000 (18:01 +0100)
committerFlorin Coras <fcoras@cisco.com>
Mon, 8 Feb 2016 23:36:09 +0000 (00:36 +0100)
1) Fix merge bit parsing in Map-Register/Notify
2) Sort locators in merged mapping record

Change-Id: I25047d1e39f1f4277e8d92bb9611f42b5876f178
Signed-off-by: Florin Coras <fcoras@cisco.com>
12 files changed:
mappingservice/api/src/main/java/org/opendaylight/lispflowmapping/interfaces/mapcache/IMappingSystem.java
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/MappingService.java
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/MappingSystem.java
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/lisp/MapServer.java
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/mapcache/SimpleMapCache.java
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/util/MappingMergeUtil.java
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/serializer/MapNotifySerializer.java
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/serializer/MapRegisterSerializer.java
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/util/LispAddressUtil.java
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/util/MapNotifyBuilderHelper.java
mappingservice/lisp-proto/src/main/yang/odl-lisp-proto.yang
mappingservice/southbound/src/main/java/org/opendaylight/lispflowmapping/southbound/util/LispNotificationHelper.java

index 95f93b4b0f22a82754363658e3e0a3b779aac738..57c5faa216a4bfd9c7a80fe5f2d0eec467e00363 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.lispflowmapping.interfaces.mapcache;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.SiteId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
 
 /**
@@ -33,20 +32,6 @@ public interface IMappingSystem {
      */
     void addMapping(MappingOrigin origin, Eid key, Object data);
 
-    /**
-     * Add mapping and persist to datastore
-     *
-     * @param origin
-     *            Table where mapping should be added
-     * @param siteId
-     *            SiteID of SB device doing the registration
-     * @param key
-     *            Key of the mapping
-     * @param data
-     *            Value to be stored
-     */
-    void addMapping(MappingOrigin origin, SiteId siteId, Eid key, Object data);
-
     /**
      * Retrieves mapping for the provided src and dst key.
      *
index 9d677b1269f1e440bbe25653406f6941218bc23d..1aa6bd5875a502bd5563cc366c3b5f6e2c2dfa2c 100644 (file)
@@ -358,7 +358,10 @@ public class MappingService implements OdlMappingserviceService, IMappingService
     public void addMapping(MappingOrigin origin, Eid key, SiteId siteId, Object data) {
         // SB registrations are first written to the MappingSystem and only afterwards are persisted to the datastore
         if (origin.equals(MappingOrigin.Southbound)) {
-            mappingSystem.addMapping(origin, siteId, key, data);
+            // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
+            // registrations
+            mappingSystem.addMapping(origin, key, data);
+            dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
         } else {
             dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
         }
index fbb63dd72b52094b16c46933d26d21236b0af39f..3f5fd1c8fa88dbd8452d2075874093e67b38306b 100644 (file)
@@ -18,7 +18,6 @@ import org.opendaylight.lispflowmapping.implementation.mapcache.FlatMapCache;
 import org.opendaylight.lispflowmapping.implementation.mapcache.MultiTableMapCache;
 import org.opendaylight.lispflowmapping.implementation.mapcache.SimpleMapCache;
 import org.opendaylight.lispflowmapping.implementation.mdsal.DataStoreBackEnd;
-import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
 import org.opendaylight.lispflowmapping.implementation.util.MappingMergeUtil;
 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
@@ -38,7 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.ma
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.SiteId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.authkey.container.MappingAuthkey;
@@ -109,13 +107,6 @@ public class MappingSystem implements IMappingSystem {
         tableMap.put(MappingOrigin.Southbound, smc);
     }
 
-    public void addMapping(MappingOrigin origin, SiteId siteId, Eid key, Object data) {
-        // Store data first in MapCache and only afterwards persist to datastore. This should be used only for SB
-        // registrations
-        addMapping(origin, key, data);
-        dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (MappingRecord) data));
-    }
-
     public void addMapping(MappingOrigin origin, Eid key, Object value) {
         tableMap.get(origin).addMapping(key, value, origin == MappingOrigin.Southbound ? overwrite : true);
     }
index a8f5ba0ad80106f09c42f56119775b0463c8c101..2fcc0634ac17e1dbe411a3eb8e4b791632f4f3ec 100644 (file)
@@ -12,7 +12,6 @@ import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
@@ -101,6 +100,7 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener {
     @SuppressWarnings("unchecked")
     public void handleMapRegister(MapRegister mapRegister) {
         boolean authFailed = false;
+        boolean mappingUpdated = false;
         String password = null;
         Set<SubscriberRLOC> subscribers = null;
         MappingRecord oldMapping;
@@ -118,12 +118,14 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener {
                     break;
                 }
             }
+
             oldMapping = (MappingRecord) mapService.getMapping(MappingOrigin.Southbound, mapping.getEid());
             mapService.addMapping(MappingOrigin.Southbound, mapping.getEid(), getSiteId(mapRegister), mapping);
 
             if (subscriptionService) {
-                MappingRecord newMapping = ConfigIni.getInstance().mappingMergeIsSet()
-                        ? (MappingRecord) mapService.getMapping(MappingOrigin.Southbound, mapping.getEid()) : mapping;
+                MappingRecord newMapping = ConfigIni.getInstance().mappingMergeIsSet() ?
+                        (MappingRecord) mapService.getMapping(MappingOrigin.Southbound, mapping.getEid()) : mapping;
+
                 if (mappingChanged(oldMapping, newMapping)) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Mapping update occured for {} SMRs will be sent for its subscribers.",
@@ -131,6 +133,7 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener {
                     }
                     subscribers = getSubscribers(mapping.getEid());
                     sendSmrs(mapping, subscribers);
+                    mappingUpdated = true;
                 }
             }
         }
@@ -153,7 +156,10 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener {
                     }
                 }
                 MapNotifyBuilderHelper.setFromMapRegisterAndMappingRecordItems(builder, mapRegister, mergedMappings);
-                rlocs = getTransportAddresses(notifyRlocs);
+                // send map-notify to merge group only when mapping record is changed
+                if (mappingUpdated) {
+                    rlocs = getTransportAddresses(notifyRlocs);
+                }
             } else {
                 MapNotifyBuilderHelper.setFromMapRegister(builder, mapRegister);
             }
@@ -209,12 +215,6 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener {
         } else if (!Objects.equals(oldMapping.getRecordTtl(), newMapping.getRecordTtl())) {
             LOG.trace("mappingChanged(): TTL");
             return true;
-        } else if (!Arrays.equals(oldMapping.getXtrId(), newMapping.getXtrId())) {
-            LOG.trace("mappingChanged(): xTR-ID");
-            return true;
-        } else if (!Arrays.equals(oldMapping.getSiteId(), newMapping.getSiteId())) {
-            LOG.trace("mappingChanged(): site-ID");
-            return true;
         } else if (!Objects.equals(oldMapping.getMapVersion(), newMapping.getMapVersion())) {
             LOG.trace("mappingChanged(): mapping version");
             return true;
index 0755030cca97dd712f355a498c25ed8b06d53e7b..1b14d5fe9408949bebd5bb777236e1b2c0b1d058 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.lispflowmapping.implementation.mapcache;
 
 import java.util.AbstractMap.SimpleImmutableEntry;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashSet;
@@ -83,9 +84,13 @@ public class SimpleMapCache implements IMapCache {
         return table;
     }
 
+    public static Object deserializeBytes(byte[] data) {
+        return ByteBuffer.wrap(data);
+    }
+
     private void removeExpiredXtrIdTableEntries(ILispDAO xtrIdDao, List<byte[]> expiredMappings) {
         for (byte[] xtrId : expiredMappings) {
-            xtrIdDao.removeSpecific(xtrId, SubKeys.RECORD);
+            xtrIdDao.removeSpecific(deserializeBytes(xtrId), SubKeys.RECORD);
         }
     }
 
@@ -113,7 +118,7 @@ public class SimpleMapCache implements IMapCache {
         ILispDAO xtrIdDao = null;
         if (!shouldOverwrite) {
             xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
-            xtrIdDao.put(record.getXtrId(), new MappingEntry<>(SubKeys.RECORD, value));
+            xtrIdDao.put(deserializeBytes(record.getXtrId()), new MappingEntry<>(SubKeys.RECORD, value));
         }
 
         if (ConfigIni.getInstance().mappingMergeIsSet()) {
index fcd88f08b91e0e703e07a6f2106cb7e3999f3f0e..63f132c1cbf64ee1f67b5a8d3d04a20d69acf881 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.lispflowmapping.implementation.util;
 
+import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.LinkedHashMap;
@@ -72,50 +73,71 @@ 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 void mergeLocatorRecords(MappingRecordBuilder mrb, MappingRecord newRecord) {
         List<LocatorRecord> locators = mrb.getLocatorRecord();
 
-        // Optimization: unless we had to merge any of the locators due to differences in weights, etc, we return
-        // the original 'locators' List with any new locators added
-        boolean mergeHappened = false;
-
-        // We assume locators are unique and don't show up several times (with different or identical p/w/mp/mw),
-        // so we create a LinkedHashMap (which preserves order) of the locators from the existing merged record,
-        // keyed by the Rloc
+        // We assume locators are unique and sorted and don't show up several times (with different or identical
+        // p/w/mp/mw), so we create a LinkedHashMap (which preserves order) of the locators from the existing merged
+        // record, keyed by the Rloc
         Map<Rloc, LocatorRecord> locatorMap = new LinkedHashMap<Rloc, LocatorRecord>();
+
+        // All locators to be added to the merge set are first stored in this list
+        List<LocatorRecord> newLocatorList = new ArrayList<LocatorRecord>();
+
         for (LocatorRecord locator : locators) {
             locatorMap.put(locator.getRloc(), locator);
         }
         for (LocatorRecord newLocator : newRecord.getLocatorRecord()) {
             Rloc newRloc = newLocator.getRloc();
             if (locatorMap.containsKey(newRloc)) {
-                // XXX  LocatorRecord YANG generated class doesn't override equals() so I'm not sure of the behavior
-                // here, need to verify if it works as expected
+                // overlapping locator
                 if (locatorMap.get(newRloc).equals(newLocator)) {
                     continue;
                 } else {
                     LocatorRecord mergedLocator = mergeLocators(locatorMap.get(newRloc), newLocator);
-                    locatorMap.put(newRloc, mergedLocator);
-                    mergeHappened = true;
+                    newLocatorList.add(mergedLocator);
                 }
             } else {
-                // We add both the LinkedHanshMap and the List, in case we can return the original list plus new
-                // elements and need not generate a new list with merged locators (which should be the most common
-                // scenario).
-                locatorMap.put(newRloc, newLocator);
-                locators.add(newLocator);
+                // new locator
+                newLocatorList.add(newLocator);
             }
         }
 
-        if (mergeHappened) {
+        // Build new merged and sorted locator set if need be
+        if (newLocatorList.size() != 0) {
             List<LocatorRecord> mergedLocators = new ArrayList<LocatorRecord>();
-            for (Map.Entry<Rloc, LocatorRecord> entry : locatorMap.entrySet()) {
-                mergedLocators.add(entry.getValue());
+
+            int mlIt = 0, lIt = 0;
+            while (mlIt < newLocatorList.size() && lIt < locators.size()) {
+                int cmp = compareLocators(locators.get(lIt), newLocatorList.get(mlIt));
+                if (cmp < 0) {
+                    mergedLocators.add(locators.get(lIt));
+                    lIt++;
+                } else if (cmp > 0) {
+                    mergedLocators.add(newLocatorList.get(mlIt));
+                    mlIt++;
+                } else {
+                    // when a locator appears in both lists, keep the new (merged) one and skip the old
+                    mergedLocators.add(newLocatorList.get(mlIt));
+                    mlIt++;
+                    lIt++;
+                }
+            }
+            while (lIt < locators.size()) {
+                mergedLocators.add(locators.get(lIt));
+                lIt++;
+            }
+            while (mlIt < newLocatorList.size()) {
+                mergedLocators.add(newLocatorList.get(mlIt));
+                mlIt++;
             }
             mrb.setLocatorRecord(mergedLocators);
-        } else {
-            // TODO  Check if this is necessary after and .add() was called on locators
-            mrb.setLocatorRecord(locators);
         }
     }
 
@@ -139,11 +161,11 @@ public final class MappingMergeUtil {
 
     public static MappingRecord mergeXtrIdMappings(List<Object> records, List<byte[]> expiredMappings,
             Set<IpAddress> sourceRlocs) {
-        MappingRecordBuilder mrb = new MappingRecordBuilder((MappingRecord) records.get(0));
-        byte[] xtrId = mrb.getXtrId();
-        Long timestamp = mrb.getTimestamp();
+        MappingRecordBuilder mrb = null;
+        byte[] xtrId = {};
+        Long timestamp = Long.MAX_VALUE;
 
-        for (int i = 1; i < records.size(); i++) {
+        for (int i = 0; i < records.size(); i++) {
             MappingRecord record = (MappingRecord) records.get(i);
 
             // Skip expired mappings and add them to a list to be returned to the caller
@@ -152,6 +174,10 @@ public final class MappingMergeUtil {
                 continue;
             }
 
+            if (mrb == null) {
+                mrb = new MappingRecordBuilder((MappingRecord) records.get(i));
+            }
+
             // Save the oldest valid timestamp
             if (record.getTimestamp() < timestamp) {
                 timestamp = record.getTimestamp();
@@ -165,6 +191,10 @@ public final class MappingMergeUtil {
             // Save source locator for use in Map-Notify
             sourceRlocs.add(record.getSourceRloc());
         }
+
+        if (mrb == null) {
+            LOG.warn("All mappings expired when merging! Unexpected!");
+        }
         mrb.setXtrId(xtrId);
         mrb.setTimestamp(timestamp);
 
index 166d4f45b1ddb77e2499c5649f18116a40a7a645..ef64528a45e5967345a7c56f05bccc2b3e977c14 100644 (file)
@@ -11,6 +11,7 @@ import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.lang3.BooleanUtils;
 import org.opendaylight.lispflowmapping.lisp.serializer.exception.LispSerializationException;
 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
 import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
@@ -52,6 +53,7 @@ public final class MapNotifySerializer {
         ByteBuffer replyBuffer = ByteBuffer.allocate(size);
         replyBuffer.put((byte) (MessageType.MapNotify.getIntValue() << 4));
         replyBuffer.position(replyBuffer.position() + Length.RES);
+        replyBuffer.put(ByteUtil.boolToBit(BooleanUtils.isTrue(mapNotify.isMergeEnabled()), Flags.MERGE_ENABLED));
         if (mapNotify.getMappingRecordItem() != null) {
             replyBuffer.put((byte) mapNotify.getMappingRecordItem().size());
         } else {
@@ -90,6 +92,7 @@ public final class MapNotifySerializer {
             builder.setXtrSiteIdPresent(xtrSiteIdPresent);
 
             notifyBuffer.position(notifyBuffer.position() + Length.RES);
+            builder.setMergeEnabled(ByteUtil.extractBit(notifyBuffer.get(), Flags.MERGE_ENABLED));
 
             byte recordCount = (byte) ByteUtil.getUnsignedByte(notifyBuffer);
             builder.setNonce(notifyBuffer.getLong());
@@ -132,11 +135,12 @@ public final class MapNotifySerializer {
 
     private interface Flags {
         byte XTRSITEID = 0x08;
+        byte MERGE_ENABLED = 0x04;
     }
 
     private interface Length {
         int HEADER_SIZE = 16;
-        int RES = 2;
+        int RES = 1;
     }
 
 }
index 673350ac288f4738272fac95349c65af48fdab92..bfe398d75a2ce99119c15a6ee3b27b62360b88ac 100644 (file)
@@ -59,7 +59,9 @@ public final class MapRegisterSerializer {
                 ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isProxyMapReply()), Flags.PROXY) |
                 ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isXtrSiteIdPresent()), Flags.XTRSITEID)));
         registerBuffer.position(registerBuffer.position() + Length.RES);
-        registerBuffer.put(ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isWantMapNotify()), Flags.WANT_MAP_REPLY));
+        registerBuffer.put((byte)
+                (ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isMergeEnabled()), Flags.MERGE_ENABLED) |
+                ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isWantMapNotify()), Flags.WANT_MAP_NOTIFY)));
         registerBuffer.put((byte) mapRegister.getMappingRecordItem().size());
         registerBuffer.putLong(NumberUtil.asLong(mapRegister.getNonce()));
         registerBuffer.putShort(NumberUtil.asShort(mapRegister.getKeyId()));
@@ -93,7 +95,9 @@ public final class MapRegisterSerializer {
             builder.setXtrSiteIdPresent(xtrSiteIdPresent);
 
             registerBuffer.position(registerBuffer.position() + Length.RES);
-            builder.setWantMapNotify(ByteUtil.extractBit(registerBuffer.get(), Flags.WANT_MAP_REPLY));
+            byte mergeAndMapReply = registerBuffer.get();
+            builder.setWantMapNotify(ByteUtil.extractBit(mergeAndMapReply, Flags.WANT_MAP_NOTIFY));
+            builder.setMergeEnabled(ByteUtil.extractBit(mergeAndMapReply, Flags.MERGE_ENABLED));
             byte recordCount = (byte) ByteUtil.getUnsignedByte(registerBuffer);
             builder.setNonce(registerBuffer.getLong());
             builder.setKeyId(registerBuffer.getShort());
@@ -153,7 +157,8 @@ public final class MapRegisterSerializer {
     private interface Flags {
         byte PROXY = 0x08;
         byte XTRSITEID = 0x02;
-        byte WANT_MAP_REPLY = 0x01;
+        byte MERGE_ENABLED = 0x04;
+        byte WANT_MAP_NOTIFY = 0x01;
     }
 
     public interface Length {
index b59fa83ca9c7310b625b8467dd5807527c5534ee..0854d6318f27f5bfb8027389c8d262c6cc6c30c0 100644 (file)
@@ -42,8 +42,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.addres
 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.AsNumberBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.DistinguishedNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Builder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Builder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6PrefixBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.KeyValueAddress;
@@ -536,4 +538,49 @@ public final class LispAddressUtil {
         builder.setAddress(new NoAddressBuilder().setNoAddress(true).build());
         return builder.build();
     }
+
+    public static InetAddress ipAddressToInet(Address addr) {
+        try {
+            if (addr instanceof Ipv4) {
+                return Inet4Address.getByName(((Ipv4) addr).getIpv4().getValue());
+            } else if (addr instanceof Ipv6) {
+                return Inet6Address.getByName(((Ipv6) addr).getIpv6().getValue());
+            }
+        } catch (java.net.UnknownHostException e) {
+            LOG.debug("Failed to build InetAddress: {}", e);
+        }
+        return null;
+    }
+
+    public static int compareInetAddresses(InetAddress a, InetAddress b) {
+        int i;
+        if (a instanceof Inet4Address && b instanceof Inet6Address) {
+            return -1;
+        } else if (a instanceof Inet6Address && b instanceof Inet4Address) {
+            return 1;
+        } else if (a instanceof Inet4Address && b instanceof Inet4Address) {
+            byte[] aBytes = ((Inet4Address) a).getAddress();
+            byte[] bBytes = ((Inet4Address) b).getAddress();
+            for (i = 0; i < 4; i++) {
+                if (aBytes[i] < bBytes[i]) {
+                    return -1;
+                } else if (aBytes[i] > bBytes[i]) {
+                    return 1;
+                }
+            }
+            return 0;
+        } else if (a instanceof Inet6Address && b instanceof Inet6Address) {
+            byte[] aBytes = ((Inet4Address) a).getAddress();
+            byte[] bBytes = ((Inet4Address) b).getAddress();
+            for (i = 0; i < 16; i++) {
+                if (aBytes[i] < bBytes[i]) {
+                    return -1;
+                } else if (aBytes[i] > bBytes[i]) {
+                    return 1;
+                }
+            }
+            return 0;
+        }
+        return 0;
+    }
 }
index 9400f1adfcc74c964dae6db6c9055a865bb5a71c..d2c35a4d07805967e3fb5f62fcc94550450b5bef 100644 (file)
@@ -41,6 +41,8 @@ public final class MapNotifyBuilderHelper {
     private static void setNonRecordFields(MapNotifyBuilder builder, MapRegister mapRegister) {
         builder.setNonce(mapRegister.getNonce());
         builder.setKeyId(mapRegister.getKeyId());
+        builder.setMergeEnabled(mapRegister.isMergeEnabled());
+
         byte[] authenticationData = mapRegister.getAuthenticationData();
         if (authenticationData != null) {
             authenticationData = authenticationData.clone();
index 935a7c450727f3deb170fd9acf5f6defa590d8bc..58bf372611c9937ec6c9a373966a3c8275f548a4 100644 (file)
@@ -225,6 +225,9 @@ module odl-lisp-proto {
         leaf authenticationData {
             type binary;
         }
+        leaf mergeEnabled {
+            type boolean;
+        }
         uses mapping-record-list;
         uses xtrSiteId;
     }
@@ -243,6 +246,9 @@ module odl-lisp-proto {
         leaf authenticationData {
             type binary;
         }
+        leaf mergeEnabled {
+            type boolean;
+        }
         uses mapping-record-list;
         uses xtrSiteId;
     }
index 51aa82e9d5cfdbc7bb4f4612a1a47af7da50d58b..14a3059dd26abc499e85a3b882d82d76201fb7f8 100644 (file)
@@ -29,19 +29,12 @@ public final class LispNotificationHelper {
 
     public static MapRegister convertMapRegister(
             org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRegister mapRegister) {
-        return new MapRegisterBuilder().setAuthenticationData(mapRegister.getAuthenticationData())
-                .setMappingRecordItem(mapRegister.getMappingRecordItem()).setKeyId(mapRegister.getKeyId())
-                .setNonce(mapRegister.getNonce()).setProxyMapReply(mapRegister.isProxyMapReply())
-                .setWantMapNotify(mapRegister.isWantMapNotify()).setXtrSiteIdPresent(mapRegister.isXtrSiteIdPresent())
-                .setXtrId(mapRegister.getXtrId()).setSiteId(mapRegister.getSiteId()).build();
+        return new MapRegisterBuilder(mapRegister).build();
     }
 
     public static MapNotify convertMapNotify(
             org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapNotify mapNotify) {
-        return new MapNotifyBuilder().setAuthenticationData(mapNotify.getAuthenticationData())
-                .setMappingRecordItem(mapNotify.getMappingRecordItem()).setKeyId(mapNotify.getKeyId())
-                .setNonce(mapNotify.getNonce()).setXtrSiteIdPresent(mapNotify.isXtrSiteIdPresent())
-                .setXtrId(mapNotify.getXtrId()).setSiteId(mapNotify.getSiteId()).build();
+        return new MapNotifyBuilder(mapNotify).build();
     }
 
     public static MapRequest convertMapRequest(