Bug 9127: Make IT more robust when receiving packets
[lispflowmapping.git] / integrationtest / src / test / java / org / opendaylight / lispflowmapping / integrationtest / MappingServiceIntegrationTest.java
index 26d2b5f070d9033897ac764b616d568ad3177289..cb5a6830a634757d8f81d78a34ff04701899bb1e 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,
@@ -9,6 +9,7 @@ package org.opendaylight.lispflowmapping.integrationtest;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.opendaylight.lispflowmapping.integrationtest.MultiSiteScenarioUtil.SITE_A;
@@ -30,6 +31,8 @@ import static org.ops4j.pax.exam.CoreOptions.composite;
 import static org.ops4j.pax.exam.CoreOptions.maven;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
@@ -42,30 +45,64 @@ import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-
+import java.util.Set;
 import javax.inject.Inject;
-
-//import org.codehaus.jettison.json.JSONException;
-//import org.codehaus.jettison.json.JSONObject;
-//import org.codehaus.jettison.json.JSONTokener;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
+import org.opendaylight.lispflowmapping.config.ConfigIni;
 import org.opendaylight.lispflowmapping.implementation.LispMappingService;
+import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys;
+import org.opendaylight.lispflowmapping.interfaces.dao.Subscriber;
 import org.opendaylight.lispflowmapping.interfaces.lisp.IFlowMapping;
 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
-import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
-import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
-import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
 import org.opendaylight.lispflowmapping.lisp.serializer.MapNotifySerializer;
 import org.opendaylight.lispflowmapping.lisp.serializer.MapRegisterSerializer;
 import org.opendaylight.lispflowmapping.lisp.serializer.MapReplySerializer;
 import org.opendaylight.lispflowmapping.lisp.serializer.MapRequestSerializer;
+import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
+import org.opendaylight.lispflowmapping.lisp.type.MappingData;
+import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
+import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
+import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
+import org.opendaylight.lispflowmapping.lisp.util.MappingRecordUtil;
 import org.opendaylight.lispflowmapping.type.sbplugin.IConfigLispSouthboundPlugin;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.Ipv4Address;
+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.AfiListLcaf;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.ApplicationDataLcaf;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.ExplicitLocatorPathLcaf;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.InstanceIdType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4PrefixAfi;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.KeyValueAddressLcaf;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.MacAfi;
+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.SourceDestKeyLcaf;
+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.AfiList;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ApplicationData;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ExplicitLocatorPath;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix;
+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.KeyValueAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Mac;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.afi.list.AfiListBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.application.data.ApplicationDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.ExplicitLocatorPathBuilder;
+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.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop.LrsBits;
+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.HopBuilder;
+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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.Ipv4AddressBinary;
 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.augmented.lisp.address.address.Ipv4PrefixBinaryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.AddMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapNotify;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapReply;
@@ -74,8 +111,11 @@ 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.MapReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MappingKeepAlive;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.OdlLispProtoListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.RequestMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
+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.XtrReplyMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrRequestMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
@@ -84,6 +124,9 @@ 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.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.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.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.MappingRecordItem;
@@ -95,44 +138,14 @@ 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.maprequestnotification.MapRequestBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.RlocBuilder;
-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.authkey.container.MappingAuthkeyBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-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.Ipv4Address;
-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.AfiListLcaf;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.ApplicationDataLcaf;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.ExplicitLocatorPathLcaf;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.InstanceIdType;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4PrefixAfi;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.KeyValueAddressLcaf;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.MacAfi;
-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.SourceDestKeyLcaf;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.AfiList;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ApplicationData;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ExplicitLocatorPath;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix;
-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.KeyValueAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Mac;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.afi.list.AfiListBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.application.data.ApplicationDataBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.ExplicitLocatorPathBuilder;
-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.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop.LrsBits;
-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.HopBuilder;
-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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.util.Filter;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
 import org.ops4j.pax.exam.options.MavenUrlReference;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.exam.util.Filter;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
@@ -160,6 +173,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
     public static final String ODL = "org.opendaylight.controller";
     public static final String YANG = "org.opendaylight.yangtools";
+    private static final int MULTI_SITE_SLEEP_TIME = 2;
     private static final int MAX_NOTIFICATION_RETRYS = 20;
     private static final MappingAuthkey NULL_AUTH_KEY = new MappingAuthkeyBuilder().setKeyType(0).build();
 
@@ -168,7 +182,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
     public String getKarafDistro() {
         return maven()
                 .groupId("org.opendaylight.lispflowmapping")
-                .artifactId("distribution-karaf")
+                .artifactId("lispflowmapping-karaf")
                 .versionAsInProject()
                 .type("zip")
                 .getURL();
@@ -193,7 +207,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
     public Option getLoggingOption() {
         Option option = editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
                 "log4j.logger.org.opendaylight.lispflowmapping",
-                LogLevel.DEBUG.name());
+                LogLevel.TRACE.name());
         option = composite(option, super.getLoggingOption());
         return option;
     }
