/* * Copyright (c) 2014 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, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.lispflowmapping.southbound.lisp; import static io.netty.buffer.Unpooled.wrappedBuffer; import io.netty.channel.socket.DatagramPacket; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junitx.framework.ArrayAssert; import org.apache.commons.lang3.ArrayUtils; import org.jmock.api.Invocation; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; import org.opendaylight.lispflowmapping.lisp.type.LispMessage; import org.opendaylight.lispflowmapping.lisp.util.ByteUtil; import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil; import org.opendaylight.lispflowmapping.lisp.util.MapNotifyBuilderHelper; import org.opendaylight.lispflowmapping.lisp.util.MaskUtil; import org.opendaylight.lispflowmapping.lisp.serializer.MapNotifySerializer; import org.opendaylight.lispflowmapping.lisp.serializer.MapReplySerializer; import org.opendaylight.lispflowmapping.southbound.lisp.exception.LispMalformedPacketException; import org.opendaylight.lispflowmapping.tools.junit.BaseTestCase; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana.afn.safi.rev130704.AddressFamily; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4Afi; 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.Ipv6PrefixAfi; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix; 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.MapRegister; 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.MessageType; 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.eid.container.Eid; import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItem; 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.mapnotifymessage.MapNotifyBuilder; 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; import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapreplymessage.MapReplyBuilder; import org.opendaylight.yangtools.yang.binding.Notification; public class LispSouthboundServiceTest extends BaseTestCase { private LispSouthboundHandler testedLispService; private NotificationPublishService nps; private byte[] mapRequestPacket; private byte[] mapRegisterPacket; private ValueSaverAction lispNotificationSaver; // private ValueSaverAction mapRegisterSaver; // private ValueSaverAction mapRequestSaver; private MapNotifyBuilder mapNotifyBuilder; private MapReplyBuilder mapReplyBuilder; private MappingRecordBuilder mappingRecordBuilder; private interface MapReplyIpv4SingleLocatorPos { int RECORD_COUNT = 3; int NONCE = 4; int LOCATOR_COUNT = 16; int EID_MASK_LEN = 17; int AFI_TYPE = 22; int EID_PREFIX = 24; int LOC_AFI = 34; int LOCATOR_RBIT = 33; int LOCATOR = 36; } private interface MapReplyIpv4SecondLocatorPos { int FIRST_LOCATOR_IPV4_LENGTH = 12; int LOC_AFI = MapReplyIpv4SingleLocatorPos.LOC_AFI + FIRST_LOCATOR_IPV4_LENGTH; int LOCATOR_RBIT = MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT + FIRST_LOCATOR_IPV4_LENGTH; int LOCATOR = MapReplyIpv4SingleLocatorPos.LOCATOR + FIRST_LOCATOR_IPV4_LENGTH; } @Override @Before public void before() throws Exception { super.before(); // mapResolver = context.mock(IMapResolver.class); // mapServer = context.mock(IMapServer.class); testedLispService = new LispSouthboundHandler(null); nps = context.mock(NotificationPublishService.class); testedLispService.setNotificationProvider(nps); lispNotificationSaver = new ValueSaverAction(); // mapRegisterSaver = new ValueSaverAction(); // mapRequestSaver = new ValueSaverAction(); // SRC: 127.0.0.1:58560 to 127.0.0.1:4342 // LISP(Type = 8 - Encapsulated) // IP: 192.168.136.10 -> 1.2.3.4 // UDP: 56756 // LISP(Type = 1 Map-Request // Record Count: 1 // ITR-RLOC count: 0 // Source EID AFI: 0 // Source EID not present // Nonce: 0x3d8d2acd39c8d608 // ITR-RLOC AFI=1 Address=192.168.136.10 // Record 1: 1.2.3.4/32 mapRequestPacket = extractWSUdpByteArray(new String("0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " // + "0010 00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 " + "0020 00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 " + "0030 00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 " + "0040 03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d " + "0050 2a cd 39 c8 d6 08 00 01 01 02 03 04 00 01 c0 a8 88 0a 00 20 " // + "0060 00 01 01 02 03 04")); mapReplyBuilder = new MapReplyBuilder(); mapReplyBuilder.setMappingRecordItem(new ArrayList()); mapReplyBuilder.setNonce((long) 0); mapReplyBuilder.setEchoNonceEnabled(false); mapReplyBuilder.setProbe(true); mapReplyBuilder.setSecurityEnabled(true); mappingRecordBuilder = new MappingRecordBuilder(); String ip = "0.0.0.0"; mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid(ip + "/0")); mappingRecordBuilder.setLocatorRecord(new ArrayList()); mappingRecordBuilder.setRecordTtl(10); mappingRecordBuilder.setMapVersion((short) 0); mappingRecordBuilder.setMaskLength((short) 0); mappingRecordBuilder.setAction(Action.NativelyForward); mappingRecordBuilder.setAuthoritative(false); // eidToLocatorBuilder.setPrefix(new LispIpv4Address(0)); // mapReply.addEidToLocator(eidToLocatorBuilder); // IP: 192.168.136.10 -> 128.223.156.35 // UDP: 49289 -> 4342 // LISP(Type = 3 Map-Register, P=1, M=1 // Record Counter: 1 // Nonce: 0 // Key ID: 0x0001 // AuthDataLength: 20 Data: // e8:f5:0b:c5:c5:f2:b0:21:27:a8:21:41:04:f3:46:5a:a5:68:89:ec // EID prefix: 153.16.254.1/32 (EID=0x9910FE01), TTL: 10, Authoritative, // No-Action // Local RLOC: 192.168.136.10 (RLOC=0xC0A8880A), Reachable, // Priority/Weight: 1/100, Multicast Priority/Weight: // 255/0 // mapRegisterPacket = extractWSUdpByteArray(new String("0000 00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " // + "0010 00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df " + "0020 9c 23 d6 40 10 f6 00 48 59 a4 38 00 01 01 00 00 " + "0030 00 00 00 00 00 00 00 01 00 14 0e a4 c6 d8 a4 06 " + "0040 71 7c 33 a4 5c 4a 83 1c de 74 53 03 0c ad 00 00 " + "0050 00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " // + "0060 ff 00 00 05 00 01 c0 a8 88 0a")); mapNotifyBuilder = new MapNotifyBuilder(); mapNotifyBuilder.setAuthenticationData(new byte[0]); } @Test @Ignore public void todos() throws Exception { // TODO: MapRequest: usage of Map-Reply-Record in MapRequest packet. // TODO: Non-Encapsulated packets } @Test(expected = LispMalformedPacketException.class) public void mapRegister__IllegalPacket() throws Exception { mapRegisterPacket = extractWSUdpByteArray(new String("0000 00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 " + "0010 00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 " // + "0020 00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 ")); handleMapRegisterPacket(mapRegisterPacket); } @Test(expected = LispMalformedPacketException.class) public void mapRequest__IllegalPacket() throws Exception { mapRequestPacket = extractWSUdpByteArray(new String("0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " // + "0010 00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 " + "0020 00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 " + "0030 00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 " // + "0040 03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d ")); handleMapRequestPacket(mapRequestPacket); } @Test(expected = LispMalformedPacketException.class) public void mapRequest__IllegalEncapsulatedPacket() throws Exception { mapRequestPacket = extractWSUdpByteArray(new String("0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " // + "0010 00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 " // + "0020 00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 ")); handleMapRequestPacket(mapRequestPacket); } private MapRegister lastMapRegister() { assertTrue(lispNotificationSaver.lastValue instanceof AddMapping); AddMapping lastValue = (AddMapping) lispNotificationSaver.lastValue; return lastValue.getMapRegister(); } private MapRequest lastMapRequest() { RequestMapping lastValue = (RequestMapping) lispNotificationSaver.lastValue; return lastValue.getMapRequest(); } @Test public void mapRegister__TwoRlocs() throws Exception { // P Bit & M Bit set // EID prefix: 172.1.1.2/32, TTL: 10, Authoritative, No-Action // Local RLOC: 10.1.0.110, Reachable, Priority/Weight: 1/100, Multicast // Priority/Weight: 255/0 // Local RLOC: 192.168.136.51, Reachable, Priority/Weight: 6/100, // Multicast Priority/Weight: 255/0 mapRegisterPacket = extractWSUdpByteArray(new String("0000 00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 " + "0010 00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 " // + "0020 00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 " // + "0030 00 00 00 00 00 00 00 01 00 14 ae d8 7b d4 9c 59 " // + "0040 e9 35 75 6e f1 29 27 a3 45 20 96 06 c2 e1 00 00 " // + "0050 00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 01 64 " // + "0060 ff 00 00 05 00 01 0a 01 00 6e 06 64 ff 00 00 05 " // + "0070 00 01 c0 a8 88 33")); oneOf(nps).putNotification(with(lispNotificationSaver)); handleMapRegisterPacket(mapRegisterPacket); List eidRecords = lastMapRegister().getMappingRecordItem(); assertEquals(1, eidRecords.size()); MappingRecord eidRecord = eidRecords.get(0).getMappingRecord(); assertEquals(2, eidRecord.getLocatorRecord().size()); assertEquals(LispAddressUtil.asIpv4Rloc("10.1.0.110"), eidRecord.getLocatorRecord().get(0).getRloc()); assertEquals(LispAddressUtil.asIpv4Rloc("192.168.136.51"), eidRecord.getLocatorRecord().get(1).getRloc()); } @Test public void mapRegister__Ipv6Rloc() throws Exception { // P bit (Proxy-Map-Reply): Set // M bit (Want-Map-Notify): Set // Record Counter: 1 // Nonce: 0 // Key ID: 1 // AuthLength: 20 // Authentication Data: 5bc4d44a57e2a55d577a6f89779c004f5da713fb // EID prefix: 2610:d0:ffff:192::1/128, TTL: 10, Authoritative, // No-Action // Local RLOC: 10.0.58.156, Reachable, Priority/Weight: 1/100, Multicast // Priority/Weight: 255/0 mapRegisterPacket = extractWSUdpByteArray(new String("0000 00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " // + "0010 00 68 00 00 40 00 40 11 ea c3 0a 00 3a 9c 0a 00 " // + "0020 01 26 10 f6 10 f6 00 54 f5 9a 38 00 03 01 00 00 " // + "0030 00 00 00 00 00 00 00 01 00 14 22 97 ff 61 ec d8 " // + "0040 0f 91 c6 c4 01 ef 7f bb 77 58 39 5c 92 23 00 00 " // + "0050 00 0a 01 80 10 00 00 00 00 02 26 10 00 d0 ff ff " // + "0060 01 92 00 00 00 00 00 00 00 01 01 64 ff 00 00 05 " // + "0070 00 01 0a 00 3a 9c")); oneOf(nps).putNotification(with(lispNotificationSaver)); handleMapRegisterPacket(mapRegisterPacket); MappingRecord eidToLocatorRecord = lastMapRegister().getMappingRecordItem().get(0).getMappingRecord(); assertEquals("2610:d0:ffff:192:0:0:0:1/128", ((Ipv6Prefix) eidToLocatorRecord.getEid().getAddress()).getIpv6Prefix().getValue()); assertEquals(Ipv6PrefixAfi.class, eidToLocatorRecord.getEid().getAddressType()); assertEquals(LispAddressUtil.asIpv4Rloc("10.0.58.156"), eidToLocatorRecord.getLocatorRecord().get(0).getRloc()); } @Test public void mapRegister__VerifyBasicFields() throws Exception { oneOf(nps).putNotification(with(lispNotificationSaver)); handleMapRegisterPacket(mapRegisterPacket); MappingRecord eidToLocator = lastMapRegister().getMappingRecordItem().get(0).getMappingRecord(); assertEquals(LispAddressUtil.asIpv4PrefixEid("153.16.254.1/32"), eidToLocator.getEid()); assertEquals(1, eidToLocator.getLocatorRecord().size()); assertEquals(LispAddressUtil.asIpv4Rloc("192.168.136.10"), eidToLocator.getLocatorRecord().get(0).getRloc()); } @Test @Ignore public void mapRegister__NoResponseFromMapServerShouldReturnNullPacket() throws Exception { oneOf(nps).putNotification(with(lispNotificationSaver)); mapNotifyBuilder = null; assertNull(handleMapRegisterPacket(mapRegisterPacket)); } @Test public void mapRegister__NonSetMBit() throws Exception { byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000 00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " // + "0010 00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df " // + "0020 9c 23 d6 40 10 f6 00 48 59 a4 38 00 00 01 00 00 " + "0030 00 00 00 00 00 00 00 01 00 14 79 d1 44 66 19 99 " + "0040 83 63 a7 79 6e f0 40 97 54 26 3a 44 b4 eb 00 00 " // + "0050 00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " // + "0060 ff 00 00 05 00 01 c0 a8 88 0a")); stubMapRegister(true); handleMapRegisterPacket(registerWithNonSetMBit); assertFalse(lastMapRegister().isWantMapNotify()); } @Test public void mapRegister__NonSetMBitWithNonZeroReservedBits() throws Exception { byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000 00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " // + "0010 00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df " + "0020 9c 23 d6 40 10 f6 00 48 59 a4 38 00 02 01 00 00 " + "0030 00 00 00 00 00 00 00 01 00 14 c0 c7 c5 2f 57 f6 " + "0040 e7 20 25 3d e8 b2 07 e2 63 de 62 2b 7a 20 00 00 " + "0050 00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " // + "0060 ff 00 00 05 00 01 c0 a8 88 0a")); stubMapRegister(true); handleMapRegisterPacket(registerWithNonSetMBit); assertFalse(lastMapRegister().isWantMapNotify()); } @Test public void mapRegister__SetMBitWithNonZeroReservedBits() throws Exception { byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000 00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " // + "0010 00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df " + "0020 9c 23 d6 40 10 f6 00 48 59 a4 38 00 03 01 00 00 " + "0030 00 00 00 00 00 00 00 01 00 14 a2 72 40 7b 1a ae " + "0040 4e 6b e2 e5 e1 01 40 8a c9 e1 d1 80 cb 72 00 00 " + "0050 00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " // + "0060 ff 00 00 05 00 01 c0 a8 88 0a")); stubMapRegister(true); handleMapRegisterPacket(registerWithNonSetMBit); assertTrue(lastMapRegister().isWantMapNotify()); } @Test @Ignore public void mapRegisterAndNotify__ValidExtraDataParsedSuccessfully() throws Exception { byte[] extraDataPacket = new byte[mapRegisterPacket.length + 3]; extraDataPacket[mapRegisterPacket.length] = 0x9; System.arraycopy(mapRegisterPacket, 0, extraDataPacket, 0, mapRegisterPacket.length); stubMapRegister(true); DatagramPacket dp = new DatagramPacket(wrappedBuffer(extraDataPacket), new InetSocketAddress(0), new InetSocketAddress(0)); testedLispService.handlePacket(dp); // Check map register fields. // XXX: test // byte[] notifyResult = testedLispService.handlePacket(dp).getData(); byte[] notifyResult = lastMapNotifyPacket().content().array(); assertEquals(mapRegisterPacket.length, notifyResult.length); } private DatagramPacket lastMapReplyPacket() { ByteBuffer serialize = MapReplySerializer.getInstance().serialize(mapReplyBuilder.build()); return new DatagramPacket(wrappedBuffer(serialize), new InetSocketAddress(0), new InetSocketAddress(0)); } private DatagramPacket lastMapNotifyPacket() { if (mapNotifyBuilder.getMappingRecordItem() == null) { mapNotifyBuilder.setMappingRecordItem(new ArrayList()); } mapNotifyBuilder.getMappingRecordItem().add(new MappingRecordItemBuilder().setMappingRecord( mappingRecordBuilder.build()).build()); mapNotifyBuilder.setNonce((long) 0); mapNotifyBuilder.setKeyId((short) 0); mapNotifyBuilder.setAuthenticationData(new byte[0]); ByteBuffer serialize = MapNotifySerializer.getInstance().serialize(mapNotifyBuilder.build()); return new DatagramPacket(wrappedBuffer(serialize), new InetSocketAddress(0), new InetSocketAddress(0)); } @Test @Ignore public void mapNotify__VerifyBasicFields() throws Exception { byte registerType = mapRegisterPacket[0]; assertEquals(MessageType.MapRegister.getIntValue(), registerType >> 4); stubMapRegister(true); byte[] result = handleMapRegisterAsByteArray(mapRegisterPacket); assertEquals(mapRegisterPacket.length, result.length); byte expectedType = (byte) (MessageType.MapNotify.getIntValue() << 4); assertHexEquals(expectedType, result[0]); assertHexEquals((byte) 0x00, result[1]); assertHexEquals((byte) 0x00, result[2]); byte[] registerWithoutTypeWithoutAuthenticationData = ArrayUtils.addAll(Arrays.copyOfRange(mapRegisterPacket, 3, 16), Arrays.copyOfRange(mapRegisterPacket, 36, mapRegisterPacket.length)); byte[] notifyWithoutTypeWithOutAuthenticationData = ArrayUtils.addAll(Arrays.copyOfRange(result, 3, 16), Arrays.copyOfRange(result, 36, result.length)); ArrayAssert.assertEquals(registerWithoutTypeWithoutAuthenticationData, notifyWithoutTypeWithOutAuthenticationData); } @Ignore @Test public void mapNotify__VerifyPort() throws Exception { stubMapRegister(true); DatagramPacket notifyPacket = handleMapRegisterPacket(mapRegisterPacket); assertEquals(LispMessage.PORT_NUM, notifyPacket.recipient().getPort()); } @Test public void mapRequest__VerifyBasicFields() throws Exception { oneOf(nps).putNotification(with(lispNotificationSaver)); handleMapRequestAsByteArray(mapRequestPacket); List eids = lastMapRequest().getEidItem(); assertEquals(1, eids.size()); Eid lispAddress = eids.get(0).getEid(); assertEquals(Ipv4PrefixAfi.class, lispAddress.getAddressType()); assertEquals(LispAddressUtil.asIpv4PrefixEid("1.2.3.4/32"), lispAddress); assertEquals(0x3d8d2acd39c8d608L, lastMapRequest().getNonce().longValue()); } @Test public void mapRequest__Ipv6Eid() throws Exception { // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1 // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2 // (2610:d0:ffff:192::2) // MBIT: SET // EID AFI: 2 // Source EID: 2610:d0:ffff:192::1 (2610:d0:ffff:192::1) // ITR-RLOC 1: 10.0.58.156 // Record 1: 2610:d0:ffff:192::2/128 // Map-Reply Record: EID prefix: 2610:d0:ffff:192::1/128, TTL: 10, // Authoritative, No-Action mapRequestPacket = extractWSUdpByteArray(new String("0000 00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " // + "0010 00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 " + "0020 01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 " + "0030 00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 " + "0040 00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 " + "0050 00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 10 00 " + "0060 00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 " + "0070 ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 " + "0080 3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 " + "0090 00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 " // + "00a0 00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 " // + "00b0 00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c")); oneOf(nps).putNotification(with(lispNotificationSaver)); // ret(mapReply); handleMapRequestAsByteArray(mapRequestPacket); assertEquals(LispAddressUtil.asIpv6Eid("2610:d0:ffff:192:0:0:0:1"), lastMapRequest().getSourceEid().getEid()); assertEquals(LispAddressUtil.asIpv6PrefixEid("2610:d0:ffff:192:0:0:0:2/128"), lastMapRequest().getEidItem().get(0).getEid()); } @Ignore @Test public void mapRequest__UsesIpv6EncapsulatedUdpPort() throws Exception { // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1 // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2 // (2610:d0:ffff:192::2) // encapsulated UDP source port: 4342 mapRequestPacket = extractWSUdpByteArray(new String("0000 00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " // + "0010 00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 " + "0020 01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 " + "0030 00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 " + "0040 00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 " + "0050 00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 14 00 " + "0060 00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 " + "0070 ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 " + "0080 3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 " + "0090 00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 " // + "00a0 00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 " // + "00b0 00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c")); oneOf(nps).putNotification(with(lispNotificationSaver)); // ret(mapReply); DatagramPacket replyPacket = handleMapRequestPacket(mapRequestPacket); assertEquals(4342, replyPacket.recipient().getPort()); } @Test public void mapRequest__WithSourceEid() throws Exception { // encapsulated LISP packet // Source EID = 153.16.254.1 mapRequestPacket = extractWSUdpByteArray(new String("0000 00 0c 29 7a ce 83 00 15 17 c6 4a c9 08 00 45 00 " // + "0010 00 78 00 00 40 00 3e 11 ec b1 0a 00 01 26 0a 00 " + "0020 3a 9e 10 f6 10 f6 00 64 c3 a5 80 00 00 00 45 00 " + "0030 00 58 d4 31 00 00 ff 11 31 89 99 10 fe 01 0a 00 " + "0040 14 c8 10 f6 10 f6 00 44 84 ee 10 00 00 01 ba f9 " + "0050 ff 53 27 36 38 3a 00 01 99 10 fe 01 00 01 0a 00 " + "0060 01 26 00 20 00 01 0a 00 14 c8 00 00 00 0a 01 20 " + "0070 10 00 00 00 00 01 99 10 fe 01 01 64 ff 00 00 05 " // + "0080 00 01 0a 00 01 26")); oneOf(nps).putNotification(with(lispNotificationSaver)); // ret(mapReply); handleMapRequestAsByteArray(mapRequestPacket); assertEquals(Ipv4Afi.class, lastMapRequest().getSourceEid().getEid().getAddressType()); } @Test @Ignore public void mapReply__VerifyBasicIPv4Fields() throws Exception { mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid("10.0.20.200/32")); mapReplyBuilder.setNonce(0x3d8d2acd39c8d608L); stubHandleRequest(); byte[] result = handleMapRequestAsByteArray(mapRequestPacket); assertEquals(28, result.length); byte expectedLispMessageType = 2; assertEquals(expectedLispMessageType, (byte) (result[LispMessage.Pos.TYPE] >> 4)); assertEquals(0x3d8d2acd39c8d608L, ByteUtil.getLong(result, MapReplyIpv4SingleLocatorPos.NONCE)); byte expectedRecordCount = (byte) 1; assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]); assertEquals(MaskUtil.getMaskForAddress(mappingRecordBuilder.getEid().getAddress()), result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]); assertEquals(AddressFamily.IpV4.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE)); assertEquals(0x0a0014c8, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.EID_PREFIX)); } @Test @Ignore public void mapReply__VerifyBasicIPv6() throws Exception { mappingRecordBuilder.setEid(LispAddressUtil.asIpv6PrefixEid("0:0:0:0:0:0:0:1/128")); stubHandleRequest(); byte[] result = handleMapRequestAsByteArray(mapRequestPacket); assertEquals(40, result.length); byte expectedRecordCount = (byte) 1; assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]); assertEquals(MaskUtil.getMaskForAddress(mappingRecordBuilder.getEid().getAddress()), result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]); assertEquals(AddressFamily.IpV6.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE)); byte[] expectedIpv6 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; ArrayAssert.assertEquals(expectedIpv6, Arrays.copyOfRange(result, 24, 40)); } @Test @Ignore public void mapReply__VerifyIPv6EidAndLocator() throws Exception { mappingRecordBuilder.setEid(LispAddressUtil.asIpv6PrefixEid("0:0:0:0:0:0:0:1/128")); mappingRecordBuilder.getLocatorRecord().add( new LocatorRecordBuilder().setRloc(LispAddressUtil.asIpv6Rloc("0:0:0:0:0:0:0:2")).build()); stubHandleRequest(); byte[] result = handleMapRequestAsByteArray(mapRequestPacket); assertEquals(64, result.length); byte[] expectedIpv6Eid = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; ArrayAssert.assertEquals(expectedIpv6Eid, Arrays.copyOfRange(result, 24, 40)); byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; ArrayAssert.assertEquals(expectedIpv6Rloc, Arrays.copyOfRange(result, 48, 64)); } @Ignore @Test public void mapReply__UseEncapsulatedUdpPort() throws Exception { stubHandleRequest(); assertEquals(LispMessage.PORT_NUM, handleMapRequestPacket(mapRequestPacket).recipient().getPort()); } @Test @Ignore public void mapReply__WithNonRoutableSingleLocator() throws Exception { mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid("10.0.20.200/32")); mappingRecordBuilder.getLocatorRecord().add( new LocatorRecordBuilder().setRouted(false).setRloc(LispAddressUtil.asIpv4Rloc("4.3.2.1")).build()); stubHandleRequest(); byte[] result = handleMapRequestAsByteArray(mapRequestPacket); assertEquals(0x00, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01); } @Test @Ignore public void mapReply__WithSingleLocator() throws Exception { mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid("10.0.20.200/32")); mappingRecordBuilder.getLocatorRecord().add( new LocatorRecordBuilder().setRouted(true).setRloc(LispAddressUtil.asIpv4Rloc("4.3.2.1")).build()); stubHandleRequest(); byte[] result = handleMapRequestAsByteArray(mapRequestPacket); assertEquals(40, result.length); byte expectedLocCount = 1; assertEquals(expectedLocCount, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]); assertEquals(AddressFamily.IpV4.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOC_AFI)); assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR)); assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01); } @Test @Ignore public void mapReply__WithMultipleLocator() throws Exception { mappingRecordBuilder.getLocatorRecord().add( new LocatorRecordBuilder().setRouted(true).setRloc(LispAddressUtil.asIpv4Rloc("4.3.2.1")).build()); mappingRecordBuilder.getLocatorRecord().add( new LocatorRecordBuilder().setRouted(true).setRloc(LispAddressUtil.asIpv6Rloc("0:0:0:0:0:0:0:1")).build()); stubHandleRequest(); byte[] result = handleMapRequestAsByteArray(mapRequestPacket); assertEquals(64, result.length); assertEquals(2, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]); assertEquals(AddressFamily.IpV4.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOC_AFI)); assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR)); assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01); assertEquals(AddressFamily.IpV6.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SecondLocatorPos.LOC_AFI)); byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; ArrayAssert.assertEquals(expectedIpv6Rloc, Arrays.copyOfRange(result, MapReplyIpv4SecondLocatorPos.LOCATOR, MapReplyIpv4SecondLocatorPos.LOCATOR + 16)); assertEquals(0x01, result[MapReplyIpv4SecondLocatorPos.LOCATOR_RBIT] & 0x01); } @Test public void handleUnknownLispMessage() throws Exception { // IP: 192.168.136.10 -> 128.223.156.35 // UDP: 49289 -> 4342 // LISP(Type = 14 UNKNOWN!!!, P=1, M=1 byte[] unknownTypePacket = extractWSUdpByteArray(new String("0000 00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " // + "0010 00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df " + "0020 9c 23 d6 40 10 f6 00 48 59 a4 F8 00 01 01 00 00 " + "0030 00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 " + "0040 b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 " + "0050 00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " // + "0060 ff 00 00 05 00 01 c0 a8 88 0a")); assertNull(handlePacket(unknownTypePacket)); } @Test public void mapRequest__MultipleItrRlocs() throws Exception { // this is what LISPmob sends when configured multiple RLOCs for single // EID. // ITR-RLOC 1: 10.1.0.111 // ITR-RLOC 2: 192.168.136.51 // mapRequestPacket = extractWSUdpByteArray(new String("0000 00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 " + "0010 00 8a 00 00 40 00 40 11 25 f2 0a 01 00 6f 0a 01 " // + "0020 00 01 10 f6 10 f6 00 76 06 1f 80 00 00 00 45 00 " // + "0030 00 6a d4 31 00 00 ff 11 2a 3e ac 01 01 02 08 08 " // + "0040 08 08 10 f6 10 f6 00 56 63 14 10 00 01 01 79 67 " // + "0050 ff 75 a0 61 66 19 00 01 ac 01 01 02 00 01 0a 01 " // + "0060 00 6f 00 01 c0 a8 88 33 00 20 00 01 08 08 08 08 " // + "0070 00 00 00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 " // + "0080 01 64 ff 00 00 05 00 01 0a 01 00 6f 06 64 ff 00 " // + "0090 00 05 00 01 c0 a8 88 33")); oneOf(nps).putNotification(with(lispNotificationSaver)); handleMapRequestAsByteArray(mapRequestPacket); } private void stubMapRegister(final boolean setNotifyFromRegister) { try { allowing(nps).putNotification(with(lispNotificationSaver)); } catch (InterruptedException e) { } will(new SimpleAction() { @Override public Object invoke(Invocation invocation) throws Throwable { if (setNotifyFromRegister) { MapNotifyBuilderHelper.setFromMapRegister(mapNotifyBuilder, lastMapRegister()); } return null; } }); } private void stubHandleRequest() { try { allowing(nps).putNotification(wany(Notification.class)); } catch (InterruptedException e) { } } private byte[] handleMapRequestAsByteArray(byte[] inPacket) { handleMapRequestPacket(inPacket); return lastMapReplyPacket().content().array(); } private byte[] handleMapRegisterAsByteArray(byte[] inPacket) { handleMapRegisterPacket(inPacket); return lastMapNotifyPacket().content().array(); } private DatagramPacket handleMapRequestPacket(byte[] inPacket) { DatagramPacket dp = new DatagramPacket(wrappedBuffer(inPacket), new InetSocketAddress(0), new InetSocketAddress(0)); // Unless we explicitly set the source port, it will be -1, which breaks some tests // This is till not the real port number, but it's better //dp.setPort(LispMessage.PORT_NUM); testedLispService.handlePacket(dp); return lastMapReplyPacket(); } private DatagramPacket handleMapRegisterPacket(byte[] inPacket) { DatagramPacket dp = new DatagramPacket(wrappedBuffer(inPacket), new InetSocketAddress(0), new InetSocketAddress(0)); // Unless we explicitly set the source port, it will be -1, which breaks some tests // This is till not the real port number, but it's better //dp.setPort(LispMessage.PORT_NUM); testedLispService.handlePacket(dp); if (mapNotifyBuilder == null) { return null; } else { return lastMapNotifyPacket(); } } private DatagramPacket handlePacket(byte[] inPacket) { // TODO get from mock testedLispService.handlePacket(new DatagramPacket(wrappedBuffer(inPacket), new InetSocketAddress(0), new InetSocketAddress(0))); return null; } private byte[] extractWSUdpByteArray(String wiresharkHex) { final int HEADER_LEN = 42; byte[] res = new byte[1000]; String[] split = wiresharkHex.split(" "); int counter = 0; for (String cur : split) { cur = cur.trim(); if (cur.length() == 2) { ++counter; if (counter > HEADER_LEN) { res[counter - HEADER_LEN - 1] = (byte) Integer.parseInt(cur, 16); } } } return Arrays.copyOf(res, counter - HEADER_LEN); } @Test(expected = LispMalformedPacketException.class) public void mapRequest__NoIPITRRLOC() throws Exception { mapRequestPacket = hexToByteBuffer("10 00 " // + "02 " // This means 3 ITR - RLOCs + "01 3d 8d 2a cd 39 c8 d6 08 00 00 " // + "40 05 c0 a8 88 0a 01 02 " // MAC (ITR-RLOC #1 of 3) + "40 05 00 00 00 00 00 00 " // MAC (ITR-RLOC #2 of 3) + "40 05 11 22 34 56 78 90 " // MAC (ITR-RLOC #3 of 3) + "00 20 00 01 01 02 03 04").array(); handleMapRequestPacket(mapRequestPacket); } // @Ignore // @Test // public void mapRequest__IPITRRLOCIsSecond() throws Exception { // mapRequestPacket = hexToByteBuffer("10 00 " // // + "01 " // This means 3 ITR - RLOCs // + "01 3d 8d 2a cd 39 c8 d6 08 00 00 " // // + "40 05 c0 a8 88 0a 01 02 " // MAC (ITR-RLOC #1 of 2) // + "00 01 01 02 03 04 " // IP (ITR-RLOC #2 of 2) // + "00 20 00 01 01 02 03 04").array(); // oneOf(nps).putNotification(with(lispNotificationSaver)); // // ret(mapReply); // DatagramPacket packet = handleMapRequestPacket(mapRequestPacket); // assertEquals(2, lastMapRequest().getItrRlocs().size()); // assertEquals((new LispIpv4Address("1.2.3.4")).getAddress(), // packet.getAddress()); // } // // @Ignore // @Test // public void mapRequest__MULTIPLEIPITRRLOCs() throws Exception { // mapRequestPacket = hexToByteBuffer("10 00 " // // + "01 " // This means 3 ITR - RLOCs // + "01 3d 8d 2a cd 39 c8 d6 08 00 00 " // // + "00 01 01 02 03 04 " // IP (ITR-RLOC #1 of 2) // + "00 01 c0 a8 88 0a " // MAC (ITR-RLOC #2 of 2) // + "00 20 00 01 01 02 03 04").array(); // oneOf(nps).putNotification(with(lispNotificationSaver)); // // ret(mapReply); // DatagramPacket packet = handleMapRequestPacket(mapRequestPacket); // assertEquals(2, lastMapRequest().getItrRloc().size()); // assertEquals((new LispIpv4Address("1.2.3.4")).getAddress(), // packet.getAddress()); // } }