refactoring of listmappingservice into Northbound (future REST) and Southbound (LISP...
[lispflowmapping.git] / mappingservice / southbound / src / test / java / org / opendaylight / lispflowmapping / southbound / lisp / LispSouthboundServiceTest.java
1 /*
2  * Copyright (c) 2013 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 junit.framework.Assert.assertEquals;
12 import static junit.framework.Assert.assertFalse;
13 import static junit.framework.Assert.assertTrue;
14
15 import java.net.DatagramPacket;
16 import java.util.Arrays;
17 import java.util.List;
18
19 import junitx.framework.ArrayAssert;
20 import junitx.framework.Assert;
21
22 import org.jmock.api.Invocation;
23 import org.junit.Before;
24 import org.junit.Ignore;
25 import org.junit.Test;
26 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolver;
27 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapServer;
28 import org.opendaylight.lispflowmapping.southbound.lisp.exception.LispMalformedPacketException;
29 import org.opendaylight.lispflowmapping.southbound.serializer.LispMessage;
30 import org.opendaylight.lispflowmapping.southbound.serializer.LispMessageEnum;
31 import org.opendaylight.lispflowmapping.southbound.util.ByteUtil;
32 import org.opendaylight.lispflowmapping.tools.junit.BaseTestCase;
33 import org.opendaylight.lispflowmapping.type.AddressFamilyNumberEnum;
34 import org.opendaylight.lispflowmapping.type.lisp.EidRecord;
35 import org.opendaylight.lispflowmapping.type.lisp.EidToLocatorRecord;
36 import org.opendaylight.lispflowmapping.type.lisp.LocatorRecord;
37 import org.opendaylight.lispflowmapping.type.lisp.MapNotify;
38 import org.opendaylight.lispflowmapping.type.lisp.MapRegister;
39 import org.opendaylight.lispflowmapping.type.lisp.MapReply;
40 import org.opendaylight.lispflowmapping.type.lisp.MapRequest;
41 import org.opendaylight.lispflowmapping.type.lisp.address.LispAddress;
42 import org.opendaylight.lispflowmapping.type.lisp.address.LispIpv4Address;
43 import org.opendaylight.lispflowmapping.type.lisp.address.LispIpv6Address;
44
45 public class LispSouthboundServiceTest extends BaseTestCase {
46
47     private LispSouthboundService testedLispService;
48     private IMapResolver mapResolver;
49     private IMapServer mapServer;
50     private byte[] mapRequestPacket;
51     private byte[] mapRegisterPacket;
52     private ValueSaverAction<MapRegister> mapRegisterSaver;
53     private ValueSaverAction<MapRequest> mapRequestSaver;
54     private MapNotify mapNotify;
55     private MapReply mapReply;
56     private EidToLocatorRecord eidToLocator;
57
58     private interface MapReplyIpv4SingleLocatorPos {
59         int RECORD_COUNT = 3;
60         int NONCE = 4;
61         int LOCATOR_COUNT = 16;
62         int EID_MASK_LEN = 17;
63         int AFI_TYPE = 22;
64         int EID_PREFIX = 24;
65         int LOC_AFI = 34;
66         int LOCATOR_RBIT = 33;
67         int LOCATOR = 36;
68     }
69
70     private interface MapReplyIpv4SecondLocatorPos {
71         int FIRST_LOCATOR_IPV4_LENGTH = 12;
72         int LOC_AFI = MapReplyIpv4SingleLocatorPos.LOC_AFI + FIRST_LOCATOR_IPV4_LENGTH;
73         int LOCATOR_RBIT = MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT + FIRST_LOCATOR_IPV4_LENGTH;
74         int LOCATOR = MapReplyIpv4SingleLocatorPos.LOCATOR + FIRST_LOCATOR_IPV4_LENGTH;
75     }
76
77     @Override
78     @Before
79     public void before() throws Exception {
80         super.before();
81         mapResolver = context.mock(IMapResolver.class);
82         mapServer = context.mock(IMapServer.class);
83         testedLispService = new LispSouthboundService(mapResolver, mapServer);
84
85         mapRegisterSaver = new ValueSaverAction<MapRegister>();
86         mapRequestSaver = new ValueSaverAction<MapRequest>();
87         // SRC: 127.0.0.1:58560 to 127.0.0.1:4342
88         // LISP(Type = 8 - Encapsulated)
89         // IP: 192.168.136.10 -> 1.2.3.4
90         // UDP: 56756
91         // LISP(Type = 1 Map-Request
92         // Record Count: 1
93         // ITR-RLOC count: 0
94         // Source EID AFI: 0
95         // Source EID not present
96         // Nonce: 0x3d8d2acd39c8d608
97         // ITR-RLOC AFI=1 Address=192.168.136.10
98         // Record 1: 1.2.3.4/32
99         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " //
100                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
101                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "
102                 + "0030   00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 "
103                 + "0040   03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d "
104                 + "0050   2a cd 39 c8 d6 08 00 00 00 01 c0 a8 88 0a 00 20 " //
105                 + "0060   00 01 01 02 03 04"));
106         mapReply = new MapReply();
107         eidToLocator = new EidToLocatorRecord();
108         eidToLocator.setPrefix(new LispIpv4Address(0));
109         mapReply.addEidToLocator(eidToLocator);
110
111         // IP: 192.168.136.10 -> 128.223.156.35
112         // UDP: 49289 -> 4342
113         // LISP(Type = 3 Map-Register, P=1, M=1
114         // Record Counter: 1
115         // Nonce: 0
116         // Key ID: 0x0001
117         // AuthDataLength: 20 Data:
118         // e8:f5:0b:c5:c5:f2:b0:21:27:a8:21:41:04:f3:46:5a:a5:68:89:ec
119         // EID prefix: 153.16.254.1/32 (EID=0x9910FE01), TTL: 10, Authoritative,
120         // No-Action
121         // Local RLOC: 192.168.136.10 (RLOC=0xC0A8880A), Reachable,
122         // Priority/Weight: 1/100, Multicast Priority/Weight:
123         // 255/0
124         //
125
126         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
127                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
128                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 01 01 00 00 "
129                 + "0030   00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 "
130                 + "0040   b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 "
131                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
132                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
133         mapNotify = new MapNotify();
134     }
135
136     @Test
137     @Ignore
138     public void todos() throws Exception {
139
140         // TODO: MapRequest: usage of Map-Reply-Record in MapRequest packet.
141         // TODO: Non-Encapsulated packets
142     }
143
144     @Test(expected = LispMalformedPacketException.class)
145     public void mapRegister__IllegalPacket() throws Exception {
146         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
147                 + "0010   00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 " //
148                 + "0020   00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 "));
149
150         handlePacket(mapRegisterPacket);
151     }
152
153     @Test(expected = LispMalformedPacketException.class)
154     public void mapRequest__IllegalPacket() throws Exception {
155         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " //
156                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 "
157                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "
158                 + "0030   00 38 d4 31 00 00 ff 11 56 f3 c0 a8 88 0a 01 02 " //
159                 + "0040   03 04 dd b4 10 f6 00 24 ef 3a 10 00 00 01 3d 8d "));
160         handlePacket(mapRequestPacket);
161     }
162
163     @Test(expected = LispMalformedPacketException.class)
164     public void mapRequest__IllegalEncapsulatedPacket() throws Exception {
165         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 " //
166                 + "0010   00 58 00 00 40 00 40 11 3c 93 7f 00 00 01 7f 00 " //
167                 + "0020   00 01 e4 c0 10 f6 00 44 fe 57 80 00 00 00 45 00 "));
168         handlePacket(mapRequestPacket);
169     }
170
171     @Test
172     public void mapRegister__TwoRlocs() throws Exception {
173         // P Bit & M Bit set
174         // EID prefix: 172.1.1.2/32, TTL: 10, Authoritative, No-Action
175         // Local RLOC: 10.1.0.110, Reachable, Priority/Weight: 1/100, Multicast
176         // Priority/Weight: 255/0
177         // Local RLOC: 192.168.136.51, Reachable, Priority/Weight: 6/100,
178         // Multicast Priority/Weight: 255/0
179         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
180                 + "0010   00 68 00 00 40 00 40 11 26 15 0a 01 00 6e 0a 01 " //
181                 + "0020   00 01 10 f6 10 f6 00 54 03 3b 38 00 01 01 00 00 " //
182                 + "0030   00 00 00 00 00 00 00 01 00 14 f8 3c d8 9d 92 8b " //
183                 + "0040   67 20 2c 63 82 63 c5 38 7b 74 b8 70 01 dd 00 00 " //
184                 + "0050   00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 01 64 " //
185                 + "0060   ff 00 00 05 00 01 0a 01 00 6e 06 64 ff 00 00 05 " //
186                 + "0070   00 01 c0 a8 88 33"));
187
188         oneOf(mapServer).handleMapRegister(with(mapRegisterSaver));
189         ret(null);
190
191         handlePacket(mapRegisterPacket);
192
193         List<EidToLocatorRecord> eidRecords = mapRegisterSaver.lastValue.getEidToLocatorRecords();
194         assertEquals(1, eidRecords.size());
195         EidToLocatorRecord eidRecord = eidRecords.get(0);
196         assertEquals(2, eidRecord.getLocators().size());
197         assertEquals(new LispIpv4Address("10.1.0.110"), eidRecord.getLocators().get(0).getLocator());
198         assertEquals(new LispIpv4Address("192.168.136.51"), eidRecord.getLocators().get(1).getLocator());
199     }
200
201     @Test
202     public void mapRegister__Ipv6Rloc() throws Exception {
203         // P bit (Proxy-Map-Reply): Set
204         // M bit (Want-Map-Notify): Set
205         // Record Counter: 1
206         // Nonce: 0
207         // Key ID: 1
208         // AuthLength: 20
209         // Authentication Data: 5bc4d44a57e2a55d577a6f89779c004f5da713fb
210         // EID prefix: 2610:d0:ffff:192::1/128, TTL: 10, Authoritative,
211         // No-Action
212         // Local RLOC: 10.0.58.156, Reachable, Priority/Weight: 1/100, Multicast
213         // Priority/Weight: 255/0
214
215         mapRegisterPacket = extractWSUdpByteArray(new String("0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " //
216                 + "0010   00 68 00 00 40 00 40 11 ea c3 0a 00 3a 9c 0a 00 " //
217                 + "0020   01 26 10 f6 10 f6 00 54 f5 9a 38 00 03 01 00 00 " //
218                 + "0030   00 00 00 00 00 00 00 01 00 14 5b c4 d4 4a 57 e2 " //
219                 + "0040   a5 5d 57 7a 6f 89 77 9c 00 4f 5d a7 13 fb 00 00 " //
220                 + "0050   00 0a 01 80 10 00 00 00 00 02 26 10 00 d0 ff ff " //
221                 + "0060   01 92 00 00 00 00 00 00 00 01 01 64 ff 00 00 05 " //
222                 + "0070   00 01 0a 00 3a 9c"));
223
224         oneOf(mapServer).handleMapRegister(with(mapRegisterSaver));
225         ret(null);
226
227         handlePacket(mapRegisterPacket);
228         byte[] expectedIpv6Address = new byte[] { 0x26, 0x10, 0x00, (byte) 0xd0, (byte) 0xff, (byte) 0xff, 0x01, (byte) 0x92, 0x00, 0x00, 0x00, 0x00,
229                 0x00, 0x00, 0x00, 0x01 };
230
231         EidToLocatorRecord eidToLocatorRecord = mapRegisterSaver.lastValue.getEidToLocatorRecords().get(0);
232         assertEquals(new LispIpv6Address(expectedIpv6Address), eidToLocatorRecord.getPrefix());
233         assertEquals(AddressFamilyNumberEnum.IP6, eidToLocatorRecord.getPrefix().getAfi());
234
235         assertEquals(new LispIpv4Address(0x0A003A9C), eidToLocatorRecord.getLocators().get(0).getLocator());
236     }
237
238     @Test
239     public void mapRegister__VerifyBasicFields() throws Exception {
240         oneOf(mapServer).handleMapRegister(with(mapRegisterSaver));
241         ret(null);
242         handlePacket(mapRegisterPacket);
243
244         EidToLocatorRecord eidToLocator = mapRegisterSaver.lastValue.getEidToLocatorRecords().get(0);
245         assertEquals(new LispIpv4Address(0x9910FE01), eidToLocator.getPrefix());
246
247         assertEquals(1, eidToLocator.getLocators().size());
248         assertEquals(new LispIpv4Address(0xC0A8880A), eidToLocator.getLocators().get(0).getLocator());
249     }
250
251     @Test
252     public void mapRegister__NoResponseFromMapServerShouldReturnNullPacket() throws Exception {
253         allowing(mapServer).handleMapRegister(with(mapRegisterSaver));
254         ret(null);
255
256         assertNull(handlePacket(mapRegisterPacket));
257     }
258
259     @Test
260     public void mapRegister__NonSetMBit() throws Exception {
261         byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
262                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df " //
263                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 00 01 00 00 "
264                 + "0030   00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 "
265                 + "0040   b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 " //
266                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
267                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
268         stubMapRegister(true);
269
270         handlePacket(registerWithNonSetMBit);
271
272         assertFalse(mapRegisterSaver.lastValue.isWantMapNotify());
273     }
274
275     @Test
276     public void mapRegister__NonSetMBitWithNonZeroReservedBits() throws Exception {
277         byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
278                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
279                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 02 01 00 00 "
280                 + "0030   00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 "
281                 + "0040   b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 "
282                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
283                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
284         stubMapRegister(true);
285
286         handlePacket(registerWithNonSetMBit);
287         assertFalse(mapRegisterSaver.lastValue.isWantMapNotify());
288     }
289
290     @Test
291     public void mapRegister__SetMBitWithNonZeroReservedBits() throws Exception {
292         byte[] registerWithNonSetMBit = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
293                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
294                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 38 00 03 01 00 00 "
295                 + "0030   00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 "
296                 + "0040   b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 "
297                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
298                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
299         stubMapRegister(true);
300
301         handlePacket(registerWithNonSetMBit);
302         assertTrue(mapRegisterSaver.lastValue.isWantMapNotify());
303     }
304
305     @Test
306     public void mapRegisterAndNotify__ValidExtraDataParsedSuccessfully() throws Exception {
307         byte[] extraDataPacket = new byte[mapRegisterPacket.length + 3];
308         extraDataPacket[mapRegisterPacket.length] = 0x9;
309         System.arraycopy(mapRegisterPacket, 0, extraDataPacket, 0, mapRegisterPacket.length);
310         stubMapRegister(true);
311
312         DatagramPacket dp = new DatagramPacket(extraDataPacket, extraDataPacket.length);
313         dp.setLength(mapRegisterPacket.length);
314         byte[] notifyResult = testedLispService.handlePacket(dp).getData();
315
316         assertEquals(mapRegisterPacket.length, notifyResult.length);
317
318     }
319
320     @Test
321     public void mapNotify__VerifyBasicFields() throws Exception {
322         byte registerType = mapRegisterPacket[0];
323         assertEquals(LispMessageEnum.MapRegister.getValue(), registerType >> 4);
324
325         stubMapRegister(true);
326
327         byte[] result = handlePacketAsByteArray(mapRegisterPacket);
328
329         assertEquals(mapRegisterPacket.length, result.length);
330
331         byte expectedType = (byte) (LispMessageEnum.MapNotify.getValue() << 4);
332         assertHexEquals(expectedType, result[0]);
333         assertHexEquals((byte) 0x00, result[1]);
334         assertHexEquals((byte) 0x00, result[2]);
335
336         byte[] registerWithoutType = Arrays.copyOfRange(mapRegisterPacket, 3, mapRegisterPacket.length);
337         byte[] notifyWithoutType = Arrays.copyOfRange(result, 3, result.length);
338         ArrayAssert.assertEquals(registerWithoutType, notifyWithoutType);
339     }
340
341     @Test
342     public void mapNotify__VerifyPort() throws Exception {
343         stubMapRegister(true);
344
345         DatagramPacket notifyPacket = handlePacket(mapRegisterPacket);
346         assertEquals(LispMessage.PORT_NUM, notifyPacket.getPort());
347     }
348
349     @Test
350     public void mapRequest__VerifyBasicFields() throws Exception {
351         oneOf(mapResolver).handleMapRequest(with(mapRequestSaver));
352         ret(mapReply);
353
354         handlePacketAsByteArray(mapRequestPacket);
355         List<EidRecord> eids = mapRequestSaver.lastValue.getEids();
356         assertEquals(1, eids.size());
357         LispAddress lispAddress = eids.get(0).getPrefix();
358         assertTrue(lispAddress instanceof LispIpv4Address);
359         assertEquals(asInet(0x01020304), ((LispIpv4Address) lispAddress).getAddress());
360         assertEquals((byte) 0x20, eids.get(0).getMaskLength());
361         assertEquals(0x3d8d2acd39c8d608L, mapRequestSaver.lastValue.getNonce());
362         assertEquals(AddressFamilyNumberEnum.RESERVED, mapRequestSaver.lastValue.getSourceEid().getAfi());
363     }
364
365     @Test
366     public void mapRequest__Ipv6Eid() throws Exception {
367         // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1
368         // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2
369         // (2610:d0:ffff:192::2)
370         // MBIT: SET
371         // EID AFI: 2
372         // Source EID: 2610:d0:ffff:192::1 (2610:d0:ffff:192::1)
373         // ITR-RLOC 1: 10.0.58.156
374         // Record 1: 2610:d0:ffff:192::2/128
375         // Map-Reply Record: EID prefix: 2610:d0:ffff:192::1/128, TTL: 10,
376         // Authoritative, No-Action
377
378         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " //
379                 + "0010   00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 "
380                 + "0020   01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 "
381                 + "0030   00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 "
382                 + "0040   00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 "
383                 + "0050   00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 14 00 "
384                 + "0060   00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 "
385                 + "0070   ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 "
386                 + "0080   3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 "
387                 + "0090   00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 " //
388                 + "00a0   00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 " //
389                 + "00b0   00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c"));
390
391         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
392         ret(mapReply);
393
394         handlePacketAsByteArray(mapRequestPacket);
395         assertEquals(new LispIpv6Address("2610:d0:ffff:192::1"), mapRequestSaver.lastValue.getSourceEid());
396         assertEquals(new LispIpv6Address("2610:d0:ffff:192::2"), mapRequestSaver.lastValue.getEids().get(0).getPrefix());
397     }
398
399     @Test
400     public void mapRequest__UsesIpv6EncapsulatedUdpPort() throws Exception {
401         // Internet Protocol Version 6, Src: 2610:d0:ffff:192::1
402         // (2610:d0:ffff:192::1), Dst: 2610:d0:ffff:192::2
403         // (2610:d0:ffff:192::2)
404         // encapsulated UDP source port: 4342
405
406         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 34 3e 1b 00 0c 29 f6 d6 0d 08 00 45 00 " //
407                 + "0010   00 b0 00 00 40 00 40 11 ea 7b 0a 00 3a 9c 0a 00 "
408                 + "0020   01 26 10 f6 10 f6 00 9c 9b 19 80 00 00 00 60 00 "
409                 + "0030   00 00 00 68 11 ff 26 10 00 d0 ff ff 01 92 00 00 "
410                 + "0040   00 00 00 00 00 01 26 10 00 d0 ff ff 01 92 00 00 "
411                 + "0050   00 00 00 00 00 02 10 f6 10 f6 00 68 94 8b 14 00 "
412                 + "0060   00 01 ff f5 bf 5d 7b 75 93 e6 00 02 26 10 00 d0 "
413                 + "0070   ff ff 01 92 00 00 00 00 00 00 00 01 00 01 0a 00 "
414                 + "0080   3a 9c 00 80 00 02 26 10 00 d0 ff ff 01 92 00 00 "
415                 + "0090   00 00 00 00 00 02 00 00 00 0a 01 80 10 00 00 00 " //
416                 + "00a0   00 02 26 10 00 d0 ff ff 01 92 00 00 00 00 00 00 " //
417                 + "00b0   00 01 01 64 ff 00 00 05 00 01 0a 00 3a 9c"));
418
419         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
420         ret(mapReply);
421
422         DatagramPacket replyPacket = handlePacket(mapRequestPacket);
423         assertEquals(4342, replyPacket.getPort());
424     }
425
426     @Test
427     public void mapRequest__WithSourceEid() throws Exception {
428         // encapsulated LISP packet
429         // Source EID = 153.16.254.1
430
431         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 83 00 15 17 c6 4a c9 08 00 45 00 " //
432                 + "0010   00 78 00 00 40 00 3e 11 ec b1 0a 00 01 26 0a 00 "
433                 + "0020   3a 9e 10 f6 10 f6 00 64 c3 a5 80 00 00 00 45 00 "
434                 + "0030   00 58 d4 31 00 00 ff 11 31 89 99 10 fe 01 0a 00 "
435                 + "0040   14 c8 10 f6 10 f6 00 44 84 ee 14 00 00 01 ba f9 "
436                 + "0050   ff 53 27 36 38 3a 00 01 99 10 fe 01 00 01 0a 00 "
437                 + "0060   01 26 00 20 00 01 0a 00 14 c8 00 00 00 0a 01 20 "
438                 + "0070   10 00 00 00 00 01 99 10 fe 01 01 64 ff 00 00 05 " //
439                 + "0080   00 01 0a 00 01 26"));
440
441         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
442         ret(mapReply);
443
444         handlePacketAsByteArray(mapRequestPacket);
445         Assert.assertNotEquals(AddressFamilyNumberEnum.RESERVED, mapRequestSaver.lastValue.getSourceEid().getAfi());
446
447     }
448
449     @Test
450     public void mapReply__VerifyBasicIPv4Fields() throws Exception {
451         eidToLocator.setMaskLength((byte) 0x20)//
452                 .setPrefix(new LispIpv4Address(0x0a0014c8));
453         mapReply.setNonce(0x3d8d2acd39c8d608L);
454
455         stubHandleRequest();
456
457         byte[] result = handlePacketAsByteArray(mapRequestPacket);
458
459         assertEquals(28, result.length);
460
461         byte expectedLispMessageType = 2;
462         assertEquals(expectedLispMessageType, (byte) (result[LispMessage.Pos.TYPE] >> 4));
463         assertEquals(0x3d8d2acd39c8d608L, ByteUtil.getLong(result, MapReplyIpv4SingleLocatorPos.NONCE));
464
465         byte expectedRecordCount = (byte) 1;
466         assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]);
467
468         assertEquals(eidToLocator.getMaskLength(), result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]);
469         assertEquals(AddressFamilyNumberEnum.IP.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE));
470         assertEquals(0x0a0014c8, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.EID_PREFIX));
471     }
472
473     @Test
474     public void mapReply__VerifyBasicIPv6() throws Exception {
475         eidToLocator.setMaskLength((byte) 0x80)//
476                 .setPrefix(new LispIpv6Address("::1"));
477
478         stubHandleRequest();
479
480         byte[] result = handlePacketAsByteArray(mapRequestPacket);
481
482         assertEquals(40, result.length);
483
484         byte expectedRecordCount = (byte) 1;
485         assertEquals(expectedRecordCount, result[MapReplyIpv4SingleLocatorPos.RECORD_COUNT]);
486
487         assertEquals(eidToLocator.getMaskLength(), result[MapReplyIpv4SingleLocatorPos.EID_MASK_LEN]);
488         assertEquals(AddressFamilyNumberEnum.IP6.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.AFI_TYPE));
489         byte[] expectedIpv6 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
490
491         ArrayAssert.assertEquals(expectedIpv6, Arrays.copyOfRange(result, 24, 40));
492     }
493
494     @Test
495     public void mapReply__VerifyIPv6EidAndLocator() throws Exception {
496         eidToLocator.setPrefix(new LispIpv6Address("::1"));
497         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv6Address("::2")));
498
499         stubHandleRequest();
500
501         byte[] result = handlePacketAsByteArray(mapRequestPacket);
502
503         assertEquals(64, result.length);
504
505         byte[] expectedIpv6Eid = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
506         ArrayAssert.assertEquals(expectedIpv6Eid, Arrays.copyOfRange(result, 24, 40));
507
508         byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
509         ArrayAssert.assertEquals(expectedIpv6Rloc, Arrays.copyOfRange(result, 48, 64));
510     }
511
512     @Test
513     public void mapReply__UseEncapsulatedUdpPort() throws Exception {
514         stubHandleRequest();
515
516         assertEquals(56756, handlePacket(mapRequestPacket).getPort());
517     }
518
519     @Test
520     public void mapReply__WithNonRoutableSingleLocator() throws Exception {
521         eidToLocator.setMaskLength((byte) 0x20)//
522                 .setPrefix(new LispIpv4Address(0x0a0014c8));
523         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv4Address(0x04030201)).setRouted(false));
524         stubHandleRequest();
525
526         byte[] result = handlePacketAsByteArray(mapRequestPacket);
527         assertEquals(0x00, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
528     }
529
530     @Test
531     public void mapReply__WithSingleLocator() throws Exception {
532         eidToLocator.setMaskLength((byte) 0x20)//
533                 .setPrefix(new LispIpv4Address(0x0a0014c8));
534         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv4Address(0x04030201)).setRouted(true));
535         stubHandleRequest();
536
537         byte[] result = handlePacketAsByteArray(mapRequestPacket);
538         assertEquals(40, result.length);
539
540         byte expectedLocCount = 1;
541         assertEquals(expectedLocCount, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]);
542
543         assertEquals(AddressFamilyNumberEnum.IP.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.LOC_AFI));
544
545         assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR));
546         assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
547     }
548
549     @Test
550     public void mapReply__WithMultipleLocator() throws Exception {
551         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv4Address(0x04030201)).setRouted(true));
552         eidToLocator.addLocator(new LocatorRecord().setLocator(new LispIpv6Address("::1")).setRouted(true));
553         stubHandleRequest();
554
555         byte[] result = handlePacketAsByteArray(mapRequestPacket);
556         assertEquals(64, result.length);
557
558         assertEquals(2, result[MapReplyIpv4SingleLocatorPos.LOCATOR_COUNT]);
559
560         assertEquals(AddressFamilyNumberEnum.IP.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SingleLocatorPos.LOC_AFI));
561         assertEquals(0x04030201, ByteUtil.getInt(result, MapReplyIpv4SingleLocatorPos.LOCATOR));
562         assertEquals(0x01, result[MapReplyIpv4SingleLocatorPos.LOCATOR_RBIT] & 0x01);
563
564         assertEquals(AddressFamilyNumberEnum.IP6.getIanaCode(), ByteUtil.getShort(result, MapReplyIpv4SecondLocatorPos.LOC_AFI));
565
566         byte[] expectedIpv6Rloc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
567         ArrayAssert.assertEquals(expectedIpv6Rloc, Arrays.copyOfRange(result, MapReplyIpv4SecondLocatorPos.LOCATOR,
568                 MapReplyIpv4SecondLocatorPos.LOCATOR + 16));
569
570         assertEquals(0x01, result[MapReplyIpv4SecondLocatorPos.LOCATOR_RBIT] & 0x01);
571     }
572
573     @Test
574     public void handleUnknownLispMessage() throws Exception {
575         // IP: 192.168.136.10 -> 128.223.156.35
576         // UDP: 49289 -> 4342
577         // LISP(Type = 14 UNKNOWN!!!, P=1, M=1
578
579         byte[] unknownTypePacket = extractWSUdpByteArray(new String("0000   00 50 56 ee d1 4f 00 0c 29 7a ce 79 08 00 45 00 " //
580                 + "0010   00 5c 00 00 40 00 40 11 d4 db c0 a8 88 0a 80 df "
581                 + "0020   9c 23 d6 40 10 f6 00 48 59 a4 F8 00 01 01 00 00 "
582                 + "0030   00 00 00 00 00 00 00 01 00 14 e8 f5 0b c5 c5 f2 "
583                 + "0040   b0 21 27 a8 21 41 04 f3 46 5a a5 68 89 ec 00 00 "
584                 + "0050   00 0a 01 20 10 00 00 00 00 01 99 10 fe 01 01 64 " //
585                 + "0060   ff 00 00 05 00 01 c0 a8 88 0a"));
586         assertNull(handlePacket(unknownTypePacket));
587     }
588
589     @Test
590     public void mapRequest__MultipleItrRlocs() throws Exception {
591         // this is what LISPmob sends when configured multiple RLOCs for single
592         // EID.
593         // ITR-RLOC 1: 10.1.0.111
594         // ITR-RLOC 2: 192.168.136.51
595         //
596         mapRequestPacket = extractWSUdpByteArray(new String("0000   00 0c 29 7a ce 8d 00 0c 29 e4 ef 70 08 00 45 00 "
597                 + "0010   00 8a 00 00 40 00 40 11 25 f2 0a 01 00 6f 0a 01 " //
598                 + "0020   00 01 10 f6 10 f6 00 76 06 1f 80 00 00 00 45 00 " //
599                 + "0030   00 6a d4 31 00 00 ff 11 2a 3e ac 01 01 02 08 08 " //
600                 + "0040   08 08 10 f6 10 f6 00 56 63 14 14 00 01 01 79 67 " //
601                 + "0050   ff 75 a0 61 66 19 00 01 ac 01 01 02 00 01 0a 01 " //
602                 + "0060   00 6f 00 01 c0 a8 88 33 00 20 00 01 08 08 08 08 " //
603                 + "0070   00 00 00 0a 02 20 10 00 00 00 00 01 ac 01 01 02 " //
604                 + "0080   01 64 ff 00 00 05 00 01 0a 01 00 6f 06 64 ff 00 " //
605                 + "0090   00 05 00 01 c0 a8 88 33"));
606
607         allowing(mapResolver).handleMapRequest(with(mapRequestSaver));
608         ret(mapReply);
609
610         handlePacketAsByteArray(mapRequestPacket);
611
612         // assertEquals(2, mapRequestSaver.lastValue.getItrRlocs().size());
613         // assertEquals(new LispIpv4Address("10.1.0.111"),
614         // mapRequestSaver.lastValue.getItrRlocs().get(0));
615         // assertEquals(new LispIpv4Address("192.168.136.51"),
616         // mapRequestSaver.lastValue.getItrRlocs().get(1));
617     }
618
619     private void stubMapRegister(final boolean setNotifyFromRegister) {
620         allowing(mapServer).handleMapRegister(with(mapRegisterSaver));
621         will(new SimpleAction() {
622
623             @Override
624             public Object invoke(Invocation invocation) throws Throwable {
625                 if (setNotifyFromRegister) {
626                     mapNotify.setFromMapRegister(mapRegisterSaver.lastValue);
627                 }
628                 return mapNotify;
629             }
630         });
631     }
632
633     private void stubHandleRequest() {
634         allowing(mapResolver).handleMapRequest(wany(MapRequest.class));
635         ret(mapReply);
636     }
637
638     private byte[] handlePacketAsByteArray(byte[] inPacket) {
639         return handlePacket(inPacket).getData();
640     }
641
642     private DatagramPacket handlePacket(byte[] inPacket) {
643         return testedLispService.handlePacket(new DatagramPacket(inPacket, inPacket.length));
644     }
645
646     private byte[] extractWSUdpByteArray(String wiresharkHex) {
647         final int HEADER_LEN = 42;
648         byte[] res = new byte[1000];
649         String[] split = wiresharkHex.split(" ");
650         int counter = 0;
651         for (String cur : split) {
652             cur = cur.trim();
653             if (cur.length() == 2) {
654                 ++counter;
655                 if (counter > HEADER_LEN) {
656                     res[counter - HEADER_LEN - 1] = (byte) Integer.parseInt(cur, 16);
657                 }
658
659             }
660         }
661         return Arrays.copyOf(res, counter - HEADER_LEN);
662     }
663 }