@@ -208,16 +222,16 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         if (socket != null) {
             socket.close();
         }
-//        if (connection != null) {
-//            connection.disconnect();
-//        }
+        // reset mapping record validity to default value
+        ConfigIni.getInstance().setRegistrationValiditySb(200000L);
     }
 
     @Before
     public void before() throws Exception {
         areWeReady();
         mapService.setLookupPolicy(IMappingService.LookupPolicy.NB_FIRST);
-        mapService.setMappingOverwrite(true);
+        mapService.setMappingMerge(false);
+        ConfigIni.getInstance().setSmrRetryCount(1);
 
         locatorEid = LispAddressUtil.asIpv4Rloc("4.3.2.1");
         socket = initSocket(socket, LispMessage.PORT_NUM);
@@ -380,6 +394,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
     @Test
     public void testTimeOuts() throws Exception {
+        timedOutMappingRecord();
         mapRequestMapRegisterAndMapRequestTestTimeout();
         //mapRequestMapRegisterAndMapRequestTestNativelyForwardTimeoutResponse();   TODO commented because it needs NB
     }
@@ -394,6 +409,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
     @Test
     public void testSmr() throws Exception {
         registerQueryRegisterWithSmr();
+        //testRepeatedSmr();
     }
 
     @Test
@@ -402,11 +418,356 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         testMultiSiteScenarioB();
     }
 
