641acb874f8809622e3ea736c98f423edeac9294
[lispflowmapping.git] / mappingservice / southbound / src / test / java / org / opendaylight / lispflowmapping / southbound / lisp / LispSouthboundHandlerTest.java
1 /*
2  * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.lispflowmapping.southbound.lisp;
10
11 import static io.netty.buffer.Unpooled.wrappedBuffer;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertTrue;
15 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.DATA1;
16 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.DATA2;
17 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.DATA3;
18 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.KEY_ID;
19 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.NONCE;
20 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.SITE_ID;
21 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.XTR_ID;
22 import static org.opendaylight.lispflowmapping.southbound.lisp.MapRegisterCacheTestUtil.joinArrays;
23
24 import io.netty.channel.socket.DatagramPacket;
25 import java.net.InetSocketAddress;
26 import java.net.UnknownHostException;
27 import java.nio.ByteBuffer;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.List;
31 import java.util.Map;
32 import junitx.framework.ArrayAssert;
33 import org.apache.commons.lang3.ArrayUtils;
34 import org.junit.Before;
35 import org.junit.BeforeClass;
36 import org.junit.Ignore;
37 import org.junit.Test;
38 import org.mockito.AdditionalMatchers;
39 import org.mockito.ArgumentCaptor;
40 import org.mockito.ArgumentMatchers;
41 import org.mockito.InOrder;
42 import org.mockito.Mockito;
43 import org.opendaylight.lispflowmapping.lisp.serializer.MapNotifySerializer;
44 import org.opendaylight.lispflowmapping.lisp.serializer.MapReplySerializer;
45 import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
46 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
47 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
48 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
49 import org.opendaylight.lispflowmapping.mapcache.AuthKeyDb;
50 import org.opendaylight.lispflowmapping.southbound.ConcurrentLispSouthboundStats;
51 import org.opendaylight.lispflowmapping.southbound.LispSouthboundPlugin;
52 import org.opendaylight.lispflowmapping.southbound.lisp.cache.MapRegisterCache;
53 import org.opendaylight.lispflowmapping.southbound.lisp.exception.LispMalformedPacketException;
54 import org.opendaylight.lispflowmapping.tools.junit.BaseTestCase;
55 import org.opendaylight.mdsal.binding.api.DataBroker;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana.afn.safi.rev130704.AddressFamily;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.InstanceIdType;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.Ipv4BinaryAfi;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.Ipv4PrefixBinaryAfi;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.Ipv6PrefixBinaryAfi;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.AddMapping;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.RequestMapping;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItem;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.key.container.MapRegisterCacheKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.key.container.MapRegisterCacheKeyBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.MapRegisterCacheMetadataBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.value.grouping.MapRegisterCacheValue;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.value.grouping.MapRegisterCacheValueBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapnotifymessage.MapNotifyBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.container.MappingRecord;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.container.MappingRecord.Action;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.container.MappingRecordBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.list.MappingRecordItem;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.list.MappingRecordItemBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkeyBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapreplymessage.MapReplyBuilder;
81 import org.opendaylight.yangtools.yang.binding.Notification;
82 import org.opendaylight.yangtools.yang.common.Uint16;
83 import org.opendaylight.yangtools.yang.common.Uint32;
84
85 public class LispSouthboundHandlerTest extends BaseTestCase {
86
87     private LispSouthboundHandler testedLispService;
88     private byte[] mapRequestPacket;
89     private byte[] mapRegisterPacket;
90     private MapNotifyBuilder mapNotifyBuilder;
91     private MapReplyBuilder mapReplyBuilder;
92     private MappingRecordBuilder mappingRecordBuilder;
93     private MapRegisterCache mapRegisterCache;
94     private LispSouthboundPlugin mockLispSouthboundPlugin;
95     private LispSouthboundPlugin contextMockLispSouthboundPlugin;
96     private static final long CACHE_RECORD_TIMEOUT = 90000;
97
98     private static AuthKeyDb akdb;
99     private static AuthenticationKeyDataListener akdl;
100
101     private interface MapReplyIpv4SingleLocatorPos {
102         int RECORD_COUNT = 3;
103         int NONCE = 4;
104         int LOCATOR_COUNT = 16;
105         int EID_MASK_LEN = 17;
106         int AFI_TYPE = 22;
107         int EID_PREFIX = 24;
108         int LOC_AFI = 34;
109         int LOCATOR_RBIT = 33;
110         int LOCATOR = 36;
111     }
112
113     private interface MapReplyIpv4SecondLocatorPos {
114         int FIRST_LOCATOR_IPV4_LENGTH = 12;
115         int LOC_AFI = MapReplyIpv4SingleLocatorPos.LOC_AFI + FIRST_LOCATOR_IPV4_LENGTH;
116         int LOCATOR_RBIT = MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT + FIRST_LOCATOR_IPV4_LENGTH;
117         int LOCATOR = MapReplyIpv4SingleLocatorPos.LOCATOR + FIRST_LOCATOR_IPV4_LENGTH;
118     }
119
120     @BeforeClass
121     public static void initTests() {
122         akdb = Mockito.mock(AuthKeyDb.class);
123         Mockito.when(akdb.getAuthenticationKey(ArgumentMatchers.eq(LispAddressUtil.asIpv4PrefixBinaryEid(
124                 "10.10.10.10/8"))))
125                 .thenReturn(new MappingAuthkeyBuilder().setKeyType(Uint16.ONE).setKeyString("password").build());
126         Mockito.when(akdb.getAuthenticationKey(ArgumentMatchers.eq(LispAddressUtil.asIpv6PrefixBinaryEid(
127                 "2610:d0:ffff:192:0:0:0:1/128"))))
128                 .thenReturn(new MappingAuthkeyBuilder().setKeyType(Uint16.ONE).setKeyString("password").build());
129         Mockito.when(akdb.getAuthenticationKey(ArgumentMatchers.eq(LispAddressUtil.asIpv4PrefixBinaryEid(
130                 "153.16.254.1/32"))))
131                 .thenReturn(new MappingAuthkeyBuilder().setKeyType(Uint16.ONE).setKeyString("password").build());
132         Mockito.when(akdb.getAuthenticationKey(ArgumentMatchers.eq(LispAddressUtil.asIpv4PrefixBinaryEid(
133                 "125.124.123.122/8", new InstanceIdType(Uint32.valueOf(21))))))
134                 .thenReturn(new MappingAuthkeyBuilder().setKeyType(Uint16.ONE).setKeyString("password").build());
135         Mockito.when(akdb.getAuthenticationKey(ArgumentMatchers.eq(LispAddressUtil.asMacEid(
136                 "0a:0b:0c:0d:0e:0f"))))
137                 .thenReturn(new MappingAuthkeyBuilder().setKeyType(Uint16.ONE).setKeyString("password").build());
138         Mockito.when(akdb.getAuthenticationKey(ArgumentMatchers.eq(LispAddressUtil.asIpv6PrefixBinaryEid(
139                 "f0f:f0f:f0f:f0f:f0f:f0f:f0f:f0f/8"))))
140                 .thenReturn(new MappingAuthkeyBuilder().setKeyType(Uint16.ONE).setKeyString("password").build());
141         Mockito.when(akdb.getAuthenticationKey(ArgumentMatchers.eq(LispAddressUtil.asIpv4PrefixBinaryEid(
142                 "172.1.1.2/32"))))
143                 .thenReturn(new MappingAuthkeyBuilder().setKeyType(Uint16.ONE).setKeyString("password").build());
144
145         akdl = Mockito.mock(AuthenticationKeyDataListener.class);
146         Mockito.when(akdl.authKeysForEidsUnchanged(Mockito.anyMap(), Mockito.anyLong())).thenReturn(true);
147     }
148
149     @Override
150     @Before
151     public void before() throws Exception {
152         super.before();
153         mockLispSouthboundPlugin = Mockito.mock(LispSouthboundPlugin.class);
154         contextMockLispSouthboundPlugin = context.mock(LispSouthboundPlugin.class);
155         Mockito.when(mockLispSouthboundPlugin.isMapRegisterCacheEnabled()).thenReturn(true);
156         Mockito.when(mockLispSouthboundPlugin.getMapRegisterCacheTimeout()).thenReturn(CACHE_RECORD_TIMEOUT);
157         mapRegisterCache = new MapRegisterCache();
158         Mockito.when(mockLispSouthboundPlugin.getMapRegisterCache()).thenReturn(mapRegisterCache);
159         Mockito.when(mockLispSouthboundPlugin.getDataBroker()).thenReturn(Mockito.mock(DataBroker.class));
160         Mockito.when(mockLispSouthboundPlugin.getAkdb()).thenReturn(akdb);
161         Mockito.when(mockLispSouthboundPlugin.getAuthenticationKeyDataListener()).thenReturn(akdl);
162         ConcurrentLispSouthboundStats lispSouthboundStats = new ConcurrentLispSouthboundStats();
163         Mockito.when(mockLispSouthboundPlugin.getStats()).thenReturn(lispSouthboundStats);
164         testedLispService = new LispSouthboundHandler(mockLispSouthboundPlugin);
165
166         // SRC: 127.0.0.1:58560 to 127.0.0.1:4342
167         // LISP(Type = 8 - Encapsulated)
168         // IP: 192.168.136.10 -> 1.2.3.4
169         // UDP: 56756
170         // LISP(Type = 1 Map-Request
171         // Record Count: 1
172         // ITR-RLOC count: 0
173         // Source EID AFI: 0
174         // Source EID not present
175         // Nonce: 0x3d8d2acd39c8d608
176         // ITR-RLOC AFI=1 Address=192.168.136.10
177         // Record 1: 1.2.3.4/32
178         mapRequestPacket = extractWSUdpByteArray(
179                   "0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
180                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
181                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "
182                 + "0030   00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 "
183                 + "0040   03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d "
184                 + "0050   2a cd 39 c8 d6 08 00 01 01 02 03 04 00 01 c0 a8 88 0a 00 20 "
185                 + "0060   00 01 01 02 03 04");
186         mapReplyBuilder = new MapReplyBuilder();
187         mapReplyBuilder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
188         mapReplyBuilder.setNonce((long) 0);
189         mapReplyBuilder.setEchoNonceEnabled(false);
190         mapReplyBuilder.setProbe(true);
191         mapReplyBuilder.setSecurityEnabled(true);
192         mappingRecordBuilder = new MappingRecordBuilder();
193         String ip = "0.0.0.0";
194         mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid(ip + "/0"));
195         mappingRecordBuilder.setLocatorRecord(new ArrayList<LocatorRecord>());
196         mappingRecordBuilder.setRecordTtl(10);
197         mappingRecordBuilder.setMapVersion((short) 0);
198         mappingRecordBuilder.setAction(Action.NativelyForward);
199         mappingRecordBuilder.setAuthoritative(false);
200         // eidToLocatorBuilder.setPrefix(new LispIpv4Address(0));
201         // mapReply.addEidToLocator(eidToLocatorBuilder);
202
203         // IP: 192.168.136.10 -> 128.223.156.35
204         // UDP: 49289 -> 4342
205         // LISP(Type = 3 Map-Register, P=1, M=1
206         // Record Counter: 1
207         // Nonce: 0
208         // Key ID: 0x0001
209         // AuthDataLength: 20 Data:
210         // e8:f5:0b:c5:c5:f2:b0:21:27:a8:21:41:04:f3:46:5a:a5:68:89:ec
211         // EID prefix: 153.16.254.1/32 (EID=0x9910FE01), TTL: 10, Authoritative,
212         // No-Action
213         // Local RLOC: 192.168.136.10 (RLOC=0xC0A8880A), Reachable,
214         // Priority/Weight: 1/100, Multicast Priority/Weight:
215         // 255/0
216         //
217
218         mapRegisterPacket = extractWSUdpByteArray(
219                   "0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 "
220                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
221                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 01 01 00 00 "
222                 + "0030   00 00 00 00 00 00 00 01 00 14 0e a4 c6 d8 a4 06 "
223                 + "0040   71 7c 33 a4 5c 4a 83 1c de 74 53 03 0c ad 00 00 "
224                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 "
225                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a");
226         mapNotifyBuilder = new MapNotifyBuilder();
227         mapNotifyBuilder.setAuthenticationData(new byte[0]);
228     }
229
230     @Test
231     @Ignore
232     public void todos() throws Exception {
233
234         // TODO: MapRequest: usage of Map-Reply-Record in MapRequest packet.
235         // TODO: Non-Encapsulated packets
236     }
237
238     @Test(expected = LispMalformedPacketException.class)
239     public void mapRegister__IllegalPacket() throws Exception {
240         mapRegisterPacket = extractWSUdpByteArray(
241                   "0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
242                 + "0010   00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 "
243                 + "0020   00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 ");
244
245         handleMapRegisterPacket(mapRegisterPacket);
246     }
247
248     @Test(expected = LispMalformedPacketException.class)
249     public void mapRequest__IllegalPacket() throws Exception {
250         mapRequestPacket = extractWSUdpByteArray(
251                   "0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
252                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
253                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "
254                 + "0030   00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 "
255                 + "0040   03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d ");
256         handleMapRequestPacket(mapRequestPacket);
257     }
258
259     @Test(expected = LispMalformedPacketException.class)
260     public void mapRequest__IllegalEncapsulatedPacket() throws Exception {
261         mapRequestPacket = extractWSUdpByteArray(
262                   "0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 "
263                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
264                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 ");
265         handleMapRequestPacket(mapRequestPacket);
266     }
267
268     @Test
269     public void mapRegister__TwoRlocs() throws Exception {
270         // P Bit & M Bit set
271         // EID prefix: 172.1.1.2/32, TTL: 10, Authoritative, No-Action
272         // Local RLOC: 10.1.0.110, Reachable, Priority/Weight: 1/100, Multicast
273         // Priority/Weight: 255/0
274         // Local RLOC: 192.168.136.51, Reachable, Priority/Weight: 6/100,
275         // Multicast Priority/Weight: 255/0
276         mapRegisterPacket = extractWSUdpByteArray(
277                   "0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
278                 + "0010   00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 "
279                 + "0020   00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 "
280                 + "0030   00 00 00 00 00 00 00 01 00 14 ae d8 7b d4 9c 59 "
281                 + "0040   e9 35 75 6e f1 29 27 a3 45 20 96 06 c2 e1 00 00 "
282                 + "0050   00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 01 64 "
283                 + "0060   ff 00 00 05 00 01 0a 01 00 6e 06 64 ff 00 00 05 "
284                 + "0070   00 01 c0 a8 88 33");
285
286         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
287         handleMapRegisterPacket(mapRegisterPacket);
288         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
289
290         List<MappingRecordItem> eidRecords = captor.getValue().getMapRegister().getMappingRecordItem();
291         assertEquals(1, eidRecords.size());
292         MappingRecord eidRecord = eidRecords.get(0).getMappingRecord();
293         assertEquals(2, eidRecord.getLocatorRecord().size());
294         assertEquals(LispAddressUtil.asIpv4Rloc("10.1.0.110"), eidRecord.getLocatorRecord().get(0).getRloc());
295         assertEquals(LispAddressUtil.asIpv4Rloc("192.168.136.51"), eidRecord.getLocatorRecord().get(1).getRloc());
296     }
297
298     @Test
299     public void mapRegister__Ipv6Rloc() throws Exception {
300         // P bit (Proxy-Map-Reply): Set
301         // M bit (Want-Map-Notify): Set
302         // Record Counter: 1
303         // Nonce: 0
304         // Key ID: 1
305         // AuthLength: 20
306         // Authentication Data: 5bc4d44a57e2a55d577a6f89779c004f5da713fb
307         // EID prefix: 2610:d0:ffff:192::1/128, TTL: 10, Authoritative,
308         // No-Action
309         // Local RLOC: 10.0.58.156, Reachable, Priority/Weight: 1/100, Multicast
310         // Priority/Weight: 255/0
311
312         mapRegisterPacket = extractWSUdpByteArray(
313                   "0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 "
314                 + "0010   00 68 00 00 40 00 40 11 ea c3 0a 00 3a 9c 0a 00 "
315                 + "0020   01 26 10 f6 10 f6 00 54 f5 9a 38 00 03 01 00 00 "
316                 + "0030   00 00 00 00 00 00 00 01 00 14 22 97 ff 61 ec d8 "
317                 + "0040   0f 91 c6 c4 01 ef 7f bb 77 58 39 5c 92 23 00 00 "
318                 + "0050   00 0a 01 80 10 00 00 00 00 02 26 10 00 d0 ff ff "
319                 + "0060   01 92 00 00 00 00 00 00 00 01 01 64 ff 00 00 05 "
320                 + "0070   00 01 0a 00 3a 9c");
321
322         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
323         handleMapRegisterPacket(mapRegisterPacket);
324         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
325         MappingRecord eidToLocatorRecord =
326                 captor.getValue().getMapRegister().getMappingRecordItem().get(0).getMappingRecord();
327
328         assertEquals(LispAddressUtil.asIpv6PrefixBinaryEid("2610:d0:ffff:192:0:0:0:1/128"),
329                 eidToLocatorRecord.getEid());
330         assertEquals(Ipv6PrefixBinaryAfi.VALUE, eidToLocatorRecord.getEid().getAddressType());
331
332         assertEquals(LispAddressUtil.asIpv4Rloc("10.0.58.156"), eidToLocatorRecord.getLocatorRecord().get(0).getRloc());
333     }
334
335     @Test
336     public void mapRegister__VerifyBasicFields() throws Exception {
337         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
338         handleMapRegisterPacket(mapRegisterPacket);
339         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
340         MappingRecord eidToLocator =
341                 captor.getValue().getMapRegister().getMappingRecordItem().get(0).getMappingRecord();
342
343         assertEquals(LispAddressUtil.asIpv4PrefixBinaryEid("153.16.254.1/32"), eidToLocator.getEid());
344         assertEquals(1, eidToLocator.getLocatorRecord().size());
345         assertEquals(LispAddressUtil.asIpv4Rloc("192.168.136.10"), eidToLocator.getLocatorRecord().get(0).getRloc());
346     }
347
348     @Test
349     public void mapRegister__NoResponseFromMapServerShouldReturnNullPacket() throws Exception {
350         mapNotifyBuilder = null;
351         assertNull(handleMapRegisterPacket(mapRegisterPacket));
352     }
353
354     @Test
355     public void mapRegister__NonSetMBit() throws Exception {
356         byte[] registerWithNonSetMBit = extractWSUdpByteArray(
357                   "0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 "
358                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
359                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 00 01 00 00 "
360                 + "0030   00 00 00 00 00 00 00 01 00 14 79 d1 44 66 19 99 "
361                 + "0040   83 63 a7 79 6e f0 40 97 54 26 3a 44 b4 eb 00 00 "
362                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 "
363                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a");
364
365         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
366         handleMapRegisterPacket(registerWithNonSetMBit);
367         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
368         assertFalse(captor.getValue().getMapRegister().getWantMapNotify());
369     }
370
371     @Test
372     public void mapRegister__NonSetMBitWithNonZeroReservedBits() throws Exception {
373         byte[] registerWithNonSetMBit = extractWSUdpByteArray(
374                   "0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 "
375                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
376                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 02 01 00 00 "
377                 + "0030   00 00 00 00 00 00 00 01 00 14 c0 c7 c5 2f 57 f6 "
378                 + "0040   e7 20 25 3d e8 b2 07 e2 63 de 62 2b 7a 20 00 00 "
379                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 "
380                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a");
381
382         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
383         handleMapRegisterPacket(registerWithNonSetMBit);
384         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
385         assertFalse(captor.getValue().getMapRegister().getWantMapNotify());
386     }
387
388     @Test
389     public void mapRegister__SetMBitWithNonZeroReservedBits() throws Exception {
390         byte[] registerWithNonSetMBit = extractWSUdpByteArray(
391                   "0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 "
392                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
393                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 03 01 00 00 "
394                 + "0030   00 00 00 00 00 00 00 01 00 14 a2 72 40 7b 1a ae "
395                 + "0040   4e 6b e2 e5 e1 01 40 8a c9 e1 d1 80 cb 72 00 00 "
396                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 "
397                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a");
398
399         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
400         handleMapRegisterPacket(registerWithNonSetMBit);
401         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
402         assertTrue(captor.getValue().getMapRegister().getWantMapNotify());
403     }
404
405     /**
406      * Tests whether handling of map-register message will generate mapping-keep-alive notification.
407      */
408     @Test
409     public void mapRegister_isMappingKeepAliveAndMapNotifyGenerated() throws InterruptedException,
410             UnknownHostException {
411         byte[] eidPrefixAfi = new byte[] {
412             //eid-prefix-afi
413             0x00, 0x01
414         };
415
416         byte[] eidPrefix = new byte[] {
417             //ipv4 address
418             0x0a, 0x0a, 0x0a, 0x0a
419         };
420
421         //send stream of byte -> map register message
422         InOrder inOrder = Mockito.inOrder(mockLispSouthboundPlugin);
423         final MapRegisterCacheKey cacheKey = MapRegisterCacheTestUtil.createMapRegisterCacheKey(eidPrefix);
424         MapRegisterCacheTestUtil.beforeMapRegisterInvocationValidation(cacheKey, mapRegisterCache);
425         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
426         mapRegisterInvocationForCacheTest(eidPrefixAfi, eidPrefix);
427         inOrder.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
428         MapRegisterCacheTestUtil.afterMapRegisterInvocationValidation(
429                 cacheKey, mapRegisterCache, eidPrefixAfi, eidPrefix);
430
431         //sending the same byte stream -> map register second time
432         captor = ArgumentCaptor.forClass(AddMapping.class);
433         mapRegisterInvocationForCacheTest(eidPrefixAfi, eidPrefix);
434         inOrder.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
435
436         //mapping-keep-alive message should be generated
437         MapRegisterCacheTestUtil.afterSecondMapRegisterInvocationValidation(
438                 mockLispSouthboundPlugin, eidPrefixAfi, eidPrefix);
439     }
440
441     void mapRegisterInvocationForCacheTest(byte[] eidPrefixAfi, byte[] eidPrefix) {
442         mapRegisterInvocationForCacheTest(eidPrefixAfi, eidPrefix, MapRegisterCacheTestUtil.AUTH_DATA);
443     }
444
445     void mapRegisterInvocationForCacheTest(byte[] eidPrefixAfi, byte[] eidPrefix, byte[] authenticationData) {
446         final byte[] mapRegisterMessage = MapRegisterCacheTestUtil.joinArrays(DATA1, NONCE, KEY_ID,
447                 authenticationData, DATA2, eidPrefixAfi, eidPrefix, DATA3, XTR_ID, SITE_ID);
448         handlePacket(mapRegisterMessage);
449     }
450
451     /**
452      * It tests whether map register message is stored to local cache with Ipv4 EidPrefix.
453      */
454     @Test
455     public void mapRegister_cacheWithEidPrefixIpv4Test() throws InterruptedException {
456         byte[] eidPrefixAfi = new byte[] {
457             //eid-prefix-afi
458             0x00, 0x01
459         };
460
461         byte[] eidPrefix = new byte[] {
462             //ipv4 address
463             0x0a, 0x0a, 0x0a, 0x0a
464         };
465
466         cacheTest(eidPrefixAfi, eidPrefix, MapRegisterCacheTestUtil.AUTH_DATA);
467     }
468
469     /**
470      * It tests whether map register message is stored to local cache with Ipv6 EidPrefix.
471      */
472     @Test
473     public void mapRegister_cacheWithEidPrefixIpv6Test() throws InterruptedException {
474         byte[] eidPrefixAfi = new byte[] {
475             //eid-prefix-afi
476             0x00, 0x02
477         };
478
479         byte[] eidPrefix = new byte[] {
480             //ipv6 address
481             0x0f, 0x0f, 0x0f, 0x0f,
482             //ipv6 address
483             0x0f, 0x0f, 0x0f, 0x0f,
484             //ipv6 address
485             0x0f, 0x0f, 0x0f, 0x0f,
486             //ipv6 address
487             0x0f, 0x0f, 0x0f, 0x0f
488         };
489
490         byte[] authenticationData = new byte[] {
491             0x00, 0x14,
492             0x41,(byte)0x83,0x13,0x7C,
493             0x48,(byte)0xEE,0x75,(byte)0x9A,
494             0x4,(byte)0x8C,0x46,(byte)0xA6,
495             0x1B,0x13,(byte)0xC8,0x4D,
496             (byte)0xA1,0x17,0x53,(byte)0xC3
497         };
498
499         cacheTest(eidPrefixAfi, eidPrefix, authenticationData);
500     }
501
502     /**
503      * It tests whether map register message is stored to local cache with Mac 48bits EidPrefix.
504      */
505     @Test
506     public void mapRegister_cacheWithEidPrefixMac48Test() throws InterruptedException {
507         byte[] eidPrefixAfi = new byte[] {
508             //eid-prefix-afi
509             0x40, 0x05
510         };
511
512         byte[] eidPrefix = new byte[] {
513             //mac address
514             0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
515         };
516
517         byte[] authenticationData = new byte[] {
518             0x00, 0x14,
519             (byte)0xB2,(byte)0x8E,0x6,(byte)0x9D,
520             0x61,(byte)0xD8,0xC,0x24,
521             (byte)0x80,0x61,0x5A,0x20,
522             0xD,0x50,0x5E,(byte)0xAE,
523             0x47,(byte)0xF7,(byte)0x86,0x36
524         };
525         cacheTest(eidPrefixAfi, eidPrefix, authenticationData);
526     }
527
528     /**
529      * It tests whether map register message is stored to local cache with Lcaf EidPrefix (inside Ipv4).
530      */
531     @Test
532     public void mapRegister_cacheWithEidPrefixLcafTest() throws InterruptedException {
533         byte[] eidPrefixAfi = new byte[] {
534             //eid-prefix-afi
535             0x40, 0x03
536         };
537
538         //following lcaf prefixed variables are defined according to https://tools.ietf
539         // .org/html/draft-ietf-lisp-lcaf-12#section-4.1
540         byte[] lcafRsvd1 = new byte[]{0x00};
541         byte[] lcafFlags = new byte[]{0x00};
542         byte[] lcafType = new byte[]{0x02};
543         byte[] lcafIIDMaskLength = new byte[]{0x20};
544         byte[] lcafLength = new byte[] {0x00, 0x0a};
545         byte[] lcafInstanceId = new byte[]{0x00, 0x00, 0x00, 0x15};
546         byte[] lcafAfi = new byte[] {0x00, 0x01};
547         byte[] lcafAddress = new byte[] {0x7d, 0x7c, 0x7b, 0x7a};
548
549         byte[] eidPrefix = joinArrays(lcafRsvd1, lcafFlags, lcafType, lcafIIDMaskLength, lcafLength, lcafInstanceId,
550                 lcafAfi, lcafAddress);
551
552         byte[] authenticationData = new byte[] {
553             //authentication data length
554             0x00, 0x14,
555             //auth data
556             0x68, 0x1d, (byte) 0x9e, 0x6e,
557             //auth data
558             0x5e, 0x32, (byte) 0x88, 0x1a,
559             //auth data
560             (byte) 0xae, 0x6b, (byte) 0xe3, 0x40,
561             //auth data
562             0x30, (byte) 0x0b, (byte) 0xb6, (byte) 0xa0,
563             //auth data
564             0x71, (byte) 0xf4, (byte) 0x8c, 0x5f
565         };
566
567
568         cacheTest(eidPrefixAfi, eidPrefix, authenticationData);
569     }
570
571     /**
572      * It tests whether map register message is stored to local cache.
573      */
574     public void cacheTest(byte[] eidPrefixAfi, byte[] eidPrefix, byte[] authenticationData) throws
575             InterruptedException {
576         final MapRegisterCacheKey mapRegisterCacheKey = MapRegisterCacheTestUtil.createMapRegisterCacheKey(eidPrefix);
577
578         MapRegisterCacheTestUtil.beforeMapRegisterInvocationValidation(mapRegisterCacheKey, mapRegisterCache);
579         ArgumentCaptor<AddMapping> captor = ArgumentCaptor.forClass(AddMapping.class);
580         mapRegisterInvocationForCacheTest(eidPrefixAfi, eidPrefix, authenticationData);
581         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
582         MapRegisterCacheTestUtil.afterMapRegisterInvocationValidation(
583                 mapRegisterCacheKey, mapRegisterCache, eidPrefixAfi, eidPrefix);
584     }
585
586
587     /*
588         Checks whether old record from cache will expire and is replaced with new record.
589
590         add to empty cache record with timestamp older then 90 second - one object
591         add the same entry through calling of handleMapRegister
592         check that removeEntry() and addEntry() (or refreshEntry() was called on mocked object for mapRegisterCache
593     */
594     @Test
595     public void mapRegister_cacheRecordExpirationTest() throws InterruptedException {
596         //tests handling of map register message when next message comes:
597
598         //after cache entry timeout
599         cacheRecordExpirationTest(true);
600
601         //before cache entry timout
602         cacheRecordExpirationTest(false);
603     }
604
605     private void cacheRecordExpirationTest(boolean cacheRecordTimeouted) throws InterruptedException {
606         mapRegisterCache = Mockito.mock(MapRegisterCache.class);
607         Mockito.when(mockLispSouthboundPlugin.getMapRegisterCache()).thenReturn(mapRegisterCache);
608
609         final byte[] eidPrefixAfi = new byte[] {0x00, 0x01};
610         final byte[] eidPrefix = new byte[] {0x0a, 0x0a, 0x0a, 0x0a};
611
612         MapRegisterCacheKeyBuilder cacheKeyBld = new MapRegisterCacheKeyBuilder();
613         cacheKeyBld.setXtrId(XTR_ID);
614         cacheKeyBld.setEidPrefix(eidPrefix);
615         cacheKeyBld.setSiteId(SITE_ID);
616
617         MapRegisterCacheMetadataBuilder cacheMetadataBld = new MapRegisterCacheMetadataBuilder();
618         cacheMetadataBld.setTimestamp(System.currentTimeMillis() - (cacheRecordTimeouted ? CACHE_RECORD_TIMEOUT : 0L));
619         cacheMetadataBld.setWantMapNotify(false);
620         cacheMetadataBld.setEidLispAddress(Map.of());
621
622         MapRegisterCacheValueBuilder cacheValueBld = new MapRegisterCacheValueBuilder();
623         cacheValueBld.setMapRegisterCacheMetadata(cacheMetadataBld.build());
624         cacheValueBld.setPacketData(MapRegisterCacheTestUtil.joinArrays(DATA1, KEY_ID, DATA2, eidPrefixAfi,
625                 eidPrefix, DATA3, XTR_ID, SITE_ID));
626
627
628         final MapRegisterCacheKey cacheKey = cacheKeyBld.build();
629         final MapRegisterCacheValue cacheValue = cacheValueBld.build();
630
631         Mockito.when(mapRegisterCache.getEntry(Mockito.eq(cacheKey))).thenReturn(cacheRecordTimeouted ? null :
632                 cacheValue);
633         Mockito.when(mapRegisterCache.refreshEntry(Mockito.eq(cacheKey))).thenReturn(cacheValue);
634
635         mapRegisterInvocationForCacheTest(eidPrefixAfi, eidPrefix);
636         Mockito.verify(mockLispSouthboundPlugin, Mockito.atLeastOnce()).sendNotificationIfPossible(
637                 Mockito.any(AddMapping.class));
638
639         InOrder inOrder = Mockito.inOrder(mapRegisterCache);
640         inOrder.verify(mapRegisterCache).getEntry(Mockito.eq(cacheKey));
641
642         if (cacheRecordTimeouted) {
643             inOrder.verify(mapRegisterCache).addEntry(Mockito.eq(cacheKey), AdditionalMatchers.not(Mockito.eq(
644                     cacheValue)));
645         } else {
646             inOrder.verify(mapRegisterCache).refreshEntry(Mockito.eq(cacheKey));
647         }
648     }
649
650     @Test
651     @Ignore
652     public void mapRegisterAndNotify__ValidExtraDataParsedSuccessfully() throws Exception {
653         byte[] extraDataPacket = new byte[mapRegisterPacket.length + 3];
654         extraDataPacket[mapRegisterPacket.length] = 0x9;
655         System.arraycopy(mapRegisterPacket, 0, extraDataPacket, 0, mapRegisterPacket.length);
656
657         DatagramPacket dp = new DatagramPacket(wrappedBuffer(extraDataPacket), new InetSocketAddress(0),
658                 new InetSocketAddress(0));
659         testedLispService.handlePacket(dp);
660         // Check map register fields.
661         // XXX: test
662         // byte[] notifyResult = testedLispService.handlePacket(dp).getData();
663         byte[] notifyResult = lastMapNotifyPacket().content().array();
664         assertEquals(mapRegisterPacket.length, notifyResult.length);
665
666     }
667
668     private DatagramPacket lastMapReplyPacket() {
669         ByteBuffer serialize = MapReplySerializer.getInstance().serialize(mapReplyBuilder.build());
670         return new DatagramPacket(wrappedBuffer(serialize), new InetSocketAddress(0), new InetSocketAddress(0));
671     }
672
673     private DatagramPacket lastMapNotifyPacket() {
674         if (mapNotifyBuilder.getMappingRecordItem() == null) {
675             mapNotifyBuilder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
676         }
677         mapNotifyBuilder.getMappingRecordItem().add(new MappingRecordItemBuilder()
678                 .setMappingRecordItemId("foo")
679                 .setMappingRecord(mappingRecordBuilder.build()).build());
680         mapNotifyBuilder.setNonce((long) 0);
681         mapNotifyBuilder.setKeyId((short) 0);
682         mapNotifyBuilder.setAuthenticationData(new byte[0]);
683         ByteBuffer serialize = MapNotifySerializer.getInstance().serialize(mapNotifyBuilder.build());
684         return new DatagramPacket(wrappedBuffer(serialize), new InetSocketAddress(0), new InetSocketAddress(0));
685     }
686
687     @Test
688     @Ignore
689     public void mapNotify__VerifyBasicFields() throws Exception {
690         byte registerType = mapRegisterPacket[0];
691         assertEquals(MessageType.MapRegister.getIntValue(), registerType >> 4);
692
693         byte[] result = handleMapRegisterAsByteArray(mapRegisterPacket);
694
695         assertEquals(mapRegisterPacket.length, result.length);
696
697         byte expectedType = (byte) (MessageType.MapNotify.getIntValue() << 4);
698         assertHexEquals(expectedType, result[0]);
699         assertHexEquals((byte) 0x00, result[1]);
700         assertHexEquals((byte) 0x00, result[2]);
701
702         byte[] registerWithoutTypeWithoutAuthenticationData = ArrayUtils.addAll(
703                 Arrays.copyOfRange(mapRegisterPacket, 3, 16),
704                 Arrays.copyOfRange(mapRegisterPacket, 36, mapRegisterPacket.length));
705         byte[] notifyWithoutTypeWithOutAuthenticationData = ArrayUtils.addAll(Arrays.copyOfRange(result, 3, 16),
706                 Arrays.copyOfRange(result, 36, result.length));
707         ArrayAssert.assertEquals(registerWithoutTypeWithoutAuthenticationData,
708                 notifyWithoutTypeWithOutAuthenticationData);
709     }
710
711     @Ignore
712     @Test
713     public void mapNotify__VerifyPort() throws Exception {
714         DatagramPacket notifyPacket = handleMapRegisterPacket(mapRegisterPacket);
715         assertEquals(LispMessage.PORT_NUM, notifyPacket.recipient().getPort());
716     }
717
718     @Test
719     public void mapRequest__VerifyBasicFields() throws Exception {
720         ArgumentCaptor<RequestMapping> captor = ArgumentCaptor.forClass(RequestMapping.class);
721         handleMapRequestAsByteArray(mapRequestPacket);
722         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
723         List<EidItem> eids = captor.getValue().getMapRequest().getEidItem();
724         assertEquals(1, eids.size());
725         Eid lispAddress = eids.get(0).getEid();
726         assertEquals(Ipv4PrefixBinaryAfi.VALUE, lispAddress.getAddressType());
727         assertEquals(LispAddressUtil.asIpv4PrefixBinaryEid("1.2.3.4/32"), lispAddress);
728         assertEquals(0x3d8d2acd39c8d608L, captor.getValue().getMapRequest().getNonce().longValue());
729     }
730
731     @Test
732     public void mapRequest__Ipv6Eid() throws Exception {
733         // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1
734         // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2
735         // (2610:d0:ffff:192::2)
736         // MBIT: SET
737         // EID AFI: 2
738         // Source EID: 2610:d0:ffff:192::1 (2610:d0:ffff:192::1)
739         // ITR-RLOC 1: 10.0.58.156
740         // Record 1: 2610:d0:ffff:192::2/128
741         // Map-Reply Record: EID prefix: 2610:d0:ffff:192::1/128, TTL: 10,
742         // Authoritative, No-Action
743
744         mapRequestPacket = extractWSUdpByteArray(
745                   "0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 "
746                 + "0010   00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 "
747                 + "0020   01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 "
748                 + "0030   00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 "
749                 + "0040   00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 "
750                 + "0050   00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 10 00 "
751                 + "0060   00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 "
752                 + "0070   ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 "
753                 + "0080   3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 "
754                 + "0090   00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 "
755                 + "00a0   00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 "
756                 + "00b0   00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c");
757
758         ArgumentCaptor<RequestMapping> captor = ArgumentCaptor.forClass(RequestMapping.class);
759         handleMapRequestAsByteArray(mapRequestPacket);
760         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
761         assertEquals(LispAddressUtil.asIpv6Eid("2610:d0:ffff:192:0:0:0:1"),
762                 captor.getValue().getMapRequest().getSourceEid().getEid());
763         assertEquals(LispAddressUtil.asIpv6PrefixBinaryEid("2610:d0:ffff:192:0:0:0:2/128"),
764                 captor.getValue().getMapRequest().getEidItem().get(0).getEid());
765     }
766
767     @Ignore
768     @Test
769     public void mapRequest__UsesIpv6EncapsulatedUdpPort() throws Exception {
770         // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1
771         // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2
772         // (2610:d0:ffff:192::2)
773         // encapsulated UDP source port: 4342
774
775         mapRequestPacket = extractWSUdpByteArray(
776                   "0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 "
777                 + "0010   00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 "
778                 + "0020   01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 "
779                 + "0030   00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 "
780                 + "0040   00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 "
781                 + "0050   00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 14 00 "
782                 + "0060   00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 "
783                 + "0070   ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 "
784                 + "0080   3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 "
785                 + "0090   00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 "
786                 + "00a0   00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 "
787                 + "00b0   00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c");
788
789         ArgumentCaptor<RequestMapping> captor = ArgumentCaptor.forClass(RequestMapping.class);
790         DatagramPacket replyPacket = handleMapRequestPacket(mapRequestPacket);
791         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(Mockito.any());
792         assertEquals(4342, replyPacket.recipient().getPort());
793     }
794
795     @Test
796     public void mapRequest__WithSourceEid() throws Exception {
797         // encapsulated LISP packet
798         // Source EID = 153.16.254.1
799
800         mapRequestPacket = extractWSUdpByteArray(
801                   "0000   00 0c 29 7a ce 83 00 15 17 c6 4a c9 08 00 45 00 "
802                 + "0010   00 78 00 00 40 00 3e 11 ec b1 0a 00 01 26 0a 00 "
803                 + "0020   3a 9e 10 f6 10 f6 00 64 c3 a5 80 00 00 00 45 00 "
804                 + "0030   00 58 d4 31 00 00 ff 11 31 89 99 10 fe 01 0a 00 "
805                 + "0040   14 c8 10 f6 10 f6 00 44 84 ee 10 00 00 01 ba f9 "
806                 + "0050   ff 53 27 36 38 3a 00 01 99 10 fe 01 00 01 0a 00 "
807                 + "0060   01 26 00 20 00 01 0a 00 14 c8 00 00 00 0a 01 20 "
808                 + "0070   10 00 00 00 00 01 99 10 fe 01 01 64 ff 00 00 05 "
809                 + "0080   00 01 0a 00 01 26");
810
811         ArgumentCaptor<RequestMapping> captor = ArgumentCaptor.forClass(RequestMapping.class);
812         handleMapRequestAsByteArray(mapRequestPacket);
813         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(captor.capture());
814         assertEquals(Ipv4BinaryAfi.VALUE, captor.getValue().getMapRequest().getSourceEid().getEid().getAddressType());
815
816     }
817
818     @Test
819     @Ignore
820     public void mapReply__VerifyBasicIPv4Fields() throws Exception {
821         mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid("10.0.20.200/32"));
822         mapReplyBuilder.setNonce(0x3d8d2acd39c8d608L);
823
824         stubHandleRequest();
825
826         byte[] result = handleMapRequestAsByteArray(mapRequestPacket);
827
828         assertEquals(28, result.length);
829
830         byte expectedLispMessageType = 2;
831         assertEquals(expectedLispMessageType, (byte) (result[LispMessage.Pos.TYPE] >> 4));
832         assertEquals(0x3d8d2acd39c8d608L, ByteUtil.getLong(result, MapReplyIpv4SingleLocatorPos.NONCE));
833
834         byte expectedRecordCount = (byte) 1;
835         assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]);
836
837         assertEquals(MaskUtil.getMaskForAddress(mappingRecordBuilder.getEid().getAddress()),
838                 result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]);
839         assertEquals(AddressFamily.IpV4.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE));
840         assertEquals(0x0a0014c8, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.EID_PREFIX));
841     }
842
843     @Test
844     @Ignore
845     public void mapReply_q_VerifyBasicIPv6() throws Exception {
846         mappingRecordBuilder.setEid(LispAddressUtil.asIpv6PrefixEid("0:0:0:0:0:0:0:1/128"));
847
848         stubHandleRequest();
849
850         byte[] result = handleMapRequestAsByteArray(mapRequestPacket);
851
852         assertEquals(40, result.length);
853
854         byte expectedRecordCount = (byte) 1;
855         assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]);
856
857         assertEquals(MaskUtil.getMaskForAddress(mappingRecordBuilder.getEid().getAddress()),
858                 result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]);
859         assertEquals(AddressFamily.IpV6.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE));
860         byte[] expectedIpv6 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
861
862         ArrayAssert.assertEquals(expectedIpv6, Arrays.copyOfRange(result, 24, 40));
863     }
864
865     @Test
866     @Ignore
867     public void mapReply__VerifyIPv6EidAndLocator() throws Exception {
868         mappingRecordBuilder.setEid(LispAddressUtil.asIpv6PrefixEid("0:0:0:0:0:0:0:1/128"));
869         mappingRecordBuilder.getLocatorRecord().add(
870                 new LocatorRecordBuilder().setRloc(LispAddressUtil.asIpv6Rloc("0:0:0:0:0:0:0:2")).build());
871
872         stubHandleRequest();
873
874         byte[] result = handleMapRequestAsByteArray(mapRequestPacket);
875
876         assertEquals(64, result.length);
877
878         byte[] expectedIpv6Eid = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
879         ArrayAssert.assertEquals(expectedIpv6Eid, Arrays.copyOfRange(result, 24, 40));
880
881         byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
882         ArrayAssert.assertEquals(expectedIpv6Rloc, Arrays.copyOfRange(result, 48, 64));
883     }
884
885     @Ignore
886     @Test
887     public void mapReply__UseEncapsulatedUdpPort() throws Exception {
888         stubHandleRequest();
889
890         assertEquals(LispMessage.PORT_NUM, handleMapRequestPacket(mapRequestPacket).recipient().getPort());
891     }
892
893     @Test
894     @Ignore
895     public void mapReply__WithNonRoutableSingleLocator() throws Exception {
896         mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid("10.0.20.200/32"));
897         mappingRecordBuilder.getLocatorRecord().add(
898                 new LocatorRecordBuilder().setRouted(false).setRloc(LispAddressUtil.asIpv4Rloc("4.3.2.1")).build());
899         stubHandleRequest();
900
901         byte[] result = handleMapRequestAsByteArray(mapRequestPacket);
902         assertEquals(0x00, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
903     }
904
905     @Test
906     @Ignore
907     public void mapReply__WithSingleLocator() throws Exception {
908         mappingRecordBuilder.setEid(LispAddressUtil.asIpv4PrefixEid("10.0.20.200/32"));
909         mappingRecordBuilder.getLocatorRecord().add(
910                 new LocatorRecordBuilder().setRouted(true).setRloc(LispAddressUtil.asIpv4Rloc("4.3.2.1")).build());
911         stubHandleRequest();
912
913         byte[] result = handleMapRequestAsByteArray(mapRequestPacket);
914         assertEquals(40, result.length);
915
916         byte expectedLocCount = 1;
917         assertEquals(expectedLocCount, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]);
918
919         assertEquals(AddressFamily.IpV4.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOC_AFI));
920
921         assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR));
922         assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
923     }
924
925     @Test
926     @Ignore
927     public void mapReply__WithMultipleLocator() throws Exception {
928         mappingRecordBuilder.getLocatorRecord().add(
929                 new LocatorRecordBuilder().setRouted(true).setRloc(LispAddressUtil.asIpv4Rloc("4.3.2.1")).build());
930         mappingRecordBuilder.getLocatorRecord().add(
931                 new LocatorRecordBuilder().setRouted(true).setRloc(LispAddressUtil.asIpv6Rloc("0:0:0:0:0:0:0:1"))
932                 .build());
933         stubHandleRequest();
934
935         byte[] result = handleMapRequestAsByteArray(mapRequestPacket);
936         assertEquals(64, result.length);
937
938         assertEquals(2, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]);
939
940         assertEquals(AddressFamily.IpV4.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOC_AFI));
941         assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR));
942         assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
943
944         assertEquals(AddressFamily.IpV6.getIntValue(), ByteUtil.getInt(result, MapReplyIpv4SecondLocatorPos.LOC_AFI));
945
946         byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
947         ArrayAssert.assertEquals(expectedIpv6Rloc, Arrays.copyOfRange(result, MapReplyIpv4SecondLocatorPos.LOCATOR,
948                 MapReplyIpv4SecondLocatorPos.LOCATOR + 16));
949
950         assertEquals(0x01, result[MapReplyIpv4SecondLocatorPos.LOCATOR_RBIT] & 0x01);
951     }
952
953     @Test
954     public void handleUnknownLispMessage() throws Exception {
955         // IP: 192.168.136.10 -> 128.223.156.35
956         // UDP: 49289 -> 4342
957         // LISP(Type = 14 UNKNOWN!!!, P=1, M=1
958
959         byte[] unknownTypePacket = extractWSUdpByteArray(
960                   "0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 "
961                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
962                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 F8 00 01 01 00 00 "
963                 + "0030   00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 "
964                 + "0040   b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 "
965                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 "
966                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a");
967         assertNull(handlePacket(unknownTypePacket));
968     }
969
970     @Test
971     public void mapRequest__MultipleItrRlocs() throws Exception {
972         // this is what LISPmob sends when configured multiple RLOCs for single
973         // EID.
974         // ITR-RLOC 1: 10.1.0.111
975         // ITR-RLOC 2: 192.168.136.51
976         //
977         mapRequestPacket = extractWSUdpByteArray(
978                   "0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
979                 + "0010   00 8a 00 00 40 00 40 11 25 f2 0a 01 00 6f 0a 01 "
980                 + "0020   00 01 10 f6 10 f6 00 76 06 1f 80 00 00 00 45 00 "
981                 + "0030   00 6a d4 31 00 00 ff 11 2a 3e ac 01 01 02 08 08 "
982                 + "0040   08 08 10 f6 10 f6 00 56 63 14 10 00 01 01 79 67 "
983                 + "0050   ff 75 a0 61 66 19 00 01 ac 01 01 02 00 01 0a 01 "
984                 + "0060   00 6f 00 01 c0 a8 88 33 00 20 00 01 08 08 08 08 "
985                 + "0070   00 00 00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 "
986                 + "0080   01 64 ff 00 00 05 00 01 0a 01 00 6f 06 64 ff 00 "
987                 + "0090   00 05 00 01 c0 a8 88 33");
988
989         handleMapRequestAsByteArray(mapRequestPacket);
990         Mockito.verify(mockLispSouthboundPlugin).sendNotificationIfPossible(Mockito.any(RequestMapping.class));
991     }
992
993     private void stubHandleRequest() {
994         try {
995             allowing(contextMockLispSouthboundPlugin).sendNotificationIfPossible(wany(Notification.class));
996         } catch (InterruptedException e) {
997             LOG.debug("Interrupted", e);
998         }
999     }
1000
1001     private byte[] handleMapRequestAsByteArray(byte[] inPacket) {
1002         handleMapRequestPacket(inPacket);
1003         return lastMapReplyPacket().content().array();
1004     }
1005
1006     private byte[] handleMapRegisterAsByteArray(byte[] inPacket) {
1007         handleMapRegisterPacket(inPacket);
1008         return lastMapNotifyPacket().content().array();
1009     }
1010
1011     private DatagramPacket handleMapRequestPacket(byte[] inPacket) {
1012         DatagramPacket dp = new DatagramPacket(wrappedBuffer(inPacket), new InetSocketAddress(0),
1013                 new InetSocketAddress(0));
1014         // Unless we explicitly set the source port, it will be -1, which breaks some tests
1015         // This is till not the real port number, but it's better
1016         //dp.setPort(LispMessage.PORT_NUM);
1017         testedLispService.handlePacket(dp);
1018         return lastMapReplyPacket();
1019     }
1020
1021     private DatagramPacket handleMapRegisterPacket(byte[] inPacket) {
1022         DatagramPacket dp = new DatagramPacket(wrappedBuffer(inPacket), new InetSocketAddress(0),
1023                 new InetSocketAddress(0));
1024         // Unless we explicitly set the source port, it will be -1, which breaks some tests
1025         // This is till not the real port number, but it's better
1026         //dp.setPort(LispMessage.PORT_NUM);
1027         testedLispService.handlePacket(dp);
1028         if (mapNotifyBuilder == null) {
1029             return null;
1030         } else {
1031             return lastMapNotifyPacket();
1032         }
1033     }
1034
1035     private DatagramPacket handlePacket(byte[] inPacket) {
1036         // TODO get from mock
1037         testedLispService.handlePacket(new DatagramPacket(wrappedBuffer(inPacket), new InetSocketAddress(0),
1038                 new InetSocketAddress(0)));
1039         return null;
1040     }
1041
1042     private byte[] extractWSUdpByteArray(String wiresharkHex) {
1043         final int headerLen = 42;
1044         byte[] res = new byte[1000];
1045         String[] split = wiresharkHex.split(" ");
1046         int counter = 0;
1047         for (String cur : split) {
1048             cur = cur.trim();
1049             if (cur.length() == 2) {
1050                 ++counter;
1051                 if (counter > headerLen) {
1052                     res[counter - headerLen - 1] = (byte) Integer.parseInt(cur, 16);
1053                 }
1054
1055             }
1056         }
1057         return Arrays.copyOf(res, counter - headerLen);
1058     }
1059
1060     @Test(expected = LispMalformedPacketException.class)
1061     public void mapRequest__NoIpItrRloc() throws Exception {
1062         mapRequestPacket = hexToByteBuffer("10 00 "
1063                 // This means 3 ITR - RLOCs
1064                 + "02 "
1065                 + "01 3d 8d 2a cd 39 c8 d6 08 00 00 "
1066                 // MAC (ITR-RLOC #1 of 3)
1067                 + "40 05 c0 a8 88 0a 01 02 "
1068                 // MAC (ITR-RLOC #2 of 3)
1069                 + "40 05 00 00 00 00 00 00 "
1070                 // MAC (ITR-RLOC #3 of 3)
1071                 + "40 05 11 22 34 56 78 90 "
1072                 + "00 20 00 01 01 02 03 04").array();
1073         handleMapRequestPacket(mapRequestPacket);
1074     }
1075 }