+ //testRepeatedSmr();
+ }
+
+ @Test
+ public void testMultiSite() throws Exception {
+ testMultiSiteScenarioA();
+ 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_moreSpecific();
+
+ // https://bugs.opendaylight.org/show_bug.cgi?id=9116
+ testPositivePrefixOverlappingNegativePrefix_lessSpecific();
+ }
+
+ @Test
+ public void testMappingChangeCases() {
+ // Test numbers described in the below Google Sheet:
+ // https://docs.google.com/spreadsheets/d/1we3eBBilS-HoAZgtHH3jtmvq4-6lBvVX2yMgxfF48w0/edit?usp=sharing
+
+ test1nullToNB();
+ test2nullToSB();
+ test3deleteNB();
+ test4NBtoNBmoreSpecific();
+ test5NBtoNBexactMatch();
+ test6NBtoNBlessSpecific();
+ test7NBtoSBmoreSpecific();
+ test8NBtoSBexactMatch();
+ test9NBtoSBlessSpecific();
+ test10deleteSBpositive();
+ test11SBpositiveToNBmoreSpecific();
+ test12SBpositiveToNBexactMatch();
+ test13SBtoNBlessSpecific();
+ test14SBpositiveToSBmoreSpecific();
+ test15SBpositiveToSBexactMatch();
+ test16SBpositiveToSBlessSpecific();
+ test17deleteSBnegative();
+ test18SBnegativeToNBmoreSpecific();
+ test19SBnegativeToNBexactMatch();
+ test20SBnegativeToNBlessSpecific();
+ test21SBnegativeToSBmoreSpecific();
+ test22SBnegativeToSBexactMatch();
+ test23SBnegativeToSBlessSpecific();
+
+ testNbSourceDest();
+
+ testSubtree();
+ }
+
+ private void testRepeatedSmr() throws SocketTimeoutException, UnknownHostException {
+ cleanUP();
+ long timeout = ConfigIni.getInstance().getSmrTimeout();
+ ConfigIni.getInstance().setSmrRetryCount(5);
+
+ final InstanceIdType iid = new InstanceIdType(Uint32.ONE);
+ 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(List.of(new ItrRlocBuilder()
+ .setRloc(LispAddressUtil.asIpv4Rloc(subscriberSrcRloc1)).build()))
+ .setEidItem(List.of(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(List.of(new ItrRlocBuilder()
+ .setRloc(LispAddressUtil.asIpv4Rloc(subscriberSrcRloc2)).build()))
+ .setEidItem(List.of(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 = new ArrayList<>();
+ byte[][] buffers = reader.getBuffers(expectedSmrs);
+ for (byte[] buf : buffers) {
+ ByteBuffer packet = ByteBuffer.wrap(buf);
+ if (MappingServiceIntegrationTestUtil.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(Uint32.ONE);
+ 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()
+ .setEidItemId(LispAddressStringifier
+ .getString(LispAddressUtil.asIpv4PrefixBinaryEid(prefix1, iid)))
+ .setEid(LispAddressUtil.asIpv4PrefixBinaryEid(prefix1, iid))
+ .build(),
+ new EidItemBuilder()
+ .setEidItemId(LispAddressStringifier
+ .getString(LispAddressUtil.asIpv4PrefixBinaryEid(prefix2, iid)))
+ .setEid(LispAddressUtil.asIpv4PrefixBinaryEid(prefix2, iid))
+ .build(),
+ new EidItemBuilder()
+ .setEidItemId(LispAddressStringifier
+ .getString(LispAddressUtil.asIpv4PrefixBinaryEid(prefix3, iid)))
+ .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(Uint8.valueOf(18)).build();
+
+ final String resultPrefix2 = "1.1.128.0";
+ final Address resultMapping2 = new Ipv4PrefixBinaryBuilder()
+ .setIpv4AddressBinary(new Ipv4AddressBinary(InetAddress.getByName(resultPrefix2).getAddress()))
+ .setIpv4MaskLength(Uint8.valueOf(17)).build();
+
+ final String resultPrefix3 = "1.3.0.0";
+ final Address resultNegMapping3 = new Ipv4PrefixBinaryBuilder()
+ .setIpv4AddressBinary(new Ipv4AddressBinary(InetAddress.getByName(resultPrefix3).getAddress()))
+ .setIpv4MaskLength(Uint8.valueOf(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(Uint8.valueOf(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();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ insertNBMappings(1L, "192.0.2.0/24");
+ insertSBMappings(false, 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();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+ insertSBMappings(false, 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));
+
+ MappingServiceIntegrationTestUtil.printMapCacheState(mapService);
+
+ mapService.removeMapping(MappingOrigin.Southbound, LispAddressUtil.asIpv4PrefixBinaryEid(
+ 1L, "192.168.32.0/19"));
+
+ MappingServiceIntegrationTestUtil.printMapCacheState(mapService);
+
+ 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));
+
+ MappingServiceIntegrationTestUtil.printMapCacheState(mapService);
+ }
+
+ private void testPositivePrefixOverlappingNegativePrefix_moreSpecific() {
+ 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");
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+
+ 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 testPositivePrefixOverlappingNegativePrefix_lessSpecific() {
+ 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.0.0.0/8");
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+
+ mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ Eid expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.0.0.0/8");
+ mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+ }
+
+ /*
+ * Mapping change: NO old mapping, new mapping is from northbound
+ * Support status: SUPPORTED
+ * Description: If no mappings exists in either NB or SB, that means no subscriptions exist either, so
+ * this is just a simple case of adding a new mapping, no SMR required.
+ */
+ private void test1nullToNB() {
+ cleanUP();
+
+ insertNBMappings(1L, "192.168.0.0/16");
+ MappingServiceIntegrationTestUtil.assertNoMoreSMRs(socket, mapService);
+ }
+
+ /*
+ * Mapping change: NO old mapping, new mapping is from southbound
+ * Support status: SUPPORTED
+ * Description: If no mappings exists in either NB or SB, that means no subscriptions exist either, so
+ * this is just a simple case of adding a new mapping, no SMR required.
+ */
+ private void test2nullToSB() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ registerSBMapping(1L, "192.168.0.0/16", "10.10.10.10");
+ MappingServiceIntegrationTestUtil.assertNoMoreSMRs(socket, mapService);
+ }
+
+ /*
+ * Mapping change: deleting a mapping from northbound
+ * Support status: SUPPORTED
+ * Description: When a NB mapping is deleted, its subscribers, and the subscribers of its children are notified.
+ */
+ private void test3deleteNB() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Overlapping SB mapping, which will stay
+ insertSBMappings(false, 1L, "192.168.255.0/24");
+ // Subscribe to the overlapping SB mapping
+ lms.handleMapRequest(newMapRequest(1L, "192.168.255.1/32"));
+ // NB mapping which will be removed
+ insertNBMappings(1L, "192.168.0.0/16");
+ // The child prefix is notified of the change
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.255.0");
+ // The above SMR will result in a SMR-invoked Map-Request for 192.168.255.0/32, which in turn will result in
+ // subscribing to the new NB mapping
+
+ // Remove NB mapping
+ removeNBMapping(1L, "192.168.0.0/16");
+ // The removed prefix and the child prefix are both notified of the change
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0", "192.168.255.0");
+ }
+
+ /*
+ * Mapping change: adding a more specific northbound mapping overlapping a less specific one
+ * Support status: PARTIALLY SUPPORTED (?)
+ * Description: Overlapping prefixes in general are not "officially" supported in NB and should not be used.
+ * That said, adding a more specific does result in an SMR, but adding a less specific does not (see
+ * test 6 below).
+ */
+ private void test4NBtoNBmoreSpecific() {
+ cleanUP();
+
+ // Original (less specific) NB mapping
+ insertNBMappings(1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add the more specific new overlapping mapping
+ insertNBMapping(1L, "192.168.1.0/24", "10.10.10.10");
+ // No notification is sent
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: updating a northbound mapping
+ * Support status: SUPPORTED
+ * Description: Simple case of updating an exact match NB prefix.
+ */
+ private void test5NBtoNBexactMatch() {
+ cleanUP();
+
+ // Original NB mapping
+ insertNBMappings(1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Updated NB mapping with different locator set for the same exact prefix
+ insertNBMapping(1L, "192.168.0.0/16", "10.10.10.10");
+ // Notification is sent for the prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a less specific northbound mapping overlapping a more specific one
+ * Support status: NOT SUPPORTED
+ * Description: Overlapping prefixes in general are not "officially" supported in NB and should not be used.
+ * That said, adding a more specific does result in an SMR (see test 4 above), but adding a less
+ * specific does not.
+ */
+ private void test6NBtoNBlessSpecific() {
+ cleanUP();
+
+ // Original (more specific) NB mapping
+ insertNBMappings(1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add the less specific new overlapping mapping
+ insertNBMapping(1L, "192.0.0.0/8", "10.10.10.10");
+ // No notification is sent
+ MappingServiceIntegrationTestUtil.assertNoMoreSMRs(socket, mapService);
+ }
+
+ /*
+ * Mapping change: adding a more specific southbound mapping overlapping a less specific northbound mapping
+ * Support status: SUPPORTED
+ * Description: This is not an issue for NB_FIRST, since there is no change in the resolved mappings for the
+ * prefix range covered by the existing NB mapping. For NB_AND_SB it does make a difference, and that
+ * case is supported.
+ */
+ private void test7NBtoSBmoreSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+ mapService.setLookupPolicy(IMappingService.LookupPolicy.NB_AND_SB);
+
+ // Original (less specific) NB mapping
+ insertNBMapping(1L, "192.168.0.0/16", "172.16.0.1", "10.10.10.10");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add the more specific new overlapping SB mapping
+ registerSBMapping(1L, "192.168.1.0/24", "10.10.10.10");
+ // Notification is sent for the original prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a southbound mapping matching a northbound mapping
+ * Support status: SUPPORTED
+ * Description: When a SB mapping is added that has an existing exact match NB counterpart the subscribers of the
+ * prefix are notified. This is not strictly necessary for the NB_FIRST policy, but it is still useful
+ * for the NB_AND_SB policy.
+ */
+ private void test8NBtoSBexactMatch() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+ mapService.setLookupPolicy(IMappingService.LookupPolicy.NB_AND_SB);
+
+ // Original NB mapping
+ insertNBMapping(1L, "192.168.0.0/16", "172.16.0.1", "10.10.10.10");
+ // Subscribe, by sending a Map-Request
+ MapReply mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add a mapping with the same EID but different locator set in SB
+ registerSBMapping(1L, "192.168.0.0/16", "10.10.10.10");
+ // Notification is sent for the prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a less specific southbound mapping overlapping a more specific northbound mapping
+ * Support status: PARTIALLY SUPPORTED (?)
+ * Description: When a less specific SB mapping is added no SMR is sent, but for the NB mapping subscribers there
+ * is no actual change in the mapping. Part of the southbound prefix is not covered by the existing NB,
+ * and queries for that part will resolve to the full SB prefix, shadowing the NB prefix. This is a
+ * general problem with overlapping prefixes, but this particular combination is pretty bad.
+ */
+ private void test9NBtoSBlessSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Original (more specific) NB mapping
+ insertNBMappings(1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add the less specific new overlapping SB mapping
+ registerSBMapping(1L, "192.0.0.0/8", "10.10.10.10");
+ // No notification is sent
+ MappingServiceIntegrationTestUtil.assertNoMoreSMRs(socket, mapService);
+ }
+
+ /*
+ * Mapping change: deleting a positive mapping from southbound
+ * Support status: SUPPORTED
+ * Description: When a positive SB mapping is deleted, its subscribers, and the subscribers of its children are
+ * notified.
+ */
+ private void test10deleteSBpositive() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Overlapping SB mapping, which will stay
+ insertSBMappings(false, 1L, "192.168.255.0/24");
+ // Subscribe to the overlapping SB mapping
+ lms.handleMapRequest(newMapRequest(1L, "192.168.255.1/32"));
+ // Overlapping negative mapping
+ insertSBMappings(true, 1L, "192.168.127.0/24");
+ // Subscribe to the overlapping negative SB mapping
+ lms.handleMapRequest(newMapRequest(1L, "192.168.127.1/32"));
+ // Positive SB mapping which will be removed
+ insertSBMappings(false, 1L, "192.168.0.0/16");
+ // The child prefix is notified of the change
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.127.0", "192.168.255.0");
+ // The above SMR will result in a SMR-invoked Map-Request for 192.168.255.0/32 and 192.168.255.0/32, which in
+ // turn will result in subscribing to the new SB mapping
+
+ // Remove positive SB mapping
+ removeSBMapping(1L, "192.168.0.0/16");
+ // The removed prefix and the child prefix are both notified of the change
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0", "192.168.255.0");
+ }
+
+ /*
+ * Mapping change: adding a more specific northbound mapping overlapping a less specific southbound mapping
+ * Support status: PARTIALLY SUPPORTED (?)
+ * Description: This mapping change is detected and an SMR is sent, but the EID prefix in it is for the base address
+ * of the old prefix. When xTRs query for that, they won't actually install the new mapping. This is
+ * one of those cases where saving the original request causing the subscription would help the xTR get
+ * the correct mapping. Additionally, similar to case 9 above, this combination will shadow the NB
+ * mapping for new requests into the non-overlapping part.
+ */
+ private void test11SBpositiveToNBmoreSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Original (less specific) SB mapping
+ insertSBMappings(false, 1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add the more specific new overlapping NB mapping
+ insertNBMappings(1L, "192.168.1.0/24");
+ // Notification is sent for the original prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a northbound mapping matching a southbound mapping
+ * Support status: SUPPORTED
+ * Description: When a NB mapping is added that has an existing exact match SB counterpart, the subscribers of the
+ * prefix are notified.
+ */
+ private void test12SBpositiveToNBexactMatch() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Original SB mapping
+ insertSBMappings(false, 1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add a mapping with the same EID but different locator set in NB
+ insertNBMappings(1L, "192.168.0.0/16");
+ // Notification is sent for the prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a less specific northbound mapping overlapping a more specific southbound mapping
+ * Support status: PARTIALLY SUPPORTED (?)
+ * Description: No SMR is sent, but the NB mapping takes precedence for new requests.
+ */
+ private void test13SBtoNBlessSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Original (more specific) SB mapping
+ insertNBMappings(1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add the less specific new overlapping SB mapping
+ registerSBMapping(1L, "192.0.0.0/8", "10.10.10.10");
+ // No notification is sent
+ MappingServiceIntegrationTestUtil.assertNoMoreSMRs(socket, mapService);
+ }
+
+ /*
+ * Mapping change: adding a more specific southbound mapping overlapping a less specific one
+ * Support status: SUPPORTED
+ * Description: When a more specific SB mapping is added, the subscribers of the overlapping less specific existing
+ * SB mapping are notified.
+ */
+ private void test14SBpositiveToSBmoreSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ insertSBMappings(false, 1L, "192.168.0.0/16");
+
+ MapReply mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ Eid expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/16");
+ MappingRecord mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+
+ registerSBMapping(1L, "192.168.254.0/24", "10.10.10.10");
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+
+ mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/16");
+ mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+
+ mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.254.1/32"));
+ expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.254.0/24");
+ mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+ }
+
+ /*
+ * Mapping change: updating a southbound mapping
+ * Support status: SUPPORTED
+ * Description: Simple case of updating an exact match SB prefix.
+ */
+ private void test15SBpositiveToSBexactMatch() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Original SB mapping
+ insertSBMappings(false, 1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Updated SB mapping with different locator set for the same exact prefix
+ registerSBMapping(1L, "192.168.0.0/16", "10.10.10.10");
+ // Notification is sent for the prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a less specific southbound mapping overlapping a more specific one
+ * Support status: SUPPORTED
+ * Description: When a less specific SB mapping is added, all child prefixes with subscribers are notified.
+ */
+ private void test16SBpositiveToSBlessSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Original (more specific) SB mapping
+ insertSBMappings(false, 1L, "192.168.0.0/16");
+ // Subscribe, by sending a Map-Request
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add the less specific new overlapping SB mapping
+ registerSBMapping(1L, "192.0.0.0/8", "10.10.10.10");
+ // Notification is sent for the original prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: deleting a negative mapping from southbound
+ * Support status: SUPPORTED
+ * Description: When a negative SB mapping is deleted, its subscribers are notified.
+ */
+ private void test17deleteSBnegative() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // First we add two negative mappings to NB with a hole between them
+ insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+ // We query for the hole, adding a negative SB mapping for 192.168.0.0/16 with a subscriber in the process
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Remove positive SB mapping
+ removeSBMapping(1L, "192.168.0.0/16");
+ // Notification is sent for the prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a more specific northbound mapping overlapping a less specific negative southbound mapping
+ * Support status: SUPPORTED
+ * Description: When a more specific NB mapping is added, the overlapping negative prefix is deleted, its
+ * subscribers notified, and then more specific negatives are created when requested.
+ */
+ private void test18SBnegativeToNBmoreSpecific() {
+ cleanUP();
+
+ // First we add two negative mappings to NB with a hole between them
+ insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+ // We query for the hole, adding a negative SB mapping for 192.168.0.0/16 with a subscriber in the process
+ 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));
+
+ // Add the more specific new overlapping NB mapping
+ insertNBMappings(1L, "192.168.1.0/24");
+ // Notification is sent for the original prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+
+ // The original negative should now be broken up
+ 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));
+
+ 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.1.1/32"));
+ Eid expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.1.0/24");
+ mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+ }
+
+ /*
+ * Mapping change: adding a northbound mapping matching a negative southbound mapping
+ * Support status: SUPPORTED
+ * Description: When a NB mapping is added that has an existing exact match negative SB counterpart,
+ * the subscribers of the prefix are notified, and the negative is deleted.
+ */
+ private void test19SBnegativeToNBexactMatch() {
+ cleanUP();
+
+ // First we add two negative mappings to NB with a hole between them
+ insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+ // We query for the hole, adding a negative SB mapping for 192.168.0.0/16 with a subscriber in the process
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ insertNBMappings(1L, "192.168.0.0/16");
+ // Notification is sent for the prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0", "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a less specific northbound mapping overlapping a more specific negative southbound mapping
+ * Support status: PARTIALLY SUPPORTED (?)
+ * Description: When a less specific NB mapping covering a more specific negative SB mapping is added, the negative
+ * is deleted and its subscribers notified. Depending on the particular xTR map-cache implementation,
+ * the negative prefix may or may not stay cached (hence partially supported).
+ */
+ private void test20SBnegativeToNBlessSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Add a negative mapping
+ insertSBMappings(true, 1L, "192.168.0.0/16");
+ // Subscribe for the mapping
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add less specific northbound mapping
+ insertNBMappings(1L, "192.0.0.0/8");
+ // Notification is sent for the negative prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ /*
+ * Mapping change: adding a more specific southbound mapping overlapping a less specific negative mapping
+ * Support status: SUPPORTED
+ * Description: When a more specific SB mapping is added, the subscribers of the overlapping less specific existing
+ * negative SB mapping are notified, the negative is deleted, and then more specific negatives are
+ * created when requested.
+ */
+ private void test21SBnegativeToSBmoreSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // First we add two negative mappings to NB with a hole between them
+ insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+ // We query for the hole, adding a negative SB mapping for 192.168.0.0/16 with a subscriber in the process
+ 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));
+
+ // Add the more specific new overlapping SB mapping
+ registerSBMapping(1L, "192.168.254.0/24", "10.10.10.10");
+ // Notification is sent for the original prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L,"192.168.0.0");
+
+ mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ expectedNegativePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/17");
+ mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedNegativePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isNegativeMapping(mr));
+
+ mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.254.1/32"));
+ Eid expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.254.0/24");
+ mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+ }
+
+ /*
+ * Mapping change: updating a negative southbound mapping with a positive one
+ * Support status: SUPPORTED
+ * Description: Simple case of updating an exact match SB prefix.
+ */
+ private void test22SBnegativeToSBexactMatch() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // First we add two negative mappings to NB with a hole between them
+ insertNBMappings(1L, "192.167.0.0/16", "192.169.0.0/16");
+ // We query for the hole, adding a negative SB mapping for 192.168.0.0/16 with a subscriber in the process
+ 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));
+ // Updated SB mapping with different locator set for the same exact prefix
+ registerSBMapping(1L, "192.168.0.0/16", "10.10.10.10");
+ // Notification is sent for the prefix
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+
+ mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ Eid expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/16");
+ mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+ }
+
+ /*
+ * Mapping change: adding a less specific southbound mapping overlapping a more specific negative mapping
+ * Support status: SUPPORTED
+ * Description: When a less specific SB mapping is added, all child prefixes with subscribers are notified. In this
+ * case, the overlapping more specific negative is removed.
+ */
+ private void test23SBnegativeToSBlessSpecific() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ // Add a negative mapping
+ insertSBMappings(true, 1L, "192.168.0.0/16");
+ // Subscribe for the mapping
+ lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ // Add less specific southbound mapping
+ registerSBMapping(1L, "192.0.0.0/8", "10.10.10.10");
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ private void testNbSourceDest() {
+ cleanUP();
+
+ insertNBMappingSourceDest(1L, "192.0.2.0/24", "192.168.0.0/16",
+ MappingServiceIntegrationTestUtil.DEFAULT_IPV4_RLOC_STRING);
+
+ MapReply mapReply = lms.handleMapRequest(newMapRequest(1L, "192.168.0.1/32"));
+ Eid expectedPositivePrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "192.168.0.0/16");
+ MappingRecord mr = mapReply.getMappingRecordItem().get(0).getMappingRecord();
+ assertEquals(expectedPositivePrefix, mr.getEid());
+ assertTrue(MappingRecordUtil.isPositiveMapping(mr));
+
+ insertNBMapping(1L, "192.168.0.0/16", "10.10.10.10");
+ MappingServiceIntegrationTestUtil.checkSmr(socket, lms, mapService, 1L, "192.168.0.0");
+ }
+
+ private void testSubtree() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+
+ insertSBMappings(false, 1L, "10.0.0.0/8",
+ "10.0.0.0/16", "10.2.0.0/16", "10.255.0.0/16");
+ Eid queryPrefix = LispAddressUtil.asIpv4PrefixBinaryEid(1L, "10.0.0.0/9");
+ Set<Eid> subtreePrefixes = mapService.getSubtree(MappingOrigin.Southbound, queryPrefix);
+ LOG.debug("Subtree prefix set for EID {}: {}", LispAddressStringifier.getString(queryPrefix),
+ LispAddressStringifier.getString(subtreePrefixes));
+ Set<Eid> expectedSubtreePrefixes = new HashSet<>();
+ expectedSubtreePrefixes.add(LispAddressUtil.asIpv4PrefixBinaryEid(1L, "10.0.0.0/16"));
+ expectedSubtreePrefixes.add(LispAddressUtil.asIpv4PrefixBinaryEid(1L, "10.2.0.0/16"));
+ assertEquals(expectedSubtreePrefixes, subtreePrefixes);
+ }
+
+ private void insertMappings() {
+ cleanUP();
+ allowNullAuthenticationForAllIPv4(1L);
+ mapService.setLookupPolicy(IMappingService.LookupPolicy.NB_AND_SB);
+
+ insertNBMappings(1L, "1.2.0.0/16", "1.1.128.0/17");
+ insertSBMappings(false, 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 in VNI {} for prefixes: {}", iid, prefixes);
+ final InstanceIdType iiType = new InstanceIdType(Uint32.valueOf(iid));
+ for (String prefix : prefixes) {
+ MappingRecord record = newMappingRecord(prefix, iiType);
+ mapService.addMapping(MappingOrigin.Northbound, record.getEid(), null, new MappingData(record));
+ }
+ sleepForMilliseconds(100);
+ MappingServiceIntegrationTestUtil.printMapCacheState(mapService);
+ }
+
+ private void removeNBMapping(long iid, String prefix) {
+ LOG.debug("Removing Northbound mapping in VNI {} for prefix {}", iid, prefix);
+ Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid(iid, prefix);
+ mapService.removeMapping(MappingOrigin.Northbound, eid);
+ }
+
+ private void insertNBMapping(long iid, String prefix, String ... locators) {
+ LOG.debug("Adding Northbound mapping in VNI {} for prefix {}, locators {}", iid, prefix, locators);
+ Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid(iid, prefix);
+ List<Rloc> rlocs = new ArrayList<>();
+ for (String locator : locators) {
+ rlocs.add(LispAddressUtil.asIpv4Rloc(locator));
+ }
+ insertNBMapping(eid, rlocs);
+ }
+
+ private void insertNBMappingSourceDest(long iid, String src, String dst, String locator) {
+ String srcAddress = MaskUtil.getPrefixAddress(src);
+ String dstAddress = MaskUtil.getPrefixAddress(dst);
+ int srcMask = Integer.parseInt(MaskUtil.getPrefixMask(src));
+ int dstMask = Integer.parseInt(MaskUtil.getPrefixMask(dst));
+ LOG.debug("Adding Northbound mapping in VNI {} for prefix {}|{}, locator {}", iid, src, dst, locator);
+ Eid eid = LispAddressUtil.asSrcDstEid(srcAddress, dstAddress, srcMask, dstMask, iid);
+ List<Rloc> rlocs = Arrays.asList(LispAddressUtil.asIpv4Rloc(locator));
+ insertNBMapping(eid, rlocs);
+ }
+
+ private void insertNBMapping(Eid eid, List<Rloc> rlocs) {
+ MappingRecord record = MappingServiceIntegrationTestUtil.getDefaultMappingRecordBuilder(eid, rlocs).build();
+ mapService.addMapping(MappingOrigin.Northbound, record.getEid(), null, new MappingData(record));
+ sleepForMilliseconds(100);
+ MappingServiceIntegrationTestUtil.printMapCacheState(mapService);
+ }
+
+ private void allowNullAuthenticationForAllIPv4(long iid) {
+ final InstanceIdType iiType = new InstanceIdType(Uint32.valueOf(iid));
+ Eid allIPs = LispAddressUtil.asIpv4PrefixBinaryEid("0.0.0.0/0", iiType);
+ mapService.addAuthenticationKey(allIPs, NULL_AUTH_KEY);
+ }
+
+ private void insertSBMappings(boolean negative, long iid, String... prefixes) {
+ LOG.debug("Adding Southbound mappings in VNI {} for prefixes: {}", iid, prefixes);
+ final InstanceIdType iiType = new InstanceIdType(Uint32.valueOf(iid));
+
+ for (String prefix : prefixes) {
+ MappingRecord record;
+ if (negative) {
+ record = newMappingRecordNegative(prefix, iiType);
+ } else {
+ record = newMappingRecord(prefix, iiType);
+ }
+ mapService.addMapping(MappingOrigin.Southbound, record.getEid(), null,
+ new MappingData(record, System.currentTimeMillis()));
+ }
+ MappingServiceIntegrationTestUtil.printMapCacheState(mapService);
+ }
+
+ private void registerSBMapping(long iid, String prefix, String locator) {
+ LOG.debug("Registering Southbound mapping in VNI {} for prefix {}, locator {}" +
+ " via simulated Map-Register a.k.a. handleMapRegister()", iid, prefix, locator);
+
+ Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid(iid, prefix);
+ Rloc rloc = LispAddressUtil.asIpv4Rloc(locator);
+ MapRegister mr = MappingServiceIntegrationTestUtil.getDefaultMapRegisterBuilder(eid, rloc).build();
+ lms.handleMapRegister(mr);
+ sleepForMilliseconds(100);
+ MappingServiceIntegrationTestUtil.printMapCacheState(mapService);
+ }
+
+ private void removeSBMapping(long iid, String prefix) {
+ LOG.debug("Removing Southbound mapping in VNI {} for prefix {}", iid, prefix);
+ Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid(iid, prefix);
+ mapService.removeMapping(MappingOrigin.Southbound, eid);
+ }
+
+ private MappingRecord newMappingRecord(String prefix, InstanceIdType iid) {
+ final Eid prefixBinary = LispAddressUtil.asIpv4PrefixBinaryEid(prefix, iid);
+ return MappingServiceIntegrationTestUtil.getDefaultMappingRecordBuilder(prefixBinary).build();
+ }
+
+ private MappingRecord newMappingRecordNegative(String prefix, InstanceIdType iid) {
+ final Eid prefixBinary = LispAddressUtil.asIpv4PrefixBinaryEid(prefix, iid);
+ return MappingServiceIntegrationTestUtil.getDefaultMappingRecordBuilder(prefixBinary, (List<Rloc>) null)
+ .setAction(Action.NativelyForward).build();
+ }
+
+ private MapRequest newMapRequest(long iid, String prefix) {
+ final Eid prefixBinary = LispAddressUtil.asIpv4PrefixBinaryEid(prefix, new InstanceIdType(Uint32.valueOf(iid)));
+ return MappingServiceIntegrationTestUtil.getDefaultMapRequestBuilder(prefixBinary).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();
+
+ restartSocket();
+ final SocketReader socketReader = SocketReader.startReadingInStandaloneThread(socket);
+
+ //TEST CASE 1
+ multiSiteScenario.storeSouthboundMappings(false, SITE_A, SITE_B, SITE_C, SITE_D4, SITE_D5);
+ multiSiteScenario.storeNorthMappingSrcDst(SITE_B, SITE_C);
+ multiSiteScenario.storeNorthMappingNegative(SITE_C_NEGATIVE, Action.Drop);
+ 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 generating of SMR messages:
+ // 1) 192.0.2.5/32
+ // 2) 192.0.1.1/32
+ multiSiteScenario.storeNorthMappingSrcDst(SITE_A, SITE_C);
+ 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 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(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 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(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 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(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
+ // 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_A.getHost(1), SITE_A.getHost(5));
+
+ // 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(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_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 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_B, 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_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 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.deleteNorthMappingNegative(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_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);
+
+ socketReader.stopReading();
+
+ }
+
+ /**
+ * TEST SCENARIO B
+ */
+ public void testMultiSiteScenarioB() throws IOException {
+ restartSocket();
+ cleanUP();
+
+ final MultiSiteScenario multiSiteScenario = new MultiSiteScenario(mapService, lms);
+ multiSiteScenario.setCommonAuthentication();
+
+ restartSocket();
+ final SocketReader socketReader = SocketReader.startReadingInStandaloneThread(socket);
+
+ mapService.setLookupPolicy(IMappingService.LookupPolicy.NB_AND_SB);
+ 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,
+ SITE_E_SB);
+ 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(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 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(MULTI_SITE_SLEEP_TIME);
+ multiSiteScenario.checkSMR(socketReader, SITE_C.getEidPrefix(), SITE_B_SB.getHost(5), SITE_A_SB.getHost(5));
+
+ // 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(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);
+ multiSiteScenario.assertPingFails(SITE_B_SB, 5, SITE_C_SB, 4);
+
+
+ //TEST CASE 3
+ // 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(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(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.assertPingWorks(SITE_B_SB, 5, SITE_C_WP_50_2_SB, 4, SITE_D_WP_50_2_SB);
+
+ //TEST CASE 5
+ multiSiteScenario.deleteSouthboundMappings(SITE_D_DELETE_SB);
+ 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.assertPingWorks(SITE_B_SB, 5, SITE_C_WP_50_2_SB, 4);
+
+ //TEST CASE 6
+ multiSiteScenario.deleteNorthMapingSrcDst(SITE_A_SB, SITE_C_WP_50_2_SB);
+ 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(MULTI_SITE_SLEEP_TIME);
+ multiSiteScenario.assertPingFails(SITE_B_SB, 5, SITE_C_WP_50_2_SB, 4);
+
+ socketReader.stopReading();
+