+    @Test
+    public void testNbAndSbNegativePrefix() throws UnknownHostException {
+        insertMappings();
+        testGapIntersection();
+
+        insertMappings();
+        testMultipleMappings();
+    }
+
+    @Test
+    public void testExplicitSbNegativePrefixes() {
+        // https://bugs.opendaylight.org/show_bug.cgi?id=8679
+        testNegativePrefix();
+
+        // https://bugs.opendaylight.org/show_bug.cgi?id=9023
+        testPositiveMappingRemoval();
+
+        // https://bugs.opendaylight.org/show_bug.cgi?id=9037
+        testPositivePrefixOverlappingNegativePrefix();
+    }
+
+    private void testRepeatedSmr() throws SocketTimeoutException, UnknownHostException {
+        cleanUP();
+        long timeout = ConfigIni.getInstance().getSmrTimeout();
+        ConfigIni.getInstance().setSmrRetryCount(5);
+
+        final InstanceIdType iid = new InstanceIdType(1L);
+        final Eid eid1 = LispAddressUtil.asIpv4Eid("1.1.1.1", 1L);
+        final Eid subscriberEid = LispAddressUtil.asIpv4Eid("2.2.2.2", 1L);
+        final int expectedSmrs1 = 2;
+        final int expectedSmrs2 = 3;
+
+        /* set auth */
+        final Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid("0.0.0.0/0", iid);
+        mapService.addAuthenticationKey(eid, NULL_AUTH_KEY);
+
+        /* add subscribers */
+        final String subscriberSrcRloc1 = "127.0.0.3";
+        final String subscriberSrcRloc2 = "127.0.0.4";
+        final Set<Subscriber> subscriberSet1 = Sets.newHashSet(newSubscriber(subscriberEid, subscriberSrcRloc1),
+                newSubscriber(subscriberEid, subscriberSrcRloc2));
+        mapService.addData(MappingOrigin.Southbound, eid1, SubKeys.SUBSCRIBERS, subscriberSet1);
+
+        final SocketReader reader1 = startSocketReader(subscriberSrcRloc1, 15000);
+        final SocketReader reader2 = startSocketReader(subscriberSrcRloc2, 15000);
+        sleepForSeconds(1);
+
+        /* add mapping */
+        final MappingRecord mapping1 = new MappingRecordBuilder()
+                .setEid(eid1).setTimestamp(System.currentTimeMillis()).setRecordTtl(1440).build();
+        mapService.addMapping(MappingOrigin.Northbound, eid1, null, new MappingData(mapping1));
+
+        sleepForMilliseconds((timeout * expectedSmrs1) - (timeout / 2));
+        final List<MapRequest> requests1 = processSmrPackets(reader1, subscriberSrcRloc1, expectedSmrs1);
+        final MapReply mapReply1 = lms.handleMapRequest(
+                new MapRequestBuilder(requests1.get(0))
+                        .setSourceEid(new SourceEidBuilder().setEid(subscriberEid).build())
+                        .setItrRloc(Lists.newArrayList(new ItrRlocBuilder()
+                                .setRloc(LispAddressUtil.asIpv4Rloc(subscriberSrcRloc1)).build()))
+                        .setEidItem(Lists.newArrayList(new EidItemBuilder().setEid(eid1).build()))
+                        .setSmrInvoked(true)
+                        .setSmr(false).build());
+
+        // sleep to get 1 extra smr request
+        sleepForMilliseconds(timeout * 1);
+        final List<MapRequest> requests2 = processSmrPackets(reader2, subscriberSrcRloc2, expectedSmrs2);
+        final MapReply mapReply2 = lms.handleMapRequest(
+                new MapRequestBuilder(requests2.get(0))
+                        .setSourceEid(new SourceEidBuilder().setEid(subscriberEid).build())
+                        .setItrRloc(Lists.newArrayList(new ItrRlocBuilder()
+                                .setRloc(LispAddressUtil.asIpv4Rloc(subscriberSrcRloc2)).build()))
+                        .setEidItem(Lists.newArrayList(new EidItemBuilder().setEid(eid1).build()))
+                        .setSmrInvoked(true)
+                        .setSmr(false).build());
+
+        sleepForSeconds(3);
+        assertEquals(expectedSmrs1, requests1.size());
+        assertEquals(expectedSmrs2, requests2.size());
+        assertEquals((long) mapReply1.getNonce(), (long) requests1.get(0).getNonce());
+        assertEquals((long) mapReply2.getNonce(), (long) requests2.get(0).getNonce());
+        assertNextBufferEmpty(reader1);
+        assertNextBufferEmpty(reader2);
+
+        reader1.stopReading();
+        reader2.stopReading();
+    }
+
+    private SocketReader startSocketReader(String address, int timeout) {
+        DatagramSocket receivingSocket = null;
+
+        try {
+            receivingSocket = new DatagramSocket(new InetSocketAddress(address, LispMessage.PORT_NUM));
+        } catch (SocketException e) {
+            LOG.error("Can't initialize socket for {}", address, e);
+        }
+        return SocketReader.startReadingInStandaloneThread(receivingSocket, timeout);
+    }
+
+    private List<MapRequest> processSmrPackets(SocketReader reader, String address, int expectedSmrs) {
+        InetAddress inetAddress = null;
+        try {
+            inetAddress = InetAddress.getByName(address);
+        } catch (UnknownHostException e) {
+            LOG.error("Unknown address {}.", address, e);
+        }
+
+        final List<MapRequest> requests = Lists.newArrayList();
+        byte[][] buffers = reader.getBuffers(expectedSmrs);
+        for (byte[] buf : buffers) {
+            ByteBuffer packet = ByteBuffer.wrap(buf);
+            if (checkType(packet, MessageType.MapRequest)) {
+                MapRequest request = MapRequestSerializer.getInstance().deserialize(packet, inetAddress);
+                requests.add(request);
+            }
+        }
+        return requests;
+    }
+
+    private void assertNextBufferEmpty(SocketReader socketReader) {
+        assertTrue(MultiSiteScenario.areBuffersEmpty(socketReader.getBuffers(1)));
+    }
+
+    private static Subscriber newSubscriber(Eid srcEid, String srcRlocIp) {
+        final int timeout = 5;
+        final Rloc srcRloc = LispAddressUtil.asIpv4Rloc(srcRlocIp);
+        return new Subscriber(srcRloc, srcEid, timeout);
+    }
+
+    private void testMultipleMappings() throws UnknownHostException {
+        final InstanceIdType iid = new InstanceIdType(1L);
+        final String prefix1 = "1.1.127.10/32"; // prefix from the intersection of NB and SB gaps
+        final String prefix2 = "1.1.200.255/32"; // prefix with existing mapping in NB
+        final String prefix3 = "1.3.255.255/32";
+
+        final MapRequest mapRequest = new MapRequestBuilder().setSmrInvoked(false).setEidItem(Lists.newArrayList(
+                new EidItemBuilder().setEid(LispAddressUtil.asIpv4PrefixBinaryEid(prefix1, iid))
+                        .build(),
+                new EidItemBuilder().setEid(LispAddressUtil.asIpv4PrefixBinaryEid(prefix2, iid))
+                        .build(),
+                new EidItemBuilder().setEid(LispAddressUtil.asIpv4PrefixBinaryEid(prefix3, iid))
+                        .build()))
+                .build();
+        final MapReply mapReply = lms.handleMapRequest(mapRequest);
+
+        // expected result
+        final String resultPrefix1 = "1.1.64.0";
+        final Address resultNegMapping1 = new Ipv4PrefixBinaryBuilder()
+                .setIpv4AddressBinary(new Ipv4AddressBinary(InetAddress.getByName(resultPrefix1).getAddress()))
+                .setIpv4MaskLength((short) 18).build();
+
+        final String resultPrefix2 = "1.1.128.0";
+        final Address resultMapping2 = new Ipv4PrefixBinaryBuilder()
+                .setIpv4AddressBinary(new Ipv4AddressBinary(InetAddress.getByName(resultPrefix2).getAddress()))
+                .setIpv4MaskLength((short) 17).build();
+
+        final String resultPrefix3 = "1.3.0.0";
+        final Address resultNegMapping3 = new Ipv4PrefixBinaryBuilder()
+                .setIpv4AddressBinary(new Ipv4AddressBinary(InetAddress.getByName(resultPrefix3).getAddress()))
+                .setIpv4MaskLength((short) 16).build();
+
+        assertEquals(resultNegMapping1, mapReply.getMappingRecordItem().get(0).getMappingRecord().getEid()
+                .getAddress());
+        assertEquals(resultMapping2, mapReply.getMappingRecordItem().get(1).getMappingRecord().getEid()
+                .getAddress());
+        assertEquals(resultNegMapping3, mapReply.getMappingRecordItem().get(2).getMappingRecord().getEid()
+                .getAddress());
+    }
+
+    /**
+     * Tests a negative mapping from an intersection of gaps in northbound and southbound.
+     */
+    private void testGapIntersection() throws UnknownHostException {
+        // request an Eid from a gap between mappings
+        final MapReply mapReply = lms.handleMapRequest(newMapRequest(1L, "1.1.127.10/32"));
+
+        // expected negative mapping
+        final Address resultNegMapping = new Ipv4PrefixBinaryBuilder()
+                .setIpv4AddressBinary(new Ipv4AddressBinary(InetAddress.getByName("1.1.64.0").getAddress()))
+                .setIpv4MaskLength((short) 18).build();
+        assertEquals(resultNegMapping, mapReply.getMappingRecordItem().get(0).getMappingRecord().getEid()
+                .getAddress());
+    }
+
+    private void testNegativePrefix() {
+        // First, we test with one mapping in NB and one mapping in SB
+        cleanUP();
+
+        insertNBMappings(1L, "192.0.2.0/24");
+        insertSBMappings(1L, "10.0.0.0/32");
+
+        restartSocket();
+        sleepForSeconds(2);
+
+        MapReply mapReply = lms.handleMapRequest(newMapRequest(1L, "11.1.1.1/32"));
+        Eid expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "11.0.0.0/8");
+        assertEquals(expectedNegativePrefix, mapReply.getMappingRecordItem().get(0).getMappingRecord().getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mapReply.getMappingRecordItem().get(0).getMappingRecord()));
+
+        // Second, we test with two mappings in NB only
+        cleanUP();
+
+        insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+
+        restartSocket();
+        sleepForSeconds(2);
+
+        mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+        expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/16");
+        MappingRecord mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+        assertEquals(expectedNegativePrefix, mr.getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+    }
+
+    private void testPositiveMappingRemoval() {
+        cleanUP();
+
+        insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+        insertSBMappings(1L, "192.168.32.0/19");
+
+        MapReply mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+        Eid expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/19");
+        MappingRecord mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+        assertEquals(expectedNegativePrefix, mr.getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+
+        mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.64.1/32"));
+        expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.64.0/18");
+        mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+        assertEquals(expectedNegativePrefix, mr.getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+
+        mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.128.1/32"));
+        expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.128.0/17");
+        mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+        assertEquals(expectedNegativePrefix, mr.getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+
+        printMapCacheState();
+
+        mapService.removeMapping(MappingOrigin.Southbound, LispAddressUtil.asIpv4PrefixBinaryEid(
+                1L, "192.168.32.0/19"));
+
+        printMapCacheState();
+
+        mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.32.1/32"));
+        expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/16");
+        mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+        assertEquals(expectedNegativePrefix, mr.getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+
+        printMapCacheState();
+    }
+
+    private void testPositivePrefixOverlappingNegativePrefix() {
+        cleanUP();
+
+        insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+
+        MapReply mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+        Eid expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/16");
+        MappingRecord mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+        assertEquals(expectedNegativePrefix, mr.getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+
+        insertNBMappings(1L, "192.168.1.0/24");
+
+        mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+        expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/24");
+        mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+        assertEquals(expectedNegativePrefix, mr.getEid());
+        assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+    }
+
+    private void insertMappings() {
+        cleanUP();
+        mapService.setLookupPolicy(IMappingService.LookupPolicy.NB_AND_SB);
+
+        insertNBMappings(1L, "1.2.0.0/16", "1.1.128.0/17");
+        insertSBMappings(1L, "1.1.32.0/19", "1.0.0.0/8");
+
+        restartSocket();
+        sleepForSeconds(2);
+    }
+
+    private void insertNBMappings(long iid, String ... prefixes) {
+        LOG.debug("Adding Northbound mappings for prefixes: {}", prefixes);
+        final InstanceIdType iiType = new InstanceIdType(iid);
+        for (String prefix : prefixes) {
+            MappingRecord record = newMappingRecord(prefix, iiType);
+            mapService.addMapping(MappingOrigin.Northbound, record.getEid(), null, new MappingData(record));
+        }
+        sleepForMilliseconds(25);
+        printMapCacheState();
+    }
+
+    private void insertSBMappings(long iid, String ... prefixes) {
+        LOG.debug("Adding Southbound mappings for prefixes: {}", prefixes);
+        final InstanceIdType iiType = new InstanceIdType(iid);
+        Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid("0.0.0.0/0", iiType);
+        mapService.addAuthenticationKey(eid, NULL_AUTH_KEY);
+
+        for (String prefix : prefixes) {
+            MappingRecord record = newMappingRecord(prefix, iiType);
+            mapService.addMapping(MappingOrigin.Southbound, record.getEid(), null,
+                    new MappingData(record, System.currentTimeMillis()));
+        }
+        printMapCacheState();
+    }
+
+    private void printMapCacheState() {
+        LOG.debug("Map-cache state:\n{}", mapService.prettyPrintMappings());
+    }
+
+    /**
+     * Creates a new MappingRecord object.
+     *
+     * @param prefix The Eid prefix
+     * @param iid VNI
+     * @return new MappingRecord object
+     */
+    private MappingRecord newMappingRecord(String prefix, InstanceIdType iid) {
+        final Eid prefixBinary = LispAddressUtil.asIpv4PrefixBinaryEid(prefix, iid);
+        return new MappingRecordBuilder()
+                .setEid(prefixBinary)
+                .setLocatorRecord(Lists.newArrayList(new LocatorRecordBuilder()
+                        .setRloc(LispAddressUtil.asIpv4Rloc("2.2.2.2"))
+                        .setLocatorId("loc_id")
+                        .setRouted(true)
+                        .setPriority((short) 1)
+                        .setWeight((short) 1).build()))
+                .setTimestamp(System.currentTimeMillis())
+                .setRecordTtl(1440).build();
+    }
+
+    private MapRequest newMapRequest(long iid, String prefix) {
+        final InstanceIdType iidt = new InstanceIdType(iid);
+        return new MapRequestBuilder()
+                .setSmrInvoked(false)
+                .setEidItem(Lists.newArrayList(
+                        new EidItemBuilder().setEid(LispAddressUtil.asIpv4PrefixBinaryEid(prefix, iidt)).build()))
+                .build();
+    }
+
     /**
      * TEST SCENARIO A
      */
     public void testMultiSiteScenarioA() throws IOException {
         cleanUP();
+        ConfigIni.getInstance().setSmrRetryCount(1);
+        ConfigIni.getInstance().setSmrTimeout(30000L);
 
         final MultiSiteScenario multiSiteScenario = new MultiSiteScenario(mapService, lms);
         multiSiteScenario.setCommonAuthentication();
@@ -418,106 +779,117 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         multiSiteScenario.storeSouthboundMappings(false, SITE_A, SITE_B, SITE_C, SITE_D4, SITE_D5);
         multiSiteScenario.storeNorthMappingSrcDst(SITE_B, SITE_C);
         multiSiteScenario.storeNorthMappingNegative(SITE_C, Action.Drop);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.assertPingWorks(SITE_A, 5, SITE_B, 4);
         multiSiteScenario.assertPingWorks(SITE_B, 5, SITE_C, 4);
         multiSiteScenario.assertPingFails(SITE_A, 1, SITE_C, 4);
 
         //TEST CASE 2
-        //following action should trigger generatting of SMR messages:
+        //following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.1/32
         multiSiteScenario.storeNorthMappingSrcDst(SITE_A, SITE_C);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B.getHost(5), SITE_A.getHost(1));
         multiSiteScenario.assertPingWorks(SITE_A, 5, SITE_C, 4);
         multiSiteScenario.assertPingWorks(SITE_B, 5, SITE_C, 4);
         multiSiteScenario.assertPingFails(SITE_D4, 5, SITE_C, 4);
 
         //TEST CASE 3
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.1/32
         // 3) 192.0.1.5/32
         // 4) 192.0.4.5/32
         multiSiteScenario.deleteNorthMappingNegative(SITE_C);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B.getHost(5), SITE_A.getHost(1), SITE_A
                         .getHost(5),
                 SITE_D4.getHost(5));
         multiSiteScenario.assertPingWorks(SITE_D4, 5, SITE_C, 4);
 
         //TEST CASE 4
-        // following action should trigger generatting of SMR messages:
-        // 1) 192.0.4.5/32
+        // following action should trigger generating of SMR messages:
+        // 1) 192.0.2.5/32
+        // 2) 192.0.1.1/32
+        // 3) 192.0.1.5/32
+        // 4) 192.0.4.5/32
         multiSiteScenario.storeNorthMappingSrcDst(SITE_B, SITE_C_RLOC_10);
-        sleepForSeconds(2);
-        multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_D4.getHost(5));
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
+        multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B.getHost(5), SITE_A.getHost(1),
+                SITE_A.getHost(5), SITE_D4.getHost(5));
         //way of testing ping - get RLOC for mapping src-dst and compare it with awaited value doesn't test
         //that ping won't be successfull
         multiSiteScenario.assertPingFails(SITE_B, 5, SITE_C, 4);
 
         //TEST CASE 5
-        // following action should trigger generatting of SMR messages:
-        // 1) 192.0.4.5/32
-        // 2) 192.0.2.5/32
+        // following action should trigger generating of SMR messages:
+        // 1) 192.0.2.5/32
+        // 2) 192.0.1.1/32
+        // 3) 192.0.1.5/32
+        // 4) 192.0.4.5/32
         multiSiteScenario.storeNorthMappingNegative(SITE_C, Action.Drop);
-        sleepForSeconds(2);
-        multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_D4.getHost(5), SITE_B.getHost(5));
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
+        multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B.getHost(5), SITE_A.getHost(1),
+                SITE_A.getHost(5), SITE_D4.getHost(5));
         multiSiteScenario.assertPingFails(SITE_D4, 5, SITE_C, 4);
 
         //TEST CASE 6
         multiSiteScenario.assertPingFails(SITE_D5, 5, SITE_C, 3);
 
         //TEST CASE 7
