2 * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.lispflowmapping.integrationtest;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.fail;
14 import java.net.DatagramPacket;
15 import java.net.DatagramSocket;
16 import java.net.InetAddress;
17 import java.net.InetSocketAddress;
18 import java.net.SocketException;
19 import java.net.SocketTimeoutException;
20 import java.net.UnknownHostException;
21 import java.nio.ByteBuffer;
22 import java.util.ArrayList;
23 import java.util.List;
24 import org.opendaylight.lispflowmapping.lisp.serializer.MapNotifySerializer;
25 import org.opendaylight.lispflowmapping.lisp.serializer.MapReplySerializer;
26 import org.opendaylight.lispflowmapping.lisp.serializer.MapRequestSerializer;
27 import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
28 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
29 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
30 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapNotify;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapReply;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapregistermessage.MapRegisterBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRloc;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.SourceEidBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestnotification.MapRequestBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 final class MappingServiceIntegrationTestUtil {
56 private static final Logger LOG = LoggerFactory.getLogger(MappingServiceIntegrationTestUtil.class);
58 // Socket related method constants
59 static final String SEND_ADDRESS = "127.0.0.1";
60 static final String RECEIVE_ADDRESS = "127.0.0.2";
61 static final int NUM_OF_ATTEMPTS_TO_CREATE_SOCKET = 2;
62 static final int DEFAULT_SOCKET_TIMEOUT = 6000;
64 // Packet creation method constants
65 static final String DEFAULT_IPV4_EID_STRING = "192.0.2.1";
66 static final Eid DEFAULT_IPV4_EID = LispAddressUtil.asIpv4Eid(DEFAULT_IPV4_EID_STRING);
67 static final String DEFAULT_IPV4_RLOC_STRING = "172.16.0.1";
68 static final Rloc DEFAULT_IPV4_RLOC = LispAddressUtil.asIpv4Rloc(DEFAULT_IPV4_RLOC_STRING);
69 static final Rloc DEFAULT_IPV4_ITR_RLOC = LispAddressUtil.asIpv4Rloc(RECEIVE_ADDRESS);
70 static final byte[] DEFAULT_SITE_ID_BYTES = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
71 static final SiteId DEFAULT_SITE_ID = new SiteId(DEFAULT_SITE_ID_BYTES);
72 static final byte[] DEFAULT_XTR_ID_BYTES = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
73 static final XtrId DEFAULT_XTR_ID = new XtrId(DEFAULT_XTR_ID_BYTES);
74 private static final Eid NO_ADDRESS_EID = LispAddressUtil.getNoAddressEid();
76 // Utility class, should not be instantiated
77 private MappingServiceIntegrationTestUtil() {
81 * SOCKET RELATED METHODS
85 * Create and return a UDP socket listening on the given port.
87 * @param port listening port
88 * @return the created socket
90 static DatagramSocket initSocket(int port) {
91 for (int i=0; i < NUM_OF_ATTEMPTS_TO_CREATE_SOCKET; i++) {
93 LOG.debug("Binding socket on {}:{}", RECEIVE_ADDRESS, port);
94 return new DatagramSocket(new InetSocketAddress(RECEIVE_ADDRESS, port));
95 } catch (SocketException e) {
96 LOG.error("Can't initialize socket for {}:{}", RECEIVE_ADDRESS, port, e);
104 * Set the destination address and port of a UDP packet
105 * @param packet the packet to be set up
106 * @param port destination port
107 * @throws UnknownHostException when SEND_ADDRESS cannot be converted to InetAddress
109 static void initPacketAddress(DatagramPacket packet, int port) throws UnknownHostException {
110 packet.setAddress(InetAddress.getByName(SEND_ADDRESS));
111 packet.setPort(port);
116 * @param datagramSocket use this socket for sending the packet
117 * @param bytesToSend the packet contents
118 * @param port destination port
120 static void sendPacket(DatagramSocket datagramSocket, byte[] bytesToSend, int port) {
122 DatagramPacket packet = new DatagramPacket(bytesToSend, bytesToSend.length);
123 initPacketAddress(packet, port);
124 LOG.trace("Sending packet to {}:{}", packet.getAddress(), port);
125 datagramSocket.send(packet);
126 } catch (Throwable t) {
132 * Receive a packet on a UDP socket with a set timeout and return it.
134 * @param datagramSocket the listening socket where we expect the packet
135 * @param timeout timeout to wait for the packet to be received in milliseconds
137 * @throws SocketTimeoutException when timout expires without receiving a packet on the socket
139 static ByteBuffer receivePacket(DatagramSocket datagramSocket, int timeout) throws SocketTimeoutException {
141 byte[] buffer = new byte[4096];
142 DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);
143 LOG.trace("Waiting for packet from socket...");
144 datagramSocket.setSoTimeout(timeout);
145 datagramSocket.receive(receivePacket);
146 LOG.trace("Received packet from socket!");
147 return ByteBuffer.wrap(receivePacket.getData());
148 } catch (SocketTimeoutException ste) {
150 } catch (Throwable t) {
157 * Receive a packet on a UDP socket with a set timeout and return it.
159 * @param datagramSocket the listening socket where we expect the packet
161 * @throws SocketTimeoutException when timout expires without receiving a packet on the socket
163 static ByteBuffer receivePacket(DatagramSocket datagramSocket) throws SocketTimeoutException {
164 return receivePacket(datagramSocket, DEFAULT_SOCKET_TIMEOUT);
168 * Read packets on a UDP socket with a set timeout until the given type is received and return it.
170 * @param datagramSocket the listening socket where we expect the packet
171 * @param timeout timeout to wait for the packet to be received in milliseconds
172 * @param type the expected packet type
174 * @throws SocketTimeoutException when timout expires without receiving a packet on the socket
176 static ByteBuffer receiveSpecificPacketType(DatagramSocket datagramSocket, int timeout, MessageType type)
177 throws SocketTimeoutException {
179 ByteBuffer packet = receivePacket(datagramSocket, timeout);
180 if (checkType(packet, type)) {
187 * Read packets on a UDP socket with a set timeout until a Map-Request is received and return it.
189 * @param datagramSocket the listening socket where we expect the packet
190 * @return the Map-Request
191 * @throws SocketTimeoutException
193 static MapRequest receiveMapRequest(DatagramSocket datagramSocket) throws SocketTimeoutException {
194 ByteBuffer packet = receiveSpecificPacketType(datagramSocket, DEFAULT_SOCKET_TIMEOUT, MessageType.MapRequest);
195 return MapRequestSerializer.getInstance().deserialize(packet, null);
199 * Read packets on a UDP socket with a set timeout until a Map-Reply is received and return it.
201 * @param datagramSocket the listening socket where we expect the packet
202 * @return the Map-Reply
203 * @throws SocketTimeoutException
205 static MapReply receiveMapReply(DatagramSocket datagramSocket) throws SocketTimeoutException {
206 ByteBuffer packet = receiveSpecificPacketType(datagramSocket, DEFAULT_SOCKET_TIMEOUT, MessageType.MapReply);
207 return MapReplySerializer.getInstance().deserialize(packet);
211 * Read packets on a UDP socket with a set timeout until a Map-Notify is received and return it.
213 * @param datagramSocket the listening socket where we expect the packet
214 * @return the Map-Notify
215 * @throws SocketTimeoutException
217 static MapNotify receiveMapNotify(DatagramSocket datagramSocket) throws SocketTimeoutException {
218 ByteBuffer packet = receiveSpecificPacketType(datagramSocket, DEFAULT_SOCKET_TIMEOUT, MessageType.MapNotify);
219 return MapNotifySerializer.getInstance().deserialize(packet);
223 * Check if a buffer assumed to be a LISP control packet is of the given type.
225 * @param packet buffer containing the packet data
226 * @param type LISP control packet type
227 * @return true if the packet is of the given type
229 static boolean checkType(ByteBuffer packet, MessageType type) {
230 final int receivedType = ByteUtil.getUnsignedByte(packet, LispMessage.Pos.TYPE) >> 4;
231 MessageType messageType = MessageType.forValue(receivedType);
232 LOG.trace("Packet type: {}", messageType);
233 return messageType == type;
237 * Read packets from the given socket until a Map-Request is found. Assert that the request is an SMR, and the
238 * Source EID field contains the given IPv4 EID. Note that the source EID does not have a mask length.
240 * @param datagramSocket the receive socket
241 * @param vni the VNI for the expected EID
242 * @param eid the expected EID, as an IPv4 string, without mask length
244 static void checkSmr(DatagramSocket datagramSocket, long vni, String eid) {
246 MapRequest mapRequest = receiveMapRequest(datagramSocket);
247 assertEquals(true, mapRequest.isSmr());
249 Eid smrEid = mapRequest.getSourceEid().getEid();
250 Eid originalSourceEid = mapRequest.getEidItem().get(0).getEid();
251 assertEquals(LispAddressUtil.asIpv4Eid(eid, vni), smrEid);
252 assertEquals(NO_ADDRESS_EID, originalSourceEid);
253 } catch (SocketTimeoutException ste) {
254 fail("No SMR received");
259 * PACKETS CREATION METHODS
261 * In general we return "Builders" so that the caller can customize the fields, but that means it also needs to
262 * call .build() on the received objects.
268 * Create a default MapRequestBuilder object.
270 * @param eid the requested EID
271 * @return the MapRequestBuilder object
273 static MapRequestBuilder getDefaultMapRequestBuilder(Eid eid) {
274 MapRequestBuilder mrBuilder = new MapRequestBuilder()
275 .setAuthoritative(false)
276 .setEidItem(new ArrayList<>())
277 .setItrRloc(new ArrayList<>())
278 .setMapDataPresent(true)
283 .setSmrInvoked(false)
284 .setSourceEid(new SourceEidBuilder().setEid(NO_ADDRESS_EID).build())
285 .setItrRloc(getDefaultItrRlocList(DEFAULT_IPV4_ITR_RLOC));
287 mrBuilder.getEidItem().add(new EidItemBuilder().setEid(eid).build());
293 * Create a default ItrRloc List.
295 * @param rloc the single Rloc to be added to the list
296 * @return the ItrRloc List object
298 static List<ItrRloc> getDefaultItrRlocList(Rloc rloc) {
300 rloc = DEFAULT_IPV4_ITR_RLOC;
303 final List<ItrRloc> itrRlocList = new ArrayList<>();
304 final ItrRloc itrRloc = new ItrRlocBuilder()
305 .setKey(new ItrRlocKey(LispAddressStringifier.getString(rloc)))
306 .setItrRlocId(LispAddressStringifier.getString(rloc))
307 .setRloc(rloc).build();
308 itrRlocList.add(itrRloc);
316 * Create a default MapRegisterBuilder object with a non-empty default LocatorRecord.
318 * @param eid EID for the single mapping record, if null, a default will be added
319 * @return the MapRegisterBuilder object
321 static MapRegisterBuilder getDefaultMapRegisterBuilder(Eid eid) {
322 MapRegisterBuilder mapRegisterBuilder = getDefaultMapRegisterBuilder(eid, null);
323 mapRegisterBuilder.setMappingRecordItem(new ArrayList<>());
324 mapRegisterBuilder.getMappingRecordItem().add(getDefaultMappingRecordItemBuilder(eid,
325 DEFAULT_IPV4_RLOC).build());
327 return mapRegisterBuilder;
331 * Create a default MapRegisterBuilder object.
333 * @param eid EID for the single mapping record, if null, a default will be added
334 * @param rloc RLOC for the single mapping record, if null, no locator record will be added
335 * @return the MapRegisterBuilder object
337 static MapRegisterBuilder getDefaultMapRegisterBuilder(Eid eid, Rloc rloc) {
338 final MapRegisterBuilder mapRegisterBuilder = new MapRegisterBuilder()
339 .setProxyMapReply(true)
340 .setWantMapNotify(true)
342 .setMappingRecordItem(new ArrayList<>())
343 .setMergeEnabled(true)
345 .setSiteId(new SiteId(DEFAULT_SITE_ID_BYTES))
346 .setXtrId(new XtrId(DEFAULT_XTR_ID_BYTES))
347 .setXtrSiteIdPresent(true);
348 mapRegisterBuilder.getMappingRecordItem().add(getDefaultMappingRecordItemBuilder(eid, rloc).build());
350 return mapRegisterBuilder;
354 * Create a default MappingRecordItemBuilder object.
356 * @param eid EID for the mapping record, if null, a default will be added
357 * @param rloc RLOC for the mapping record, if null, no locator record will be added
358 * @return the MappingRecordItemBuilder object
360 static MappingRecordItemBuilder getDefaultMappingRecordItemBuilder(Eid eid, Rloc rloc) {
361 return new MappingRecordItemBuilder()
362 .setMappingRecordItemId("mapping-record-item-id")
363 .setKey(new MappingRecordItemKey("mapping-record-item-key"))
364 .setMappingRecord(getDefaultMappingRecordBuilder(eid, rloc).build());
368 * Create a default MappingRecordBuilder object with a single default locator record.
370 * @param eid EID for the mapping record, if null, a default will be added
371 * @return the MappingRecordBuilder object
373 static MappingRecordBuilder getDefaultMappingRecordBuilder(Eid eid) {
374 return getDefaultMappingRecordBuilder(eid, DEFAULT_IPV4_RLOC);
378 * Create a default MappingRecordBuilder object.
380 * @param eid EID for the mapping record, if null, a default will be added
381 * @param rloc RLOC for the mapping record, if null, no locator record will be added
382 * @return the MappingRecordBuilder object
384 static MappingRecordBuilder getDefaultMappingRecordBuilder(Eid eid, Rloc rloc) {
386 eid = DEFAULT_IPV4_EID;
387 LOG.warn("getDefaultMappingRecordBuilder(): null EID received, using the default {}",
388 DEFAULT_IPV4_EID_STRING);
391 MappingRecordBuilder mrb = new MappingRecordBuilder()
393 .setAction(MappingRecord.Action.NoAction)
394 .setAuthoritative(false)
395 .setLocatorRecord(new ArrayList<>())
396 .setMapVersion((short) 0)
398 .setTimestamp(System.currentTimeMillis());
400 // We want to allow for empty locator records, so we only add one if rloc is not null
402 mrb.getLocatorRecord().add(getDefaultLocatorBuilder(rloc).build());
409 * Create a default LocatorRecordBuilder object.
411 * @param rloc RLOC for the mapping record, if null, a default will be added
412 * @return the LocatorRecordBuilder object
414 static LocatorRecordBuilder getDefaultLocatorBuilder(Rloc rloc) {
416 rloc = DEFAULT_IPV4_RLOC;
417 LOG.warn("getDefaultLocatorBuilder(): null RLOC received, using the default {}", DEFAULT_IPV4_RLOC_STRING);
420 return new LocatorRecordBuilder()
421 .setLocalLocator(true)
422 .setMulticastPriority((short) 255)
423 .setMulticastWeight((short) 0)
424 .setPriority((short) 1)
425 .setRlocProbed(false)
427 .setWeight((short) 1)
428 .setKey(new LocatorRecordKey(LispAddressStringifier.getString(rloc)))