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