-        multiSiteScenario.deleteNorthMapingSrcDst(SITE_A, SITE_C);
-        sleepForSeconds(2);
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.4.5/32
         // 2) 192.0.2.5/32
         // 3) 192.0.5.5/32
+        // 4) 192.0.1.5/32
+        // 5) 192.0.1.1/32
+        multiSiteScenario.deleteNorthMapingSrcDst(SITE_A, SITE_C);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_D5.getHost(5), SITE_D4.getHost(5),
-                SITE_B.getHost(5));
+                SITE_B.getHost(5), SITE_A.getHost(1), SITE_A.getHost(5));
 
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.4.5/32
         // 2) 192.0.2.5/32
         // 3) 192.0.5.5/32
+        // 4) 192.0.1.5/32
+        // 5) 192.0.1.1/32
         multiSiteScenario.storeNorthMappingSrcDst(SITE_B, SITE_C);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_D5.getHost(5), SITE_D4.getHost(5),
-                SITE_B.getHost(5));
+                SITE_B.getHost(5), SITE_A.getHost(1), SITE_A.getHost(5));
 
         multiSiteScenario.assertPingWorks(SITE_A, 5, SITE_B, 4);
         multiSiteScenario.assertPingWorks(SITE_B, 5, SITE_C, 4);
         multiSiteScenario.assertPingFails(SITE_A, 1, SITE_C, 4);
 
         //TEST CASE 8
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.4.5/32
         // 2) 192.0.2.5/32
         // 3) 192.0.5.5/32
