af8d77ee9179813accbd7821fc4273f0f1f59fb8
[unimgr.git] / netvirt / src / main / java / org / opendaylight / unimgr / mef / netvirt / NetvirtVpnUtils.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.unimgr.mef.netvirt;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.List;
14 import java.util.UUID;
15
16 import org.apache.commons.net.util.SubnetUtils;
17 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.genius.mdsalutil.MDSALUtil;
22 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
23 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
24 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
30 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
31 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddressBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64 import com.google.common.base.Optional;
65
66 public class NetvirtVpnUtils {
67     private static final Logger logger = LoggerFactory.getLogger(NetvirtVpnUtils.class);
68     private final static String ELAN_PREFIX = "elan.";
69     private final static String TRUNK_SUFFIX = "-trunk";
70     private final static String VLAN_SEPARATOR = ".";
71     private final static String IP_ADDR_SUFFIX = "/32";
72     private final static String IP_MUSK_SEPARATOR = "/";
73     private final static int MaxRetries = 10;
74
75     public static void createVpnInstance(DataBroker dataBroker, String instanceName) {
76         VpnInstanceBuilder builder = new VpnInstanceBuilder();
77         builder.setVpnInstanceName(instanceName);
78         Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder();
79         ipv4FamilyBuilder.setVpnTargets(new VpnTargetsBuilder().build());
80         // WA till netvirt will allow creation of VPN without RD
81         UUID vpnId = UUID.fromString(instanceName);
82         String rd = String.valueOf(Math.abs(vpnId.getLeastSignificantBits()));
83         ipv4FamilyBuilder.setRouteDistinguisher(rd);
84         builder.setIpv4Family(ipv4FamilyBuilder.build());
85
86         MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
87                 getVpnInstanceInstanceIdentifier(instanceName), builder.build());
88     }
89
90     public static void createUpdateVpnInterface(DataBroker dataBroker, String vpnName, String interfaceName,
91             IpPrefix ifPrefix, MacAddress macAddress, boolean primary, IpPrefix gwIpAddress) {
92         synchronized (interfaceName.intern()) {
93             String ipAddress = null;
94             String nextHopIp = null;
95             if (primary) {
96                 ipAddress = getPrefixFromSubnet(MefUtils.ipPrefixToString(ifPrefix));
97             } else {
98                 ipAddress = MefUtils.ipPrefixToString(ifPrefix);
99                 nextHopIp = getIpAddressFromPrefix(MefUtils.ipPrefixToString(gwIpAddress));
100             }
101
102             Adjacencies adjancencies = buildInterfaceAdjacency(ipAddress, macAddress, primary, nextHopIp);
103             VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, adjancencies);
104
105             MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
106                     getVpnInterfaceInstanceIdentifier(interfaceName), einterfaceBuilder.build());
107         }
108     }
109
110     private static Adjacencies buildInterfaceAdjacency(String ipAddress, MacAddress macAddress, boolean primary,
111             String nextHopIp) {
112         AdjacenciesBuilder builder = new AdjacenciesBuilder();
113         List<Adjacency> list = new ArrayList<>();
114
115         AdjacencyBuilder aBuilder = new AdjacencyBuilder();
116         aBuilder.setIpAddress(ipAddress);
117         if (macAddress != null) {
118             aBuilder.setMacAddress(macAddress.getValue());
119         }
120         aBuilder.setPrimaryAdjacency(primary);
121         if (nextHopIp != null) {
122             aBuilder.setNextHopIpList(Arrays.asList(nextHopIp));
123         }
124         list.add(aBuilder.build());
125
126         builder.setAdjacency(list);
127         return builder.build();
128     }
129
130     private static VpnInterfaceBuilder createVpnInterface(String instanceName, String interfaceName,
131             Adjacencies adjacencies) {
132         VpnInterfaceBuilder einterfaceBuilder = new VpnInterfaceBuilder();
133         einterfaceBuilder.setVpnInstanceName(instanceName);
134         einterfaceBuilder.setName(interfaceName);
135         einterfaceBuilder.addAugmentation(Adjacencies.class, adjacencies);
136         return einterfaceBuilder;
137     }
138
139     private static InstanceIdentifier<VpnInstance> getVpnInstanceInstanceIdentifier(String instanceName) {
140         return InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey(instanceName))
141                 .build();
142     }
143
144     private static InstanceIdentifier<VpnInterface> getVpnInterfaceInstanceIdentifier(String interfaceName) {
145         return InstanceIdentifier.builder(VpnInterfaces.class)
146                 .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).build();
147     }
148
149     public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, IpPrefix ipAddress,
150             MacAddress macAddress) {
151         String fixedIpPrefix = MefUtils.ipPrefixToString(ipAddress);
152         String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
153         createVpnPortFixedIp(dataBroker, vpnName, portName, fixedIp, macAddress);
154     }
155
156     public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, IpAddress ipAddress,
157             MacAddress macAddress) {
158         String fixedIp = MefUtils.ipAddressToString(ipAddress);
159         createVpnPortFixedIp(dataBroker, vpnName, portName, fixedIp, macAddress);
160     }
161
162     public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, String fixedIp,
163             MacAddress macAddress) {
164         synchronized ((vpnName + fixedIp).intern()) {
165             InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
166             VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder()
167                     .setKey(new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp)
168                     .setPortName(portName).setMacAddress(macAddress.getValue()).setSubnetIp(true).setConfig(true)
169                     .setLearnt(false);
170             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, builder.build());
171             logger.debug(
172                     "Interface to fixedIp added: {}, vpn {}, interface {}, mac {} added to " + "VpnPortipToPort DS",
173                     fixedIp, vpnName, portName, macAddress);
174         }
175     }
176
177     static InstanceIdentifier<NetworkMap> buildNetworkMapIdentifier(Uuid networkId) {
178         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
179                 .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
180         return id;
181     }
182
183     private static void createSubnetToNetworkMapping(DataBroker dataBroker, Uuid subnetId, Uuid networkId) {
184         InstanceIdentifier<NetworkMap> networkMapIdentifier = buildNetworkMapIdentifier(networkId);
185         Optional<NetworkMap> optionalNetworkMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
186                 networkMapIdentifier);
187         NetworkMapBuilder nwMapBuilder = null;
188         if (optionalNetworkMap.isPresent()) {
189             nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
190         } else {
191             nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
192             logger.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
193         }
194         List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
195         if (subnetIdList == null) {
196             subnetIdList = new ArrayList<>();
197         }
198         subnetIdList.add(subnetId);
199         nwMapBuilder.setSubnetIdList(subnetIdList);
200         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
201         logger.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
202                 networkId.getValue());
203     }
204
205     private static InstanceIdentifier<VpnPortipToPort> buildVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
206         InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
207                 .child(VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
208         return id;
209     }
210
211     public static void addDirectSubnetToVpn(DataBroker dataBroker,
212             final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
213             IpPrefix subnetIpPrefix, String interfaceName) {
214         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
215                 .child(ElanInstance.class, new ElanInstanceKey(subnetName)).build();
216         Optional<ElanInstance> elanInstance = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
217                 elanIdentifierId);
218         if (!elanInstance.isPresent()) {
219             logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
220             return;
221         }
222         Long elanTag = elanInstance.get().getElanTag();
223
224         Uuid subnetId = new Uuid(subnetName);
225         logger.info("Adding subnet {} {} to elan map", subnetId);
226         createSubnetToNetworkMapping(dataBroker, subnetId, subnetId);
227
228         String subnetIp = getSubnetFromPrefix(MefUtils.ipPrefixToString(subnetIpPrefix));
229         logger.info("Adding subnet {} {} to vpn {}", subnetName, subnetIp, vpnName);
230         updateSubnetNode(dataBroker, new Uuid(vpnName), subnetId, subnetIp);
231
232         logger.info("Adding port {} to subnet {}", interfaceName, subnetName);
233         updateSubnetmapNodeWithPorts(dataBroker, subnetId, new Uuid(interfaceName));
234
235         logger.info("Publish subnet {}", subnetName);
236         publishSubnetAddNotification(notificationPublishService, subnetId, subnetIp, vpnName, elanTag);
237         logger.info("Finished Working on subnet {}", subnetName);
238
239     }
240
241     protected static void updateSubnetNode(DataBroker dataBroker, Uuid vpnId, Uuid subnetId, String subnetIp) {
242         Subnetmap subnetmap = null;
243         SubnetmapBuilder builder = null;
244         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
245                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
246
247         synchronized (subnetId.getValue().intern()) {
248             Optional<Subnetmap> sn = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
249             if (sn.isPresent()) {
250                 builder = new SubnetmapBuilder(sn.get());
251                 logger.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
252             } else {
253                 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
254                 logger.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
255             }
256
257             builder.setSubnetIp(subnetIp);
258             builder.setNetworkId(subnetId);
259             builder.setVpnId(vpnId);
260
261             subnetmap = builder.build();
262             logger.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
263             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
264         }
265     }
266
267     private static void updateSubnetmapNodeWithPorts(DataBroker dataBroker, Uuid subnetId, Uuid portId) {
268         Subnetmap subnetmap = null;
269         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
270                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
271         synchronized (subnetId.getValue().intern()) {
272             Optional<Subnetmap> sn = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
273             if (sn.isPresent()) {
274                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
275                 if (null != portId) {
276                     List<Uuid> portList = builder.getPortList();
277                     if (null == portList) {
278                         portList = new ArrayList<>();
279                     }
280                     portList.add(portId);
281                     builder.setPortList(portList);
282                     logger.debug("Updating subnetmap node {} with port {}", subnetId.getValue(), portId.getValue());
283                 }
284                 subnetmap = builder.build();
285                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
286             } else {
287                 logger.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
288             }
289         }
290     }
291
292     private static void publishSubnetAddNotification(final NotificationPublishService notificationPublishService,
293             Uuid subnetId, String subnetIp, String vpnName, Long elanTag) {
294         SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
295
296         logger.info("publish notification called");
297
298         builder.setSubnetId(subnetId);
299         builder.setSubnetIp(subnetIp);
300         builder.setVpnName(vpnName);
301         builder.setExternalVpn(true);
302         builder.setElanTag(elanTag);
303
304         try {
305             notificationPublishService.putNotification(builder.build());
306         } catch (InterruptedException e) {
307             logger.error("Fail to publish notification {}", builder, e);
308             throw new RuntimeException(e.getMessage());
309         }
310     }
311
312     private static String getIpAddressFromPrefix(String prefix) {
313         return prefix.split(IP_MUSK_SEPARATOR)[0];
314     }
315
316     private static String getMaskFromPrefix(String prefix) {
317         return prefix.split(IP_MUSK_SEPARATOR)[1];
318     }
319
320     private static String getSubnetFromPrefix(String prefix) {
321         SubnetInfo subnet = new SubnetUtils(prefix).getInfo();
322         return subnet.getNetworkAddress() + IP_MUSK_SEPARATOR + getMaskFromPrefix(prefix);
323     }
324
325     private static String getPrefixFromSubnet(String prefix) {
326         String myAddress = getIpAddressFromPrefix(prefix);
327         return myAddress + IP_ADDR_SUFFIX;
328     }
329
330     public static String getElanNameForVpnPort(String portName) {
331         return getUUidFromString(ELAN_PREFIX + portName);
332     }
333
334     public static String getInterfaceNameForVlan(String interfaceName, Integer vlan) {
335         final StringBuilder s = new StringBuilder();
336         s.append(interfaceName);
337         if (vlan != null) {
338             s.append(VLAN_SEPARATOR).append(vlan);
339         }
340         s.append(TRUNK_SUFFIX);
341         return getUUidFromString(s.toString());
342     }
343
344     public static String getUUidFromString(String key) {
345         return java.util.UUID.nameUUIDFromBytes(key.getBytes()).toString();
346     }
347
348     public static MacAddress resolveGwMac(DataBroker dataBroker, OdlArputilService arpUtilService, String vpnName,
349             IpPrefix srcIpPrefix, IpAddress dstIpAddress, String interf) {
350
351         String srcTpAddressStr = getIpAddressFromPrefix(MefUtils.ipPrefixToString(srcIpPrefix));
352         IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
353
354         if (srcIpAddress == null || dstIpAddress == null) {
355             logger.error("Can't send ARP to srcIp {} dstIp {}", srcIpAddress, dstIpAddress);
356             throw new RuntimeException("Can't send ARP for dstIp " + dstIpAddress);
357         }
358
359         MacAddress macAddress = null;
360         int retries = MaxRetries;
361         while (retries > 0 && macAddress == null) {
362             logger.info("Sending ARP request to dstIp {} take {}", dstIpAddress, MaxRetries - retries + 1);
363             sendArpRequest(arpUtilService, srcIpAddress, dstIpAddress, interf);
364             macAddress = waitForArpReplyProcessing(dataBroker, vpnName, dstIpAddress, MaxRetries);
365             retries--;
366         }
367         return macAddress;
368     }
369
370     private static void sendArpRequest(OdlArputilService arpUtilService, IpAddress srcIpAddress, IpAddress dstIpAddress,
371             String interf) {
372         try {
373             List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
374             interfaceAddresses
375                     .add(new InterfaceAddressBuilder().setInterface(interf).setIpAddress(srcIpAddress).build());
376
377             SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(dstIpAddress)
378                     .setInterfaceAddress(interfaceAddresses).build();
379             arpUtilService.sendArpRequest(sendArpRequestInput);
380         } catch (Exception e) {
381             logger.error("Failed to send ARP request to IP {} from interfaces {}",
382                     dstIpAddress.getIpv4Address().getValue(), interf, e);
383             throw new RuntimeException(e.getMessage());
384         }
385     }
386
387     public static MacAddress waitForArpReplyProcessing(DataBroker dataBroker, String vpnName, IpAddress dstIpAddress,
388             int retries) {
389         while (retries > 0) {
390             logger.info("Waiting for ARP reply from dstIp {} take {}", dstIpAddress, MaxRetries - retries + 1);
391             InstanceIdentifier<VpnPortipToPort> optionalPortIpId = buildVpnPortipToPortIdentifier(vpnName,
392                     MefUtils.ipAddressToString(dstIpAddress));
393             Optional<VpnPortipToPort> optionalPortIp = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
394                     optionalPortIpId);
395
396             if (optionalPortIp.isPresent()) {
397                 return new MacAddress(optionalPortIp.get().getMacAddress());
398             } else {
399                 sleep();
400             }
401             retries--;
402         }
403         return null;
404     }
405
406     private static void sleep() {
407         try {
408             Thread.sleep(1000);
409         } catch (InterruptedException e) {
410         }
411     }
412 }