Merge "Provide Karaf 4 features"
authorVina Ermagan <vermagan@cisco.com>
Thu, 16 Mar 2017 18:22:18 +0000 (18:22 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 16 Mar 2017 18:22:18 +0000 (18:22 +0000)
14 files changed:
mappingservice/api/src/main/java/org/opendaylight/lispflowmapping/interfaces/mapcache/ILispMapCache.java
mappingservice/api/src/main/java/org/opendaylight/lispflowmapping/interfaces/mapcache/IMappingSystem.java
mappingservice/api/src/main/java/org/opendaylight/lispflowmapping/interfaces/mappingservice/IMappingService.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/MapResolver.java
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/lisp/MapServer.java
mappingservice/implementation/src/test/java/org/opendaylight/lispflowmapping/implementation/MappingSystemTest.java
mappingservice/implementation/src/test/java/org/opendaylight/lispflowmapping/implementation/lisp/MapResolverTest.java
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/type/LispMessage.java
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/type/MappingData.java
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/util/MappingRecordUtil.java [new file with mode: 0644]
mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/util/MaskUtil.java
mappingservice/mapcache/src/main/java/org/opendaylight/lispflowmapping/mapcache/SimpleMapCache.java

index af703e7a7bafde9bde62ec101e0ca62e16550e8d..0a745dfeb3c361da2c72e7f5382d82e297da0bd7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2016, 2017 Cisco Systems, Inc.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -93,8 +93,26 @@ public interface ILispMapCache extends IMapCache {
      * Returns the parent prefix for given key.
      *
      * @param key
-     *            The key which parent is to be returned.
-     * @return The parent perfix of a specific key.
+     *            The key for which parent is to be returned.
+     * @return The parent prefix of a specific key.
      */
     Eid getParentPrefix(Eid key);
+
+    /**
+     * Returns the sibling prefix for given key.
+     *
+     * @param key
+     *            The key for which sibling is to be returned.
+     * @return The sibling prefix of a specific key.
+     */
+    Eid getSiblingPrefix(Eid key);
+
+    /**
+     * Returns the virtual parent sibling prefix for given key.
+     *
+     * @param key
+     *            The key for which virtual parent sibling is to be returned.
+     * @return The virtual parent sibling prefix of a specific key.
+     */
+    Eid getVirtualParentSiblingPrefix(Eid key);
 }
index b617efe3321de8171b1f522404f852438ca8351c..9aa641ec5f5c884f64aa329a8ab4dd5f96e8c094 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -34,6 +34,15 @@ public interface IMappingSystem {
      */
     void addMapping(MappingOrigin origin, Eid key, MappingData mapping);
 
+    /**
+     * Generate and add a negative mapping entry originated from the southbound, and return the generated mapping.
+     *
+     * @param key
+     *            Key of the mapping
+     * @return Returns the generated negative mapping (which is never null).
+     */
+    MappingData addNegativeMapping(Eid key);
+
     /**
      * Retrieves mapping for the provided src and dst key.
      *
index df53aa3c053e3112e66a4f6efbf42f729f66f667..e917a97896d327138b5175c4596e2afaf61d2bfd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -40,6 +40,15 @@ public interface IMappingService {
      */
     void addMapping(MappingOrigin origin, Eid key, SiteId siteId, MappingData mapping);
 
+    /**
+     * Generate and add a negative mapping entry originated from the southbound, and return the generated mapping.
+     *
+     * @param key
+     *            Key of the mapping
+     * @return Returns the generated negative mapping (which is never null).
+     */
+    MappingData addNegativeMapping(Eid key);
+
     /**
      * Retrieves mapping with given origin for the provided key. The lookup policy for the key is defined in the Mapping
      * System.
index a60c8a0107166d1ce4e79293bc98e3d2979d3611..6bce0e86663d8340f38a663682acc04b868b1548 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -126,7 +126,7 @@ public class MappingService implements OdlMappingserviceService, IMappingService
         LOG.info("Mapping Service initializing...");
         dsbe = new DataStoreBackEnd(dataBroker);
 
-        mappingSystem = new MappingSystem(dao, iterateMask, notificationPolicy, mappingMergePolicy);
+        mappingSystem = new MappingSystem(dao, iterateMask, notificationPublishService, mappingMergePolicy);
         mappingSystem.setDataStoreBackEnd(dsbe);
         mappingSystem.initialize();
 
@@ -187,6 +187,11 @@ public class MappingService implements OdlMappingserviceService, IMappingService
         }
     }
 
+    @Override
+    public MappingData addNegativeMapping(Eid key) {
+        return mappingSystem.addNegativeMapping(key);
+    }
+
     @Override
     public void refreshMappingRegistration(Eid key, XtrId xtrId, Long timestamp) {
         mappingSystem.refreshMappingRegistration(key, xtrId, timestamp);
index 3446930da7b84be1c409bde73c528247f39e6bb4..9005491813ded5773f1c3c0c447a578ac6bd089e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,30 +8,35 @@
 
 package org.opendaylight.lispflowmapping.implementation;
 
+import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.EnumMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.lispflowmapping.config.ConfigIni;
 import org.opendaylight.lispflowmapping.dsbackend.DataStoreBackEnd;
 import org.opendaylight.lispflowmapping.implementation.timebucket.implementation.TimeBucketMappingTimeoutService;
 import org.opendaylight.lispflowmapping.implementation.timebucket.interfaces.ISouthBoundMappingTimeoutService;
 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
+import org.opendaylight.lispflowmapping.implementation.util.MSNotificationInputUtil;
 import org.opendaylight.lispflowmapping.implementation.util.MappingMergeUtil;
 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
+import org.opendaylight.lispflowmapping.interfaces.dao.Subscriber;
 import org.opendaylight.lispflowmapping.interfaces.mapcache.IAuthKeyDb;
 import org.opendaylight.lispflowmapping.interfaces.mapcache.ILispMapCache;
 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMapCache;
 import org.opendaylight.lispflowmapping.interfaces.mapcache.IMappingSystem;
 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
+import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
+import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
 import org.opendaylight.lispflowmapping.mapcache.AuthKeyDb;
 import org.opendaylight.lispflowmapping.mapcache.MultiTableMapCache;
 import org.opendaylight.lispflowmapping.mapcache.SimpleMapCache;
@@ -42,13 +47,19 @@ 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.ServicePath;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.Ipv4PrefixBinaryAfi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.Ipv6PrefixBinaryAfi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv4PrefixBinary;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv6PrefixBinary;
 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.eid.container.Eid;
 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.authkey.container.MappingAuthkey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
 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.MappingChange;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
 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;
@@ -60,12 +71,15 @@ import org.slf4j.LoggerFactory;
  * mapping lookups.
  *
  * @author Florin Coras
+ * @author Lorand Jakab
  *
  */
 public class MappingSystem implements IMappingSystem {
     private static final Logger LOG = LoggerFactory.getLogger(MappingSystem.class);
     private static final String AUTH_KEY_TABLE = "authentication";
-    private boolean notificationService;
+    private static final int TTL_RLOC_TIMED_OUT = 1;
+    private static final int TTL_NO_RLOC_KNOWN = 15;
+    private NotificationPublishService notificationPublishService;
     private boolean mappingMerge;
     private ILispDAO dao;
     private ILispDAO sdao;
@@ -78,9 +92,9 @@ public class MappingSystem implements IMappingSystem {
 
     private ISouthBoundMappingTimeoutService sbMappingTimeoutService;
 
-    public MappingSystem(ILispDAO dao, boolean iterateMask, boolean notifications, boolean mappingMerge) {
+    public MappingSystem(ILispDAO dao, boolean iterateMask, NotificationPublishService nps, boolean mappingMerge) {
         this.dao = dao;
-        this.notificationService = notifications;
+        this.notificationPublishService = nps;
         this.mappingMerge = mappingMerge;
         buildMapCaches();
 
@@ -181,6 +195,36 @@ public class MappingSystem implements IMappingSystem {
         smc.addData(key, SubKeys.TIME_BUCKET_ID, updatedBucketId);
     }
 
+    @Override
+    public MappingData addNegativeMapping(Eid key) {
+        MappingRecord mapping = buildNegativeMapping(key);
+        MappingData mappingData = new MappingData(mapping);
+        smc.addMapping(mapping.getEid(), mappingData);
+        dsbe.addMapping(DSBEInputUtil.toMapping(MappingOrigin.Southbound, mapping.getEid(), null, mappingData));
+        return mappingData;
+    }
+
+    private MappingRecord buildNegativeMapping(Eid eid) {
+        MappingRecordBuilder recordBuilder = new MappingRecordBuilder();
+        recordBuilder.setAuthoritative(false);
+        recordBuilder.setMapVersion((short) 0);
+        recordBuilder.setEid(eid);
+        if (eid.getAddressType().equals(Ipv4PrefixBinaryAfi.class)
+                || eid.getAddressType().equals(Ipv6PrefixBinaryAfi.class)) {
+            Eid widestNegativePrefix = getWidestNegativePrefix(eid);
+            if (widestNegativePrefix != null) {
+                recordBuilder.setEid(widestNegativePrefix);
+            }
+        }
+        recordBuilder.setAction(LispMessage.NEGATIVE_MAPPING_ACTION);
+        if (getAuthenticationKey(eid) != null) {
+            recordBuilder.setRecordTtl(TTL_RLOC_TIMED_OUT);
+        } else {
+            recordBuilder.setRecordTtl(TTL_NO_RLOC_KNOWN);
+        }
+        return recordBuilder.build();
+    }
+
     /*
      * Since this method is only called when there is a hit in the southbound Map-Register cache, and that cache is
      * not used when merge is on, it's OK to ignore the effects of timestamp changes on merging for now.
@@ -407,13 +451,75 @@ public class MappingSystem implements IMappingSystem {
 
     @Override
     public void removeMapping(MappingOrigin origin, Eid key) {
+        Set<Subscriber> subscribers = null;
         if (origin == MappingOrigin.Southbound) {
             removeFromSbTimeoutService(key);
+            MappingData mapping = (MappingData) smc.getMapping(null, key);
+            if (mapping != null && !mapping.isNegative()) {
+                SimpleImmutableEntry<Eid, Set<Subscriber>> mergedNegativePrefix = computeMergedNegativePrefix(key);
+                if (mergedNegativePrefix != null) {
+                    addNegativeMapping(mergedNegativePrefix.getKey());
+                    subscribers = mergedNegativePrefix.getValue();
+                    try {
+                        notificationPublishService.putNotification(
+                                MSNotificationInputUtil.toMappingChanged(mapping, subscribers, MappingChange.Created));
+                    } catch (InterruptedException e) {
+                        LOG.warn("Notification publication interrupted!");
+                    }
+                }
+            }
         }
         tableMap.get(origin).removeMapping(key);
-        if (notificationService) {
-            // TODO
+    }
+
+    @SuppressWarnings("unchecked")
+    /*
+     * Returns the "merged" prefix and the subscribers of the prefixes that were merged.
+     */
+    private SimpleImmutableEntry<Eid, Set<Subscriber>> computeMergedNegativePrefix(Eid eid) {
+        // Variable to hold subscribers we collect along the way
+        Set<Subscriber> subscribers = null;
+
+        // If prefix sibling has a negative mapping, save its subscribers
+        Eid sibling = smc.getSiblingPrefix(eid);
+        MappingData mapping = (MappingData) smc.getMapping(null, sibling);
+        if (mapping != null && mapping.isNegative()) {
+            subscribers = (Set<Subscriber>) getData(MappingOrigin.Southbound, eid, SubKeys.SUBSCRIBERS);
+        } else {
+            return null;
+        }
+
+        Eid currentNode = sibling;
+        Eid previousNode = sibling;
+        while ((currentNode = smc.getVirtualParentSiblingPrefix(currentNode)) != null) {
+            mapping = (MappingData) smc.getMapping(null, currentNode);
+            if (mapping != null && mapping.isNegative()) {
+                subscribers.addAll((Set<Subscriber>)
+                        getData(MappingOrigin.Southbound, currentNode, SubKeys.SUBSCRIBERS));
+                removeSbMapping(currentNode, mapping);
+            } else {
+                break;
+            }
+            previousNode = currentNode;
+        }
+        return new SimpleImmutableEntry<>(getVirtualParent(previousNode), subscribers);
+    }
+
+    private static Eid getVirtualParent(Eid eid) {
+        if (eid.getAddress() instanceof Ipv4PrefixBinary) {
+            Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) eid.getAddress();
+            short parentPrefixLength = (short) (prefix.getIpv4MaskLength() - 1);
+            byte[] parentPrefix = MaskUtil.normalizeByteArray(prefix.getIpv4AddressBinary().getValue(),
+                    parentPrefixLength);
+            return LispAddressUtil.asIpv4PrefixBinaryEid(eid, parentPrefix, parentPrefixLength);
+        } else if (eid.getAddress() instanceof Ipv6PrefixBinary) {
+            Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) eid.getAddress();
+            short parentPrefixLength = (short) (prefix.getIpv6MaskLength() - 1);
+            byte[] parentPrefix = MaskUtil.normalizeByteArray(prefix.getIpv6AddressBinary().getValue(),
+                    parentPrefixLength);
+            return LispAddressUtil.asIpv6PrefixBinaryEid(eid, parentPrefix, parentPrefixLength);
         }
+        return null;
     }
 
     @Override
index b8bfe9f806e25230733cd749459b962028365569..1be9e16b5191f69ed27840c1691c78537ee178f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014, 2017 Contextream, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -46,7 +46,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.ei
 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;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord.Action;
 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.mapping.record.list.MappingRecordItemBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapreplymessage.MapReplyBuilder;
@@ -59,9 +58,6 @@ import org.slf4j.LoggerFactory;
 public class MapResolver implements IMapResolverAsync {
     protected static final Logger LOG = LoggerFactory.getLogger(MapResolver.class);
 
-    private static final int TTL_RLOC_TIMED_OUT = 1;
-    private static final int TTL_NO_RLOC_KNOWN = 15;
-
     private IMappingService mapService;
     private boolean subscriptionService;
     private String elpPolicy;
@@ -113,8 +109,7 @@ public class MapResolver implements IMapResolverAsync {
             MappingData mappingData = mapService.getMapping(srcEid, eidRecord.getEid());
             MappingRecord mapping;
             if (mappingData == null) {
-                mapping = getNegativeMapping(eidRecord.getEid());
-                mapService.addMapping(MappingOrigin.Southbound, mapping.getEid(), null, new MappingData(mapping));
+                mapping = mapService.addNegativeMapping(eidRecord.getEid()).getRecord();
             } else {
                 mapping = mappingData.getRecord();
             }
@@ -183,27 +178,6 @@ public class MapResolver implements IMapResolverAsync {
         }
     }
 
-    private MappingRecord getNegativeMapping(Eid eid) {
-        MappingRecordBuilder recordBuilder = new MappingRecordBuilder();
-        recordBuilder.setAuthoritative(false);
-        recordBuilder.setMapVersion((short) 0);
-        recordBuilder.setEid(eid);
-        if (eid.getAddressType().equals(Ipv4PrefixBinaryAfi.class)
-                || eid.getAddressType().equals(Ipv6PrefixBinaryAfi.class)) {
-            Eid widestNegativePrefix = mapService.getWidestNegativePrefix(eid);
-            if (widestNegativePrefix != null) {
-                recordBuilder.setEid(widestNegativePrefix);
-            }
-        }
-        recordBuilder.setAction(Action.NativelyForward);
-        if (authenticate && mapService.getAuthenticationKey(eid) != null) {
-            recordBuilder.setRecordTtl(TTL_RLOC_TIMED_OUT);
-        } else {
-            recordBuilder.setRecordTtl(TTL_NO_RLOC_KNOWN);
-        }
-        return recordBuilder.build();
-    }
-
     private void updateSubscribers(Rloc itrRloc, Eid reqEid, Eid mapEid, Eid srcEid, Integer recordTtl) {
         Subscriber subscriber = new Subscriber(itrRloc, srcEid, Subscriber.recordTtlToSubscriberTime(recordTtl));
         Eid subscribedEid = mapEid;
index 4fda63c955e102246dd44de2ce9c6a69510e9e29..225bce15060759fbf1e83b13ca517f630f738fa6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014, 2017 Contextream, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -45,6 +45,7 @@ import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
 import org.opendaylight.lispflowmapping.lisp.util.MapNotifyBuilderHelper;
 import org.opendaylight.lispflowmapping.lisp.util.MapRequestUtil;
+import org.opendaylight.lispflowmapping.lisp.util.MappingRecordUtil;
 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
@@ -102,6 +103,7 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener, IS
     @SuppressWarnings("unchecked")
     public void handleMapRegister(MapRegister mapRegister) {
         boolean mappingUpdated = false;
+        boolean oldMappingRemoved = false;
         boolean merge = ConfigIni.getInstance().mappingMergeIsSet() && mapRegister.isMergeEnabled();
         Set<Subscriber> subscribers = null;
         MappingRecord oldMapping;
@@ -124,6 +126,10 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener, IS
 
             oldMapping = getMappingRecord(mapService.getMapping(MappingOrigin.Southbound, eid));
             mapService.addMapping(MappingOrigin.Southbound, eid, getSiteId(mapRegister), mappingData);
+            if (oldMapping != null && MappingRecordUtil.isNegativeMapping(oldMapping)) {
+                mapService.removeMapping(MappingOrigin.Southbound, oldMapping.getEid());
+                oldMappingRemoved = true;
+            }
 
             if (subscriptionService) {
                 MappingRecord newMapping = merge
@@ -139,6 +145,10 @@ public class MapServer implements IMapServerAsync, OdlMappingserviceListener, IS
                         subscribers = addParentSubscribers(eid, subscribers);
                     }
                     sendSmrs(eid, subscribers);
+                    if (oldMapping != null && oldMappingRemoved && !oldMapping.getEid().equals(eid)) {
+                        subscribers = getSubscribers(oldMapping.getEid());
+                        sendSmrs(oldMapping.getEid(), subscribers);
+                    }
                     mappingUpdated = true;
                 }
             }
index 45702943068c355e84c089eed4e8bffb18e1e9e9..02ceaa375aea6aef738839c54598516e7adc0b2d 100644 (file)
@@ -27,6 +27,7 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.lispflowmapping.config.ConfigIni;
 import org.opendaylight.lispflowmapping.dsbackend.DataStoreBackEnd;
@@ -87,8 +88,9 @@ public class MappingSystemTest {
     @Mock private static IMapCache pmcMock;
     @Mock private static IAuthKeyDb akdbMock;
     @Mock private static DataStoreBackEnd dsbeMock;
+    @Mock private static NotificationPublishService npsMock;
     @Mock private static EnumMap<MappingOrigin, IMapCache> tableMapMock;
-    @InjectMocks private static MappingSystem mappingSystem = new MappingSystem(daoMock, false, true, true);
+    @InjectMocks private static MappingSystem mappingSystem = new MappingSystem(daoMock, false, npsMock, true);
 
     private static final String IPV4_SRC =      "127.0.0.1";
     private static final String IPV4_DST =      "192.168.0.1";
@@ -434,7 +436,7 @@ public class MappingSystemTest {
      */
     @Test
     public void removeMappingTest_sb() throws NoSuchFieldException, IllegalAccessException {
-        mappingSystem = new MappingSystem(daoMock, false, true, false);
+        mappingSystem = new MappingSystem(daoMock, false, npsMock, false);
         injectMocks();
         Mockito.when(tableMapMock.get(MappingOrigin.Southbound)).thenReturn(smcMock);
 
@@ -564,7 +566,7 @@ public class MappingSystemTest {
         Mockito.verify(smcMock).printMappings();
 
         mappingSystem.destroy();
-        mappingSystem = new MappingSystem(daoMock, true, true, true);
+        mappingSystem = new MappingSystem(daoMock, true, npsMock, true);
         mappingSystem.setDataStoreBackEnd(dsbeMock);
         mappingSystem.setMappingMerge(false);
         mappingSystem.setIterateMask(true);
index b0e82c7fe6aef7e6bec9f3ce36dc0d12f6dd51a4..632bbc27c2528666caae9a12c777d6417df90a64 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2016, 2017 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -22,6 +22,7 @@ import org.opendaylight.lispflowmapping.implementation.LispMappingService;
 import org.opendaylight.lispflowmapping.implementation.MappingService;
 import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
 import org.opendaylight.lispflowmapping.interfaces.dao.Subscriber;
+import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
 import org.opendaylight.lispflowmapping.lisp.util.SourceDestKeyHelper;
@@ -49,7 +50,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.ei
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemBuilder;
 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.locatorrecords.LocatorRecordKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkeyBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
 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.mapping.record.list.MappingRecordItemBuilder;
@@ -153,14 +153,13 @@ public class MapResolverTest {
                 .setAuthoritative(false)
                 .setMapVersion((short) 0)
                 .setEid(IPV4_PREFIX_EID_1)
-                .setAction(MappingRecord.Action.NativelyForward)
+                .setAction(LispMessage.NEGATIVE_MAPPING_ACTION)
                 .setRecordTtl(TTL_RLOC_TIMED_OUT);
 
         Mockito.when(mapServiceMock.getMapping(mapRequestBuilder.getSourceEid().getEid(), IPV4_PREFIX_EID_1))
                 .thenReturn(null);
-        Mockito.when(mapServiceMock.getAuthenticationKey(IPV4_PREFIX_EID_1))
-                .thenReturn(new MappingAuthkeyBuilder().build());
-        Mockito.when(mapServiceMock.getWidestNegativePrefix(IPV4_PREFIX_EID_1)).thenReturn(IPV4_PREFIX_EID_1);
+        Mockito.when(mapServiceMock.addNegativeMapping(IPV4_PREFIX_EID_1))
+                .thenReturn(getDefaultMappingData(mappingRecordBuilder.build()));
 
         // result
         final MapReplyBuilder mapReplyBuilder = getDefaultMapReplyBuilder();
index e339fa385696ad2071ac991e3965c33db12db0e2..11e85a5a20bac5cba92f50bb16eb9aeda6c44e7b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014, 2017 Contextream, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,9 +8,12 @@
 
 package org.opendaylight.lispflowmapping.lisp.type;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord.Action;
+
 public interface LispMessage {
     int PORT_NUM = 4342;
     int XTR_PORT_NUM = 4343;
+    Action NEGATIVE_MAPPING_ACTION = Action.NativelyForward;
 
     interface Pos {
         int TYPE = 0;
index b875e43393ea8b6f071b9de3c5cd9b6e6748c459..c66e0c68ac2e056db7787ce8df4b79508ac1e74f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2016, 2017 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -9,6 +9,7 @@
 package org.opendaylight.lispflowmapping.lisp.type;
 
 import java.util.Date;
+import org.opendaylight.lispflowmapping.lisp.util.MappingRecordUtil;
 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.mapping.record.container.MappingRecord;
 
@@ -69,6 +70,22 @@ public class MappingData {
         this.mergeEnabled = mergeEnabled;
     }
 
+    public Boolean isNegative() {
+        if (record != null) {
+            return MappingRecordUtil.isNegativeMapping(record);
+        } else {
+            return null;
+        }
+    }
+
+    public Boolean isPositive() {
+        if (record != null) {
+            return MappingRecordUtil.isPositiveMapping(record);
+        } else {
+            return null;
+        }
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder("MappingData [");
diff --git a/mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/util/MappingRecordUtil.java b/mappingservice/lisp-proto/src/main/java/org/opendaylight/lispflowmapping/lisp/util/MappingRecordUtil.java
new file mode 100644 (file)
index 0000000..9c54ac9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.lispflowmapping.lisp.util;
+
+import java.util.List;
+import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
+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.mapping.record.container.MappingRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class for MappingRecord objects.
+ *
+ * @author Lorand Jakab
+ *
+ */
+public final class MappingRecordUtil {
+    protected static final Logger LOG = LoggerFactory.getLogger(MappingRecordUtil.class);
+
+    // Utility class, should not be instantiated
+    private MappingRecordUtil() {
+    }
+
+    public static boolean isNegativeMapping(MappingRecord mapping) {
+        List<LocatorRecord> rlocs = mapping.getLocatorRecord();
+        if (mapping.getAction() == LispMessage.NEGATIVE_MAPPING_ACTION && (rlocs == null || rlocs.isEmpty())) {
+            return true;
+        }
+        return false;
+    }
+
+    public static boolean isPositiveMapping(MappingRecord mapping) {
+        return !isNegativeMapping(mapping);
+    }
+}
index 6fa17c40c69efe76190e3540aa97970c3f535ffb..2204dec8ba3d34e76bcfdf35c87fc4c02bfe9bdb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014, 2017 Contextream, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -179,7 +179,7 @@ public final class MaskUtil {
         return InetAddress.getByAddress(normalizeByteArray(address.getAddress(), (short) maskLength));
     }
 
-    private static byte[] normalizeByteArray(byte[] address, short maskLength) {
+    public static byte[] normalizeByteArray(byte[] address, short maskLength) {
         ByteBuffer byteRepresentation = ByteBuffer.wrap(address);
         byte byteMask = (byte) 0xff;
         int mask = maskLength;
index 764104a1146df2547efb32b3c436060aa3299b4d..636d1655462f483a7b0c51b43ab653920de4c0a4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -171,22 +171,39 @@ public class SimpleMapCache implements ILispMapCache {
 
     @Override
     public Eid getParentPrefix(Eid eid) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return null;
+        }
+        return table.getParentPrefix(MaskUtil.normalize(eid));
+    }
+
+    @Override
+    public Eid getSiblingPrefix(Eid eid) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return null;
         }
-        return table.getParentPrefix(key);
+        return table.getSiblingPrefix(MaskUtil.normalize(eid));
+    }
+
+    @Override
+    public Eid getVirtualParentSiblingPrefix(Eid eid) {
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return null;
+        }
+        return table.getVirtualParentSiblingPrefix(MaskUtil.normalize(eid));
     }
 
     @Override
     public void removeMapping(Eid eid) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return;
         }
 
+        Eid key = MaskUtil.normalize(eid);
         // We intentionally don't remove subscribers, so in case a mapping is re-added, they get notified
         table.removeSpecific(key, SubKeys.RECORD);
         table.removeSpecific(key, SubKeys.SRC_RLOCS);
@@ -196,11 +213,11 @@ public class SimpleMapCache implements ILispMapCache {
 
     @Override
     public void removeMapping(Eid eid, XtrId xtrId) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return;
         }
+        Eid key = MaskUtil.normalize(eid);
         ILispDAO xtrIdTable = (ILispDAO) table.getSpecific(key, SubKeys.XTRID_RECORDS);
         if (xtrIdTable == null) {
             return;
@@ -210,11 +227,11 @@ public class SimpleMapCache implements ILispMapCache {
 
     @Override
     public void removeXtrIdMappings(Eid eid, List<XtrId> xtrIds) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return;
         }
+        Eid key = MaskUtil.normalize(eid);
         ILispDAO xtrIdTable = (ILispDAO) table.getSpecific(key, SubKeys.XTRID_RECORDS);
         if (xtrIdTable == null) {
             return;
@@ -226,8 +243,8 @@ public class SimpleMapCache implements ILispMapCache {
 
     @Override
     public void addData(Eid eid, String subKey, Object data) {
+        ILispDAO table = getOrInstantiateVniTable(eid);
         Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getOrInstantiateVniTable(key);
         table.put(key, new MappingEntry<>(subKey, data));
     }