-        // 4) 192.0.1.1/32
+        // 4) 192.0.1.5/32
+        // 5) 192.0.1.1/32
         multiSiteScenario.deleteNorthMapingSrcDst(SITE_B, SITE_C);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_D5.getHost(5), SITE_D4.getHost(5),
-                SITE_B.getHost(5),
-                SITE_A.getHost(1));
+                SITE_B.getHost(5), SITE_A.getHost(1), SITE_A.getHost(5));
         multiSiteScenario.assertPingWorks(SITE_A, 5, SITE_B, 4);
         multiSiteScenario.assertPingFails(SITE_B, 5, SITE_C, 4);
         multiSiteScenario.assertPingFails(SITE_A, 1, SITE_C, 4);
 
         //TEST CASE 9
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.4.5/32
         // 2) 192.0.2.5/32
         // 3) 192.0.5.5/32
-        // 4) 192.0.1.1/32
+        // 4) 192.0.1.5/32
+        // 5) 192.0.1.1/32
         multiSiteScenario.deleteNorthMappingNegative(SITE_C);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_D5.getHost(5), SITE_D4.getHost(5),
-                SITE_B.getHost(5),
-                SITE_A.getHost(1));
+                SITE_B.getHost(5), SITE_A.getHost(1), SITE_A.getHost(5));
         multiSiteScenario.assertPingWorks(SITE_A, 5, SITE_B, 4);
         multiSiteScenario.assertPingWorks(SITE_B, 5, SITE_C, 4);
         multiSiteScenario.assertPingWorks(SITE_A, 5, SITE_C, 4);
