Bug 8112: IT: send SMR-invoked Map-Request on SMR
[lispflowmapping.git] / integrationtest / src / test / java / org / opendaylight / lispflowmapping / integrationtest / MultiSiteScenario.java
1 /**
2  * Copyright (c) 2016 Cisco Systems, 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 package org.opendaylight.lispflowmapping.integrationtest;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
14 import static org.opendaylight.lispflowmapping.integrationtest.MappingServiceIntegrationTest.ourAddress;
15 import static org.opendaylight.lispflowmapping.integrationtest.MultiSiteScenarioUtil.SITE_A;
16 import static org.opendaylight.lispflowmapping.integrationtest.MultiSiteScenarioUtil.SITE_D5;
17
18 import com.google.common.net.InetAddresses;
19 import java.nio.ByteBuffer;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26 import org.opendaylight.lispflowmapping.integrationtest.MultiSiteScenarioUtil.Site;
27 import org.opendaylight.lispflowmapping.interfaces.lisp.IFlowMapping;
28 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
29 import org.opendaylight.lispflowmapping.lisp.serializer.MapRequestSerializer;
30 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
31 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
32 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
33 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.InstanceIdType;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.Ipv4AddressBinary;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv4Binary;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv6Binary;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapReply;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItem;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecord;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.locatorrecords.LocatorRecordBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkeyBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItem;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapregisternotification.MapRegisterBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRloc;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.SourceEid;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.SourceEidBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestnotification.MapRequestBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 /**
65  * Contains methods for:
66  * - checking sites visibility (availability) - simulation of ping command
67  * - for preparing and processing data structures necessary for creating map request, map register LISP messages.
68  *
69  */
70 class MultiSiteScenario {
71
72     private final int DEFAULT_NETWORK_MASK = 24;
73     private final int IP_MASK = 32;
74
75     private final Integer TTL = 1440;
76     private final String MAP_RECORD_A = "MAP_RECORD_1";
77
78     private final Short DEFAULT_MULTICAST_PRIORITY = 255;
79     private final Short DEFAULT_MULTICAST_WEIGHT = 0;
80     private final Boolean DEFAULT_LOCAL_LOCATOR = true;
81     private final Boolean DEFAULT_RLOC_PROBED = false;
82     private final Boolean DEFAULT_ROUTED = true;
83     private final byte[] DEFAULT_SITE_ID = new byte[]{0, 0, 0, 0, 0, 0, 0, 0};
84
85     private final MappingAuthkey NULL_AUTH_KEY = new MappingAuthkeyBuilder().setKeyType(0).build();
86     private final IMappingService mapService;
87     private final IFlowMapping lms;
88
89     private static final Logger LOG = LoggerFactory.getLogger(MultiSiteScenario.class);
90
91     enum EidType {
92         EID_SRC_DST, EID_WITH_PREFIX
93     }
94
95     MultiSiteScenario(final IMappingService mapService, final IFlowMapping lms) {
96         this.mapService = mapService;
97         this.lms = lms;
98     }
99
100     private Ipv4AddressBinary verifyIpv4Address(final LocatorRecord locatorRecord) {
101         assertNotNull(locatorRecord);
102         final Rloc rloc = locatorRecord.getRloc();
103         assertNotNull(rloc);
104         final Address address = rloc.getAddress();
105         assertTrue(address instanceof Ipv4Binary);
106         return ((Ipv4Binary) address).getIpv4Binary();
107     }
108
109     private List<LocatorRecord> verifyLocatorRecordExists(final MappingRecord mappingRecord) {
110         final List<LocatorRecord> locatorRecords = mappingRecord.getLocatorRecord();
111         assertNotNull(locatorRecords);
112         return locatorRecords;
113     }
114
115     private MappingRecord verifyMappingRecord(MapReply mapReply) {
116         assertNotNull(mapReply);
117         final List<MappingRecordItem> mappingRecordItems = mapReply.getMappingRecordItem();
118         assertNotNull(mappingRecordItems);
119         assertEquals(1, mappingRecordItems.size());
120         final MappingRecordItem mappingRecordItem = mappingRecordItems.get(0);
121         assertNotNull(mappingRecordItem);
122         final MappingRecord mappingRecord = mappingRecordItem.getMappingRecord();
123         assertNotNull(mappingRecord);
124         return mappingRecord;
125     }
126
127     private void emitMapRegisterMessage(final Site dstSite, final boolean merge) {
128         final MapRegisterBuilder mapRegisterBuilder = new MapRegisterBuilder();
129         mapRegisterBuilder.setXtrSiteIdPresent(true);
130         mapRegisterBuilder.setXtrId(dstSite.getXtrId());
131         mapRegisterBuilder.setSiteId(new SiteId(DEFAULT_SITE_ID));
132         mapRegisterBuilder.setMergeEnabled(merge);
133         final MappingRecordItemBuilder mappingRecordItemBuilder = new MappingRecordItemBuilder();
134         mappingRecordItemBuilder.setMappingRecordItemId(MAP_RECORD_A);
135
136         final MappingRecordBuilder mrb = prepareMappingRecord(EidType.EID_WITH_PREFIX, null, dstSite);
137         mappingRecordItemBuilder.setMappingRecord(mrb.build());
138         mapRegisterBuilder.setMappingRecordItem(Collections.singletonList(mappingRecordItemBuilder.build()));
139
140         lms.handleMapRegister(mapRegisterBuilder.build());
141     }
142
143     void setCommonAuthentication() {
144         Eid eid = LispAddressUtil.asIpv4PrefixBinaryEid("0.0.0.0/0", SITE_A.getVNI());
145         mapService.addAuthenticationKey(eid, NULL_AUTH_KEY);
146
147         eid = LispAddressUtil.asIpv4PrefixBinaryEid("0.0.0.0/0", SITE_D5.getVNI());
148         mapService.addAuthenticationKey(eid, NULL_AUTH_KEY);
149         sleepForSeconds(1);
150     }
151
152     private Eid toEid(final String destSiteEidPrefix, final InstanceIdType vniValue, final int mask) {
153         return LispAddressUtil.asIpv4PrefixBinaryEid(destSiteEidPrefix + "/" + mask, vniValue);
154
155     }
156
157     private MapReply emitMapRequestMessage(final String siteFromEidPrefix, final String siteToEidPrefix, final
158     InstanceIdType vniValue) {
159         final MapRequestBuilder mapRequestBuilder = new MapRequestBuilder();
160         final EidItemBuilder eidItemBuilder = new EidItemBuilder();
161         Eid dstEid = toEid(siteToEidPrefix, vniValue, IP_MASK);
162
163         eidItemBuilder.setEid(dstEid);
164         eidItemBuilder.setEidItemId(siteFromEidPrefix + siteToEidPrefix);
165         final List<EidItem> eidItem = Collections.singletonList(eidItemBuilder.build());
166         final Eid srcEid = toEid(siteFromEidPrefix, vniValue, IP_MASK);
167         mapRequestBuilder.setSourceEid(new SourceEidBuilder().setEid(srcEid).build());
168         mapRequestBuilder.setEidItem(eidItem);
169         mapRequestBuilder.setItrRloc(prepareDummyItrRloc());
170         mapRequestBuilder.setSmrInvoked(false);
171         return lms.handleMapRequest(mapRequestBuilder.build());
172     }
173
174     /**
175      * This method expects a SMR Map-Request as input, which it will turn into a SMR-invoked Map-Request and use the
176      * LISP mapping service to send it
177      *
178      * @param mapRequest the SMR Map-Request
179      */
180     private void emitSMRInvokedMapRequestMessage(MapRequest mapRequest) {
181         if (mapRequest.getEidItem().isEmpty()) {
182             fail("Empty SMR received!");
183         }
184
185         Eid srcEid = addMaximumPrefixIfNecessary(mapRequest.getSourceEid().getEid());
186         final EidItemBuilder eidItemBuilder = new EidItemBuilder();
187         eidItemBuilder.setEid(srcEid);
188         eidItemBuilder.setEidItemId(LispAddressStringifier.getString(srcEid));
189         final List<EidItem> eidItem = Collections.singletonList(eidItemBuilder.build());
190
191         final MapRequestBuilder mapRequestBuilder = new MapRequestBuilder(mapRequest);
192         mapRequestBuilder.setSmr(false);
193         mapRequestBuilder.setSmrInvoked(true);
194         mapRequestBuilder.setItrRloc(prepareDummyItrRloc());
195         mapRequestBuilder.setEidItem(eidItem);
196         for (EidItem ei : mapRequest.getEidItem()) {
197             mapRequestBuilder.setSourceEid(new SourceEidBuilder().setEid(ei.getEid()).build());
198             LOG.debug("Sending SMR-invoked Map-Reqeust for EID {}, Source EID {}",
199                     LispAddressStringifier.getString(srcEid),
200                     LispAddressStringifier.getString(ei.getEid()));
201             lms.handleMapRequest(mapRequestBuilder.build());
202         }
203     }
204
205     /*
206      * Since the Source EID field from a Map-Request packet does not have a prefix length field, IPv4 and IPv6 addresses
207      * are serialized into Ipv4Binary and Ipv6Binary objects. However, when we want to use the addresses in a
208      * SMR-invoked Map-Request, we need to use an Ipv4PrefixBinary or Ipv6PrefixBinary object respectively, since that's
209      * what the EID item field would be deserialized into.
210      */
211     private static Eid addMaximumPrefixIfNecessary(Eid eid) {
212         Address address = eid.getAddress();
213         if (address instanceof Ipv4Binary) {
214             return LispAddressUtil.asIpv4PrefixBinaryEid(
215                     eid, ((Ipv4Binary) address).getIpv4Binary().getValue(), MaskUtil.IPV4_MAX_MASK);
216         } else if (address instanceof Ipv6Binary) {
217             return LispAddressUtil.asIpv6PrefixBinaryEid(
218                     eid, ((Ipv6Binary) address).getIpv6Binary().getValue(), MaskUtil.IPV6_MAX_MASK);
219         }
220         return eid;
221     }
222
223     private List<ItrRloc> prepareDummyItrRloc() {
224         List<ItrRloc> itrRlocs = new ArrayList<>();
225         final ItrRlocBuilder itrRlocBuilder = new ItrRlocBuilder();
226         itrRlocBuilder.setItrRlocId(ourAddress);
227         itrRlocBuilder.setRloc(LispAddressUtil.asIpv4Rloc(ourAddress));
228         itrRlocs.add(itrRlocBuilder.build());
229         return itrRlocs;
230     }
231
232     void storeNorthMappingNegative(final Site dstSite, final MappingRecord.Action action) {
233         final Eid eidAsIpv4Prefix = LispAddressUtil.asIpv4PrefixBinaryEid(
234                 dstSite.getEidPrefix() + "/" + DEFAULT_NETWORK_MASK, dstSite.getVNI());
235
236         final MappingRecordBuilder mrbNegative = prepareMappingRecord(EidType.EID_WITH_PREFIX, null, dstSite);
237         mrbNegative.setEid(eidAsIpv4Prefix);
238         mrbNegative.setAction(action);
239
240         mapService.addMapping(MappingOrigin.Northbound, eidAsIpv4Prefix, new SiteId(DEFAULT_SITE_ID),
241                 new MappingData(mrbNegative.build()));
242     }
243
244     void deleteNorthMappingNegative(final Site dstSite) {
245         final Eid eidAsIpv4Prefix = LispAddressUtil.asIpv4PrefixBinaryEid(
246                 dstSite.getEidPrefix() + "/" + DEFAULT_NETWORK_MASK, dstSite.getVNI());
247
248         mapService.removeMapping(MappingOrigin.Northbound, eidAsIpv4Prefix);
249     }
250
251     void storeNorthMappingSrcDst(final Site srcSite, final Site ... dstSite) {
252         final MappingRecordBuilder mrb = prepareMappingRecord(EidType.EID_SRC_DST, srcSite,
253                 dstSite);
254         mapService.addMapping(MappingOrigin.Northbound, mrb.getEid(), new SiteId(DEFAULT_SITE_ID),
255                 new MappingData(mrb.build()));
256     }
257
258     void storeNorthMappingIpPrefix(final Site... dstSite) {
259         final MappingRecordBuilder mrb = prepareMappingRecord(EidType.EID_WITH_PREFIX, null, dstSite);
260         mapService.addMapping(MappingOrigin.Northbound, mrb.getEid(),  new SiteId(DEFAULT_SITE_ID),
261                 new MappingData(mrb.build()));
262     }
263
264     private void storeDestinationSiteMappingViaSouthbound(final Site dstSite, final boolean merge) {
265         emitMapRegisterMessage(dstSite, merge);
266     }
267
268     private MappingRecordBuilder prepareMappingRecordGeneral(final EidType eidType,
269                                                              final Site srcSite, final Site dstSite) {
270         final MappingRecordBuilder mrb = provideCommonMapRecordBuilder();
271         mrb.setXtrId(dstSite.getXtrId());
272
273         Eid eid = null;
274         if (EidType.EID_SRC_DST.equals(eidType)) {
275             if (srcSite != null && dstSite != null && srcSite.getEidPrefix() != null && dstSite.getEidPrefix() !=
276                     null) {
277                 eid = LispAddressUtil.asSrcDstEid(srcSite.getEidPrefix(), dstSite.getEidPrefix(), DEFAULT_NETWORK_MASK,
278                         DEFAULT_NETWORK_MASK, dstSite.getVNI().getValue().intValue());
279             }
280         }
281
282         mrb.setEid(eid == null ? toEid(dstSite.getEidPrefix(), dstSite.getVNI(), DEFAULT_NETWORK_MASK) : eid);
283         return mrb;
284     }
285
286     private MappingRecordBuilder prepareMappingRecord(final EidType eidType, final Site srcSite, final Site...
287             dstSites) {
288         assertTrue(isEidEquals(dstSites));
289         final MappingRecordBuilder mrb = prepareMappingRecordGeneral(eidType, srcSite, dstSites[0]);
290         final List<LocatorRecord> locatorRecords = new ArrayList<>();
291         if (!dstSites[0].isForDeletion) {
292             for (Site dstSite : dstSites) {
293                 if (dstSite.getRloc() != null) {
294                     locatorRecords.add(provideLocatorRecord(LispAddressUtil.asIpv4Rloc(dstSite.getRloc()),
295                             dstSite.getRloc(), dstSite.getWeight(), dstSite.getPriority()));
296                 }
297             }
298         }
299         mrb.setLocatorRecord(locatorRecords);
300
301         return mrb;
302     }
303
304     private boolean isEidEquals(final Site... sites) {
305         String commonEid = null;
306         for (Site site : sites) {
307             final String concreteEidPrefix = site.getEidPrefix();
308             if (!concreteEidPrefix.equals(commonEid)) {
309                 if (commonEid == null) {
310                     commonEid = concreteEidPrefix;
311                 } else {
312                     return false;
313                 }
314             }
315         }
316         return true;
317     }
318
319     private LocatorRecord provideLocatorRecord(final Rloc rloc, final String rlocStr, final short weight, final short
320             priority) {
321         final LocatorRecordBuilder locatorRecordBuilder = new LocatorRecordBuilder();
322         locatorRecordBuilder.setRloc(rloc);
323         locatorRecordBuilder.setLocatorId(rlocStr);
324         locatorRecordBuilder.setPriority(priority);
325         locatorRecordBuilder.setWeight(weight);
326         locatorRecordBuilder.setMulticastPriority(DEFAULT_MULTICAST_PRIORITY);
327         locatorRecordBuilder.setMulticastWeight(DEFAULT_MULTICAST_WEIGHT);
328         locatorRecordBuilder.setLocalLocator(DEFAULT_LOCAL_LOCATOR);
329         locatorRecordBuilder.setRlocProbed(DEFAULT_RLOC_PROBED);
330         locatorRecordBuilder.setRouted(DEFAULT_ROUTED);
331         return locatorRecordBuilder.build();
332     }
333
334     private MappingRecordBuilder provideCommonMapRecordBuilder() {
335         final MappingRecordBuilder mappingRecordBuilder = new MappingRecordBuilder();
336         mappingRecordBuilder.setRecordTtl(TTL);
337         mappingRecordBuilder.setAction(MappingRecord.Action.NoAction);
338         mappingRecordBuilder.setAuthoritative(true);
339         mappingRecordBuilder.setTimestamp(System.currentTimeMillis());
340         return mappingRecordBuilder;
341     }
342
343     void deleteNorthMapingSrcDst(final Site srcSite, final Site dstSite) {
344         final Eid eid = LispAddressUtil.asSrcDstEid(srcSite.getEidPrefix(), dstSite.getEidPrefix(),
345                 DEFAULT_NETWORK_MASK, DEFAULT_NETWORK_MASK, dstSite.getVNI().getValue().intValue());
346         mapService.removeMapping(MappingOrigin.Northbound, eid);
347     }
348
349     void deleteSouthboundMappings(final Site dstSite) {
350         emitMapRegisterMessage(dstSite, false);
351
352     }
353
354     void storeSouthboundMappings(final boolean merge, final Site ... sites) {
355         for (Site site : sites) {
356             storeDestinationSiteMappingViaSouthbound(site, merge);
357         }
358     }
359
360     boolean isPossibleAssertPingResultImmediately(final boolean expectedPingWorks, final boolean isPartialyWorking,
361                                                   final String  msg) {
362         //ping fail is unwanted. ping definitely failed
363         if (expectedPingWorks && !isPartialyWorking) {
364             fail(msg);
365         }
366
367         //ping fail is wanted. still can fail later
368         if (!expectedPingWorks && isPartialyWorking) {
369             return false;
370         }
371
372         //ping fail is unwanted. still can fail later
373         if (expectedPingWorks && isPartialyWorking) {
374             return false;
375         }
376
377         //ping fail is wanted. ping definitely failed.
378         if (!expectedPingWorks && !isPartialyWorking) {
379             return true;
380         }
381         return false;
382     }
383
384     boolean checkActionAndRloc(final Site dstSite, boolean expectedPingWorks, MapReply mapReplyFromSrcToDst, final
385                                 Site  ... additionalSitesFromMapping) {
386         final MappingRecord mappingRecord = verifyMappingRecord(mapReplyFromSrcToDst);
387         final boolean isNotDroppendSrcDst = !MappingRecord.Action.Drop.equals(mappingRecord.getAction());
388
389         if (isPossibleAssertPingResultImmediately(expectedPingWorks, isNotDroppendSrcDst, "Drop action has appeared " +
390                 "during ping")) {
391             return true;
392         }
393
394         final List<LocatorRecord> locatorRecords = verifyLocatorRecordExists(mappingRecord);
395         for (Site expectedTargetSite : concatenateSites(dstSite, additionalSitesFromMapping)) {
396             boolean expectedTargetFound = false;
397             for (LocatorRecord locatorRecord : locatorRecords) {
398                 if (expectedTargetSite.getRloc().equals(rlocToString(locatorRecord))) {
399                     final byte[] ipv4AddressSrcDst = verifyIpv4Address(locatorRecord).getValue();
400                     final byte[] rloc = InetAddresses.forString((expectedTargetSite.getRloc())).getAddress();
401                     final boolean isRlocSrcDstEqual = Arrays.equals(ipv4AddressSrcDst, rloc);
402                     if (isPossibleAssertPingResultImmediately(expectedPingWorks, isRlocSrcDstEqual, "Unexpected RLOC." +
403                             "Expected value " + rloc + ". Real value " + ipv4AddressSrcDst +
404                             ".")) {
405                         return true;
406                     }
407
408                     final boolean isWeightEquals = expectedTargetSite.getWeight() == locatorRecord.getWeight();
409                     if (isPossibleAssertPingResultImmediately(expectedPingWorks, isWeightEquals, "Weight isn't equal." +
410                             "Expected value " + expectedTargetSite.getWeight() + ". Value from mapping" +
411                             locatorRecord.getWeight() + ".")) {
412                         return true;
413                     }
414
415                     final boolean isPriorityEquals = expectedTargetSite.getPriority() == locatorRecord.getPriority();
416                     if (isPossibleAssertPingResultImmediately(expectedPingWorks, isPriorityEquals, "Priority isn't " +
417                             "equal. Expected value " + expectedTargetSite.getPriority() + ". Value from mapping" +
418                             locatorRecord.getPriority() + ".")) {
419                         return true;
420                     }
421
422                     expectedTargetFound = true;
423                     break;
424                 }
425             }
426             if (isPossibleAssertPingResultImmediately(expectedPingWorks, expectedTargetFound, "Mapping for " +
427                 expectedTargetSite.getRloc() + " was expected but wasn't returned from mapping service." +
428                 expectedTargetFound)) {
429                 return true;
430             }
431
432         }
433
434         return false;
435     }
436
437     private String rlocToString(final LocatorRecord locatorRecord) {
438         return LispAddressStringifier.getString(locatorRecord.getRloc());
439     }
440
441     private Iterable<Site> concatenateSites(final Site dstSite, final Site... additionalSitesFromMapping) {
442         final List<Site> sites = new ArrayList<>();
443         sites.add(dstSite);
444         for (Site additionalSite : additionalSitesFromMapping) {
445             sites.add(additionalSite);
446         }
447         return sites;
448     }
449
450     private void assertPing(final Site srcSite, final int srcHostIndex, final Site dstSite, final int dstHostIndex,
451                          boolean expectedPingWorks, final Site ... additionalSitesFromMapping) {
452         final MapReply mapReplyFromSrcToDst = emitMapRequestMessage(srcSite.getHost(srcHostIndex), dstSite.getHost
453                 (dstHostIndex), dstSite.getVNI());
454         if (checkActionAndRloc(dstSite, expectedPingWorks, mapReplyFromSrcToDst, additionalSitesFromMapping)) {
455             return;
456         }
457
458         final MapReply mapReplyFromDstToSrc = emitMapRequestMessage(dstSite.getHost(dstHostIndex), srcSite.getHost
459                 (srcHostIndex), srcSite.getVNI());
460         if (checkActionAndRloc(srcSite, expectedPingWorks, mapReplyFromDstToSrc)) {
461             return;
462         }
463
464         final InstanceIdType iidDst = mapReplyFromSrcToDst.getMappingRecordItem().get(0).getMappingRecord().getEid().
465                 getVirtualNetworkId();
466         final InstanceIdType iidSrc = mapReplyFromDstToSrc.getMappingRecordItem().get(0).getMappingRecord().getEid().
467                 getVirtualNetworkId();
468
469         final boolean isIIDEqual = iidDst.equals(iidSrc);
470
471         if (expectedPingWorks != isIIDEqual) {
472             fail("IID problem. Dst value " + iidDst.getValue() + ". Src value " + iidSrc.getValue() + ".");
473         }
474     }
475
476     void assertPingWorks(final Site srcSite, final int srcHostIndex, final Site dstSite, final int dstHostIndex,
477                          final Site ... additionalSitesFromMapping) {
478         assertPing(srcSite, srcHostIndex, dstSite, dstHostIndex, true, additionalSitesFromMapping);
479     }
480
481     void assertPingFails(final Site srcSite, final int srcHostIndex, final Site dstSite, final int dstHostIndex) {
482         assertPing(srcSite, srcHostIndex, dstSite, dstHostIndex, false);
483     }
484
485     private void sleepForSeconds(int seconds) {
486         try {
487             Thread.sleep(seconds * 1000);
488         } catch (InterruptedException e) {
489             LOG.trace("Interrupted while sleeping", e);
490         }
491     }
492
493
494     private List<MapRequest> translateBuffersToMapRequest(byte[][] buffers) {
495         final List<MapRequest> mapRequests = new ArrayList<>();
496         for (byte[] buffer : buffers) {
497             if (isBufferEmpty(buffer)) {
498                 LOG.error("Empty buffer while translating Map-Request");
499                 continue;
500             }
501             final MapRequest mapRequest = MapRequestSerializer.getInstance().deserialize(ByteBuffer.wrap(buffer), null);
502             assertNotNull(mapRequest);
503             mapRequests.add(mapRequest);
504         }
505         return mapRequests;
506     }
507
508     private Set<Eid> prepareExpectedEid(final String ... hosts) {
509         final Set<Eid> eids = new HashSet<>();
510         for (String host : hosts) {
511             eids.add(LispAddressUtil.asIpv4PrefixBinaryEid(host + "/" + IP_MASK,
512                     new InstanceIdType(MultiSiteScenarioUtil.VNI2)));
513         }
514         return eids;
515     }
516
517     private SourceEid prepareSourceEid(final String eidPrefix) {
518         final SourceEidBuilder sourceEidBuilder = new SourceEidBuilder();
519         final Eid eid = LispAddressUtil.asIpv4Eid(eidPrefix, MultiSiteScenarioUtil.VNI2);
520         return sourceEidBuilder.setEid(eid).build();
521     }
522
523     void checkSMR(final SocketReader socketReader, final String site, final String ... hosts) {
524         LOG.debug("\n" + mapService.prettyPrintMappings());
525         byte[][] buffers = socketReader.getBuffers(hosts.length);
526         if (areBuffersEmpty(buffers)) {
527             fail("No SMR received!");
528         }
529         List<MapRequest> mapRequests = translateBuffersToMapRequest(buffers);
530         if (hosts.length != mapRequests.size()) {
531             LOG.error("Expected {} SMRs, received {}", hosts.length, mapRequests.size());
532             fail("Unexpected number of SMRs received");
533         }
534         final Set<Eid> eids = prepareExpectedEid(hosts);
535         final SourceEid expectedSourceEid = prepareSourceEid(site);
536         for(MapRequest mapRequest : mapRequests) {
537             LOG.trace("Map-Request: {}", mapRequest);
538             assertTrue(mapRequest.isSmr());
539             final SourceEid receivedSourceEid = mapRequest.getSourceEid();
540             assertEquals(expectedSourceEid, receivedSourceEid);
541             final List<EidItem> currentEidItems = mapRequest.getEidItem();
542             assertNotNull(currentEidItems);
543             assertTrue(SMRContainsExpectedEid(eids, currentEidItems));
544             emitSMRInvokedMapRequestMessage(mapRequest);
545         }
546         //all expected eids should be after looping via mapRequests matched.
547         assertTrue("Expected eids wasn't/weren't found " + eids, eids.isEmpty());
548     }
549
550     private boolean SMRContainsExpectedEid(Set<Eid> eids, List<EidItem> currentEidItems) {
551         for (EidItem eidItem : currentEidItems) {
552             //if eid from map request is matched then it is removed from set of expected eids
553             if (!eids.remove(eidItem.getEid())) {
554                  fail("SMR contained EID `" + LispAddressStringifier.getString(eidItem.getEid())
555                          + "' which wasn't expected.");
556             }
557         }
558         return true;
559     }
560
561     private static boolean isBufferEmpty(byte[] buffer) {
562         for (byte b : buffer) {
563             if (b != 0) {
564                 return false;
565             }
566         }
567         return true;
568     }
569
570     protected static boolean areBuffersEmpty(byte[][] buffers) {
571         for (byte[] buffer : buffers) {
572             if (!isBufferEmpty(buffer)) {
573                 return false;
574             }
575         }
576         return true;
577     }
578 }