@@ -539,7 +911,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         final SocketReader socketReader = SocketReader.startReadingInStandaloneThread(socket);
 
         mapService.setLookupPolicy(IMappingService.LookupPolicy.NB_AND_SB);
-        mapService.setMappingOverwrite(false);
+        mapService.setMappingMerge(true);
 
         //TEST CASE 1
         multiSiteScenario.storeSouthboundMappings(true, SITE_A_SB, SITE_B_SB, SITE_C_WP_100_1_SB, SITE_D_WP_100_1_SB,
@@ -547,23 +919,23 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         multiSiteScenario.storeNorthMappingIpPrefix(SITE_A_SB);
         multiSiteScenario.storeNorthMappingIpPrefix(SITE_B_SB);
         multiSiteScenario.storeNorthMappingIpPrefix(SITE_C_WP_50_2_SB, SITE_D_WP_50_2_SB);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.assertPingWorks(SITE_A_SB, 5, SITE_C_WP_50_2_SB, 4, SITE_D_WP_50_2_SB);
         multiSiteScenario.assertPingWorks(SITE_B_SB, 5, SITE_C_WP_50_2_SB, 4, SITE_D_WP_50_2_SB);
 
         //TEST CASE 2
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.5/32
         multiSiteScenario.storeNorthMappingSrcDst(SITE_A_SB, SITE_C_WP_50_2_SB, SITE_D_WP_50_2_SB);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B_SB.getHost(5), SITE_A_SB.getHost(5));
 
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.5/32
         multiSiteScenario.storeNorthMappingNegative(SITE_C_SB, Action.Drop);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B_SB.getHost(5), SITE_A_SB.getHost(5));
 
         multiSiteScenario.assertPingWorks(SITE_A_SB, 5, SITE_C_WP_50_2_SB, 4, SITE_D_WP_50_2_SB);
@@ -571,18 +943,18 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
 
         //TEST CASE 3
-        // following action should trigger generatting of SMR messages:
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.5/32
         multiSiteScenario.storeNorthMappingSrcDst(SITE_A_SB, SITE_C_WP_50_2_SB);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B_SB.getHost(5), SITE_A_SB.getHost(5));
         multiSiteScenario.assertPingWorks(SITE_A_SB, 5, SITE_C_WP_50_2_SB, 4);
 
         //TEST CASE 4
         multiSiteScenario.storeNorthMappingSrcDst(SITE_B_SB, SITE_C_WP_50_2_SB, SITE_D_WP_50_2_SB);
-        sleepForSeconds(2);
-        // following action should trigger generatting of SMR messages:
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.5/32
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B_SB.getHost(5), SITE_A_SB.getHost(5));
@@ -590,8 +962,8 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
         //TEST CASE 5
         multiSiteScenario.deleteSouthboundMappings(SITE_D_DELETE_SB);
-        sleepForSeconds(2);
-        // following action should trigger generatting of SMR messages:
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.5/32
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B_SB.getHost(5), SITE_A_SB.getHost(5));
@@ -600,14 +972,14 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
         //TEST CASE 6
         multiSiteScenario.deleteNorthMapingSrcDst(SITE_A_SB, SITE_C_WP_50_2_SB);
-        sleepForSeconds(2);
-        // following action should trigger generatting of SMR messages:
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
+        // following action should trigger generating of SMR messages:
         // 1) 192.0.2.5/32
         // 2) 192.0.1.5/32
         multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B_SB.getHost(5), SITE_A_SB.getHost(5));
 
         multiSiteScenario.deleteNorthMapingSrcDst(SITE_B_SB, SITE_C_WP_50_2_SB);
-        sleepForSeconds(2);
+        sleepForSeconds(MULTI_SITE_SLEEP_TIME);
         multiSiteScenario.assertPingFails(SITE_B_SB, 5, SITE_C_WP_50_2_SB, 4);
 
         socketReader.stopReading();
@@ -742,7 +1114,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
     public void testMapRegisterOverwritesNoSubkey() throws SocketTimeoutException {
         cleanUP();
-        mapService.setMappingOverwrite(true);
+        mapService.setMappingMerge(false);
         Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid("1.2.3.4/32");
         Rloc rloc1Value = LispAddressUtil.asIpv4Rloc("4.3.2.1");
         Rloc rloc2Value = LispAddressUtil.asIpv4Rloc("4.3.2.2");
@@ -754,7 +1126,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
     public void testMapRegisterDoesntOverwritesNoSubkey() throws SocketTimeoutException {
         cleanUP();
-        mapService.setMappingOverwrite(false);
+        mapService.setMappingMerge(true);
         Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid("1.2.3.4/32");
         Rloc rloc1Value = LispAddressUtil.asIpv4Rloc("4.3.2.1");
         Rloc rloc2Value = LispAddressUtil.asIpv4Rloc("4.3.2.2");
@@ -1491,8 +1863,11 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         mapRegisterBuilder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
         mapRegisterBuilder.getMappingRecordItem().add(new MappingRecordItemBuilder().setMappingRecord(
                 etlrBuilder.build()).build());
-        sendMapRegister(mapRegisterBuilder.build());
+        MapRegister mapRegister = mapRegisterBuilder.build();
+        LOG.trace("Sending Map-Register via socket: {}", mapRegister);
+        sendMapRegister(mapRegister);
         MapNotify mapNotify = receiveMapNotify();
+        LOG.trace("Received Map-Notify via socket: {}", mapNotify);
         assertEquals(8, mapNotify.getNonce().longValue());
         // wait for the notifications to propagate
         sleepForSeconds(1);
@@ -1774,6 +2149,7 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
     public void mapRequestMapRegisterAndMapRequestTestTimeout() throws SocketTimeoutException {
         cleanUP();
+        ConfigIni.getInstance().setSmrRetryCount(0);
         Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid("1.2.3.4/32");
         mapService.addAuthenticationKey(eid, NULL_AUTH_KEY);
         sleepForSeconds(1);
@@ -1843,6 +2219,37 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
 
     }
 
+    private void timedOutMappingRecord() {
+        cleanUP();
+        mapService.setMappingMerge(true);
+        // mapping expires after 1 second
+        ConfigIni.getInstance().setRegistrationValiditySb(1000L);
+
+        final Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid("1.2.3.4/32", new InstanceIdType(10L));
+        final XtrId xtrId = new XtrId(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
+        final SiteId siteId = new SiteId(new byte[]{1, 2, 3, 4, 5, 6, 7, 8});
+
+        final LocatorRecord locatorRecord = new LocatorRecordBuilder()
+                .setRloc(LispAddressUtil.asIpv4Rloc("1.1.1.1")).setLocatorId("locator-id").build();
+        final MappingRecord mappingRecord = new MappingRecordBuilder()
+                .setEid(eid)
+                .setSiteId(siteId)
+                .setRecordTtl(1000)
+                .setXtrId(xtrId)
+                .setAction(Action.NoAction)
+                .setAuthoritative(true)
+                .setLocatorRecord(Lists.newArrayList()).build();
+        mappingRecord.getLocatorRecord().add(locatorRecord);
+
+        mapService.addAuthenticationKey(eid, NULL_AUTH_KEY);
+        mapService.addMapping(MappingOrigin.Southbound, eid, siteId,
+                new MappingData(mappingRecord, System.currentTimeMillis()));
+        sleepForSeconds(2);
+
+        MappingRecord resultRecord = (MappingRecord) mapService.getMapping(MappingOrigin.Southbound, eid);
+        assertNull(resultRecord);
+    }
+
     private void testTTLAfterClean(MapRequest mapRequest) throws SocketTimeoutException {
         MapReply mapReply;
         sendMapRequest(mapRequest);
@@ -2066,16 +2473,28 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
     }
 
     private MapReply receiveMapReply() throws SocketTimeoutException {
-        return MapReplySerializer.getInstance().deserialize(ByteBuffer.wrap(receivePacket().getData()));
+        return receiveMapReply(socket, 1000);
     }
 
     private MapRequest receiveMapRequest(DatagramSocket datagramSocket) throws SocketTimeoutException {
-        return MapRequestSerializer.getInstance().deserialize(ByteBuffer.wrap(receivePacket(
-                datagramSocket, 30000).getData()), null);
+        ByteBuffer packet = ByteBuffer.wrap(receivePacket(datagramSocket, 30000).getData());
+        while (!checkType(packet, MessageType.MapRequest)) {
+            packet = ByteBuffer.wrap(receivePacket(datagramSocket, 30000).getData());
+        }
+        return MapRequestSerializer.getInstance().deserialize(packet, null);
     }
 
     private MapNotify receiveMapNotify() throws SocketTimeoutException {
-        return MapNotifySerializer.getInstance().deserialize(ByteBuffer.wrap(receivePacket().getData()));
+        ByteBuffer packet = ByteBuffer.wrap(receivePacket().getData());
+        while (!checkType(packet, MessageType.MapNotify)) {
+            packet = ByteBuffer.wrap(receivePacket().getData());
+        }
+        return MapNotifySerializer.getInstance().deserialize(packet);
+    }
+
+    private static boolean checkType(ByteBuffer packet, MessageType type) {
+        final int receivedType = ByteUtil.getUnsignedByte(packet, LispMessage.Pos.TYPE) >> 4;
+        return MessageType.forValue(receivedType) == type;
     }
 
     private void sendMapRequest(MapRequest mapRequest) {
@@ -2130,6 +2549,24 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         }
     }
 
+    private MapReply receiveMapReply(DatagramSocket receivedSocket, int timeout) throws SocketTimeoutException {
+        DatagramPacket packet;
+        try {
+            while (true) {
+                packet = receivePacket(receivedSocket, timeout);
+                final ByteBuffer buff = ByteBuffer.wrap(packet.getData());
+                final int type = ByteUtil.getUnsignedByte(buff, LispMessage.Pos.TYPE) >> 4;
+                final Object lispType = MessageType.forValue(type);
+
+                if (lispType == MessageType.MapReply) {
+                    return MapReplySerializer.getInstance().deserialize(buff);
+                }
+            }
+        } catch (SocketTimeoutException ste) {
+            throw ste;
+        }
+    }
+
     private void sleepForSeconds(int seconds) {
         try {
             Thread.sleep(seconds*1000);
@@ -2138,6 +2575,14 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
         }
     }
 
+    private void sleepForMilliseconds(long milliseconds) {
+        try {
+            Thread.sleep(milliseconds);
+        } catch (InterruptedException e) {
+            LOG.warn("Interrupted while sleeping", e);
+        }
+    }
+
     private void initPacketAddress(DatagramPacket packet, int port) throws UnknownHostException {
         packet.setAddress(InetAddress.getByName(lispBindAddress));
         packet.setPort(port);
@@ -2146,9 +2591,10 @@ public class MappingServiceIntegrationTest extends AbstractMdsalTestBase {
     private DatagramSocket initSocket(DatagramSocket socket, int port) {
         for (int i=0; i < NUM_OF_ATTEMPTS_TO_CREATE_SOCKET; i++) {
             try {
+                LOG.debug("Binding socket on {}:{}", ourAddress, port);
                 return new DatagramSocket(new InetSocketAddress(ourAddress, port));
             } catch (SocketException e) {
-                LOG.error("Can't initialize socket for {}", ourAddress, e);
+                LOG.error("Can't initialize socket for {}:{}", ourAddress, port, e);
             }
         }
         fail();