d2999f300cb22b3d618286138a8c4c80cb530373
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / SubnetRoutePacketInHandler.java
1 /*
2  * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. 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.netvirt.vpnmanager;
9
10 import com.google.common.base.Optional;
11 import com.google.common.primitives.Ints;
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import javax.annotation.Nullable;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
24 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
25 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
26 import org.opendaylight.genius.mdsalutil.NWUtil;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.packet.Ethernet;
29 import org.opendaylight.genius.mdsalutil.packet.IPv4;
30 import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
31 import org.opendaylight.netvirt.vpnmanager.api.ICentralizedSwitchProvider;
32 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
33 import org.opendaylight.netvirt.vpnmanager.iplearn.ipv4.ArpUtils;
34 import org.opendaylight.netvirt.vpnmanager.utilities.VpnManagerCounters;
35 import org.opendaylight.openflowplugin.libraries.liblldp.BitBufferHelper;
36 import org.opendaylight.openflowplugin.libraries.liblldp.BufferException;
37 import org.opendaylight.openflowplugin.libraries.liblldp.HexEncode;
38 import org.opendaylight.openflowplugin.libraries.liblldp.Packet;
39 import org.opendaylight.openflowplugin.libraries.liblldp.PacketException;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.Ipv6NdUtilService;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @Singleton
66 public class SubnetRoutePacketInHandler implements PacketProcessingListener {
67     private static final Logger LOG = LoggerFactory.getLogger(SubnetRoutePacketInHandler.class);
68     private static final String LOGGING_PREFIX = "SUBNETROUTE:";
69     private final DataBroker dataBroker;
70     private final PacketProcessingService packetService;
71     private final OdlInterfaceRpcService odlInterfaceRpcService;
72     private final ICentralizedSwitchProvider centralizedSwitchProvider;
73     private final IInterfaceManager interfaceManager;
74     private final VpnManagerCounters vpnManagerCounters;
75     private final Ipv6NdUtilService ipv6NdUtilService;
76     private final VpnUtil vpnUtil;
77
78     @Inject
79     public SubnetRoutePacketInHandler(final DataBroker dataBroker, final PacketProcessingService packetService,
80             final OdlInterfaceRpcService odlInterfaceRpcService,
81             final ICentralizedSwitchProvider centralizedSwitchProvider, final IInterfaceManager interfaceManager,
82             VpnManagerCounters vpnManagerCounters, final Ipv6NdUtilService ipv6NdUtilService, VpnUtil vpnUtil) {
83         this.dataBroker = dataBroker;
84         this.packetService = packetService;
85         this.odlInterfaceRpcService = odlInterfaceRpcService;
86         this.centralizedSwitchProvider = centralizedSwitchProvider;
87         this.interfaceManager = interfaceManager;
88         this.vpnManagerCounters = vpnManagerCounters;
89         this.ipv6NdUtilService = ipv6NdUtilService;
90         this.vpnUtil = vpnUtil;
91     }
92
93     @Override
94     public void onPacketReceived(PacketReceived notification) {
95
96         short tableId = notification.getTableId().getValue();
97         LOG.trace("{} onPacketReceived: Packet punted from table {}", LOGGING_PREFIX, tableId);
98         if (!vpnUtil.isArpLearningEnabled()) {
99             LOG.trace("Not handling packet as ARP Based Learning is disabled");
100             return;
101         }
102         byte[] data = notification.getPayload();
103         if (notification.getMatch() == null || notification.getMatch().getMetadata() == null) {
104             LOG.error("{} onPacketReceived: Received from table {} where the match or metadata are null",
105                     LOGGING_PREFIX, tableId);
106             return;
107         }
108         BigInteger metadata = notification.getMatch().getMetadata().getMetadata();
109         Ethernet res = new Ethernet();
110
111         if (tableId == NwConstants.L3_SUBNET_ROUTE_TABLE) {
112             LOG.trace("{} onPacketReceived: Some packet received as {}", LOGGING_PREFIX, notification);
113             try {
114                 res.deserialize(data, 0, data.length * Byte.SIZE);
115             } catch (PacketException e) {
116                 LOG.error("{} onPacketReceived: Failed to decode Packet ", LOGGING_PREFIX, e);
117                 vpnManagerCounters.subnetRoutePacketFailed();
118                 return;
119             }
120             byte[] srcIpBytes = null;
121             byte[] dstIpBytes = null;
122             String srcIpStr;
123             String dstIpStr;
124             String srcMac = NWUtil.toStringMacAddress(res.getSourceMACAddress());
125             try {
126                 Packet pkt = res.getPayload();
127                 if (pkt instanceof IPv4) {
128                     IPv4 ipv4 = (IPv4) pkt;
129                     srcIpBytes = Ints.toByteArray(ipv4.getSourceAddress());
130                     dstIpBytes = Ints.toByteArray(ipv4.getDestinationAddress());
131                     // It is an ARP request on a configured VPN. So we must
132                     // attempt to respond.
133                 } else {
134                     // IPv6 case
135                     // TODO: IPv6 deserializer
136                     int ethType = BitBufferHelper.getInt(
137                             BitBufferHelper.getBits(data, VpnConstants.ETHTYPE_START, VpnConstants.TWO_BYTES));
138                     if (ethType == VpnConstants.IP_V6_ETHTYPE) {
139                         srcIpBytes = BitBufferHelper.getBits(data, VpnConstants.IP_V6_HDR_START + 64, 128);
140                         dstIpBytes = BitBufferHelper.getBits(data, VpnConstants.IP_V6_HDR_START + 192, 128);
141                     }
142                 }
143                 if (srcIpBytes == null || dstIpBytes == null) {
144                     LOG.trace("{} onPacketReceived: Non-IP packet received as {}", LOGGING_PREFIX, notification);
145                     return;
146                 }
147                 srcIpStr = NWUtil.toStringIpAddress(srcIpBytes);
148                 dstIpStr = NWUtil.toStringIpAddress(dstIpBytes);
149
150                 handleIpPackets(srcIpBytes, dstIpBytes, srcIpStr, dstIpStr, srcMac, metadata);
151
152             } catch (UnknownHostException | InterruptedException | ExecutionException | BufferException ex) {
153                 // Failed to handle packet
154                 vpnManagerCounters.subnetRoutePacketFailed();
155                 LOG.error("{} onPacketReceived: Failed to handle subnetroute packet.", LOGGING_PREFIX, ex);
156             } catch (ReadFailedException e) {
157                 vpnManagerCounters.subnetRoutePacketFailed();
158                 LOG.error("{} onPacketReceived: Failed to read data-store.", LOGGING_PREFIX, e);
159             }
160             return;
161         }
162         // All Arp responses learning for invisble IPs is handled by
163         // ArpNotificationHandler
164
165     }
166
167     private void handleIpPackets(byte[] srcIp, byte[] dstIp, String srcIpStr, String dstIpStr, String srcMac,
168             BigInteger metadata)
169             throws UnknownHostException, InterruptedException, ExecutionException, ReadFailedException {
170         long vpnId = MetaDataUtil.getVpnIdFromMetadata(metadata);
171
172         LOG.info("{} onPacketReceived: Processing IP Packet received with Source IP {} and Target IP {}"
173                 + " and vpnId {}", LOGGING_PREFIX, srcIpStr, dstIpStr, vpnId);
174
175         Optional<VpnIds> vpnIdsOptional = SingleTransactionDataBroker.syncReadOptional(dataBroker,
176                 LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId));
177
178         if (!vpnIdsOptional.isPresent()) {
179             // Donot trigger subnetroute logic for packets from
180             // unknown VPNs
181             vpnManagerCounters.subnetRoutePacketIgnored();
182             LOG.info("{} onPacketReceived: Ignoring IPv4 packet with destination Ip {} and source Ip {}"
183                     + " as it came on unknown VPN with ID {}", LOGGING_PREFIX, dstIpStr, srcIpStr, vpnId);
184             return;
185         }
186
187         String vpnIdVpnInstanceName = vpnIdsOptional.get().getVpnInstanceName();
188         VpnPortipToPort persistedIP =
189                 vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnIdVpnInstanceName, dstIpStr);
190         if (persistedIP != null && !persistedIP.isLearntIp()) {
191             vpnManagerCounters.subnetRoutePacketIgnored();
192             LOG.info("{} onPacketReceived: IP Packet received with Target IP {} source IP {} vpnId {} "
193                     + "is a valid Neutron port,ignoring subnet route processing", LOGGING_PREFIX, dstIpStr,
194                     srcIp, vpnId);
195             return;
196         }
197
198         if (vpnUtil.getLearntVpnVipToPort(vpnIdVpnInstanceName, dstIpStr) != null) {
199             vpnManagerCounters.subnetRoutePacketIgnored();
200             LOG.info("{} onPacketReceived: IP Packet received with Target IP {} source Ip {} vpnId {}"
201                     + " is an already discovered IPAddress, ignoring subnet route processing",
202                     LOGGING_PREFIX, dstIpStr, srcIp, vpnId);
203             return;
204         }
205
206         long elanTag = MetaDataUtil.getElanTagFromMetadata(metadata);
207         if (elanTag == 0L) {
208             vpnManagerCounters.subnetRoutePacketFailed();
209             LOG.error("{} onPacketReceived: elanTag value from metadata found to be 0, for IP "
210                     + " Packet received with Target IP {} src Ip {} vpnId {}",
211                     LOGGING_PREFIX, dstIpStr, srcIp, vpnId);
212             return;
213         }
214
215         if (!vpnIdsOptional.get().isExternalVpn()) {
216             handleInternalVpnSubnetRoutePacket(metadata, dstIp, srcIpStr, dstIpStr, vpnIdVpnInstanceName,
217                     elanTag);
218             return;
219         }
220
221         handleBgpVpnSubnetRoute(srcMac, dstIp, dstIpStr, srcIpStr, elanTag);
222     }
223
224     private void handleBgpVpnSubnetRoute(String srcMac, byte[] dstIp, String dstIpStr, String srcIpStr,
225             long elanTag) throws UnknownHostException {
226         LOG.info("{} handleBgpVpnSubnetRoute: Processing IP Packet received with Source IP {} and Target IP {}"
227                 + " and elan Tag {}", LOGGING_PREFIX, srcIpStr, dstIpStr, elanTag);
228         SubnetOpDataEntry targetSubnetForPacketOut =
229                 getTargetSubnetForPacketOut(elanTag, dstIpStr);
230         if (targetSubnetForPacketOut != null) {
231             // Handle subnet routes ip requests
232             transmitArpOrNsPacket(targetSubnetForPacketOut.getNhDpnId(), srcIpStr, srcMac, dstIp, dstIpStr, elanTag);
233         } else {
234             vpnManagerCounters.subnetRoutePacketFailed();
235             LOG.debug("{} handleBgpVpnSubnetRoute: Could not find target subnet for packet out {}", LOGGING_PREFIX,
236                     dstIpStr);
237         }
238     }
239
240     private void handleInternalVpnSubnetRoutePacket(BigInteger metadata, byte[] dstIp, String srcIpStr, String dstIpStr,
241             String vpnIdVpnInstanceName, long elanTag)
242             throws InterruptedException, ExecutionException, UnknownHostException {
243         String vmVpnInterfaceName = vpnUtil.getVpnInterfaceName(metadata);
244         if (isTunnel(vmVpnInterfaceName)) {
245             handlePacketFromTunnelToExternalNetwork(vpnIdVpnInstanceName, srcIpStr, dstIp, dstIpStr, elanTag);
246         }
247         VpnInterface vmVpnInterface = vpnUtil.getVpnInterface(vmVpnInterfaceName);
248         if (vmVpnInterface == null) {
249             LOG.error("Vpn interface {} doesn't exist.", vmVpnInterfaceName);
250             vpnManagerCounters.subnetRoutePacketFailed();
251             return;
252         }
253         if (VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnIdVpnInstanceName,
254                vmVpnInterface.getVpnInstanceNames())
255                && !vpnUtil.isBgpVpnInternet(vpnIdVpnInstanceName)) {
256             LOG.trace("Unknown IP is in internal network");
257             handlePacketToInternalNetwork(dstIp, dstIpStr, elanTag);
258         } else {
259             LOG.trace("Unknown IP is in external network");
260             String vpnName = vpnUtil.getInternetVpnFromVpnInstanceList(vmVpnInterface.getVpnInstanceNames());
261             if (vpnName != null) {
262                 handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), vpnName, dstIp, dstIpStr, elanTag);
263             } else {
264                 vpnName = VpnHelper.getFirstVpnNameFromVpnInterface(vmVpnInterface);
265                 LOG.trace("Unknown IP is in external network, but internet VPN not found." + " fallback to first VPN");
266                 handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), vpnName, dstIp, dstIpStr, elanTag);
267
268             }
269         }
270     }
271
272     private void transmitArpOrNsPacket(BigInteger dpnId, String sourceIpAddress, String sourceMac, byte[] dstIpBytes,
273             String dstIpAddress, long elanTag) throws UnknownHostException {
274         long groupid = VpnUtil.getRemoteBCGroup(elanTag);
275         if (NWUtil.isIpv4Address(dstIpAddress)) {
276             LOG.debug("Sending ARP: srcIp={}, srcMac={}, dstIp={}, dpId={}, elan-tag={}, groupid={}", sourceIpAddress,
277                     sourceMac, dstIpAddress, dpnId, elanTag, groupid);
278             vpnManagerCounters.subnetRoutePacketArpSent();
279
280             TransmitPacketInput packetInput =
281                     ArpUtils.createArpRequestInput(dpnId, groupid, HexEncode.bytesFromHexString(sourceMac),
282                             InetAddress.getByName(sourceIpAddress).getAddress(), dstIpBytes);
283             JdkFutures.addErrorLogging(packetService.transmitPacket(packetInput), LOG, "Transmit packet");
284         } else {
285             // IPv6 case
286             LOG.debug("Sending NS: srcIp={}, srcMac={}, dstIp={}, dpId={}, elan-tag={}, groupid={}", sourceIpAddress,
287                     sourceMac, dstIpAddress, dpnId, elanTag, groupid);
288             vpnManagerCounters.subnetRoutePacketNsSent();
289
290             VpnUtil.sendNeighborSolicationToOfGroup(this.ipv6NdUtilService, new Ipv6Address(sourceIpAddress),
291                     new MacAddress(sourceMac), new Ipv6Address(dstIpAddress), groupid, dpnId);
292         }
293     }
294
295     private void handlePacketToInternalNetwork(byte[] dstIp, String dstIpStr, long elanTag)
296             throws UnknownHostException {
297         try {
298             SubnetOpDataEntry targetSubnetForPacketOut =
299                     getTargetSubnetForPacketOut(elanTag, dstIpStr);
300
301             if (targetSubnetForPacketOut == null) {
302                 LOG.debug("Couldn't find matching subnet for elan tag {} and destination ip {}", elanTag, dstIpStr);
303                 vpnManagerCounters.subnetRoutePacketFailed();
304                 return;
305             }
306
307             Optional<Subnetmap> subnetMap = SingleTransactionDataBroker.syncReadOptional(dataBroker,
308                     LogicalDatastoreType.CONFIGURATION,
309                     VpnUtil.buildSubnetmapIdentifier(targetSubnetForPacketOut.getSubnetId()));
310             if (!subnetMap.isPresent()) {
311                 LOG.debug("Couldn't find subnet map for subnet {}", targetSubnetForPacketOut.getSubnetId());
312                 vpnManagerCounters.subnetRoutePacketFailed();
313                 return;
314             }
315
316             String sourceIp = subnetMap.get().getRouterInterfaceFixedIp();
317             if (sourceIp == null) {
318                 LOG.debug("Subnet map {} doesn't have a router interface ip defined", subnetMap.get().getId());
319                 vpnManagerCounters.subnetRoutePacketFailed();
320                 return;
321             }
322
323             String sourceMac = subnetMap.get().getRouterIntfMacAddress();
324             if (sourceMac == null) {
325                 LOG.debug("Subnet map {} doesn't have a router interface mac address defined",
326                         subnetMap.get().getId());
327                 vpnManagerCounters.subnetRoutePacketFailed();
328                 return;
329             }
330
331             transmitArpOrNsPacket(targetSubnetForPacketOut.getNhDpnId(), sourceIp, sourceMac, dstIp, dstIpStr, elanTag);
332         } catch (ReadFailedException e) {
333             LOG.error("handlePacketToInternalNetwork: Failed to read data store for destIp {} elanTag {}", dstIpStr,
334                     elanTag);
335         }
336     }
337
338     private void handlePacketFromTunnelToExternalNetwork(String vpnIdVpnInstanceName, String srcIpStr, byte[] dstIp,
339         String dstIpStr, long elanTag) throws UnknownHostException {
340         String routerId = vpnUtil.getAssociatedExternalRouter(srcIpStr);
341         if (null == routerId) {
342             LOG.debug("This ip is not associated with any external router: {}", srcIpStr);
343             return;
344         }
345         handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), routerId, dstIp, dstIpStr, elanTag);
346     }
347
348     private void handlePacketToExternalNetwork(Uuid vpnInstanceNameUuid, String routerId, byte[] dstIp, String dstIpStr,
349             long elanTag) throws UnknownHostException {
350         Routers externalRouter = vpnUtil.getExternalRouter(routerId);
351         if (externalRouter == null) {
352             vpnManagerCounters.subnetRoutePacketFailed();
353             LOG.debug("{} handlePacketToExternalNetwork: Can't find external router with id {}", LOGGING_PREFIX,
354                     routerId);
355             return;
356         }
357
358         List<ExternalIps> externalIps = externalRouter.getExternalIps();
359         if (externalIps == null || externalIps.isEmpty()) {
360             vpnManagerCounters.subnetRoutePacketFailed();
361             LOG.debug("{} handlePacketToExternalNetwork: Router {} doesn't have any external ips.",
362                     LOGGING_PREFIX, externalRouter.getRouterName());
363             return;
364         }
365
366         java.util.Optional<ExternalIps> externalIp = externalRouter.getExternalIps().stream()
367                 .filter(eip -> vpnInstanceNameUuid.equals(eip.getSubnetId())).findFirst();
368         if (!externalIp.isPresent()) {
369             vpnManagerCounters.subnetRoutePacketFailed();
370             LOG.debug("{} handlePacketToExternalNetwork: Router {} doesn't have an external ip for subnet id {}.",
371                     LOGGING_PREFIX, externalRouter.getRouterName(), vpnInstanceNameUuid);
372             return;
373         }
374
375         BigInteger dpnId = centralizedSwitchProvider.getPrimarySwitchForRouter(externalRouter.getRouterName());
376         if (BigInteger.ZERO.equals(dpnId)) {
377             vpnManagerCounters.subnetRoutePacketFailed();
378             LOG.debug("{} handlePacketToExternalNetwork: Could not find primary switch for router {}.",
379                     LOGGING_PREFIX, externalRouter.getRouterName());
380             return;
381         }
382
383         transmitArpOrNsPacket(dpnId, externalIp.get().getIpAddress(), externalRouter.getExtGwMacAddress(), dstIp,
384                 dstIpStr, elanTag);
385     }
386
387     // return only the first VPN subnetopdataentry
388     @Nullable
389     private SubnetOpDataEntry getTargetSubnetForPacketOut(long elanTag, String ipAddress) {
390         ElanTagName elanInfo = vpnUtil.getElanInfoByElanTag(elanTag);
391         if (elanInfo == null) {
392             LOG.error("{} getTargetDpnForPacketOut: Unable to retrieve ElanInfo for elanTag {}", LOGGING_PREFIX,
393                     elanTag);
394             return null;
395         }
396         try {
397             Optional<NetworkMap> optionalNetworkMap = SingleTransactionDataBroker.syncReadOptional(dataBroker,
398                     LogicalDatastoreType.CONFIGURATION, VpnUtil.buildNetworkMapIdentifier(new Uuid(
399                             elanInfo.getName())));
400             if (!optionalNetworkMap.isPresent()) {
401                 LOG.debug("{} getTargetDpnForPacketOut: No network map found for elan info {}", LOGGING_PREFIX,
402                         elanInfo.getName());
403                 return null;
404             }
405             List<Uuid> subnetList = optionalNetworkMap.get().getSubnetIdList();
406             LOG.debug("{} getTargetDpnForPacketOut: Obtained subnetList as {} for network {}", LOGGING_PREFIX,
407                     subnetList, elanInfo.getName());
408             if (subnetList != null) {
409                 for (Uuid subnetId : subnetList) {
410                     String vpnName = null;
411                     Subnetmap sn = vpnUtil.getSubnetmapFromItsUuid(subnetId);
412                     if (sn != null && sn.getVpnId() != null) {
413                         vpnName = sn.getVpnId().getValue();
414                     }
415                     if (vpnName == null) {
416                         continue;
417                     }
418                     Optional<SubnetOpDataEntry> optionalSubs = SingleTransactionDataBroker.syncReadOptional(dataBroker,
419                         LogicalDatastoreType.OPERATIONAL, VpnUtil.buildSubnetOpDataEntryInstanceIdentifier(subnetId));
420                     if (!optionalSubs.isPresent()) {
421                         continue;
422                     }
423                     SubnetOpDataEntry subOpEntry = optionalSubs.get();
424                     if (subOpEntry.getNhDpnId() != null) {
425                         LOG.trace("{} getTargetDpnForPacketOut: Viewing Subnet {}", LOGGING_PREFIX,
426                             subnetId.getValue());
427                         IpPrefix cidr = IpPrefixBuilder.getDefaultInstance(subOpEntry.getSubnetCidr());
428                         boolean match = NWUtil.isIpAddressInRange(IpAddressBuilder.getDefaultInstance(ipAddress), cidr);
429                         LOG.trace("{} getTargetDpnForPacketOut: Viewing Subnet {} matching {}", LOGGING_PREFIX,
430                             subnetId.getValue(), match);
431                         if (match) {
432                             return subOpEntry;
433                         }
434                     }
435                 }
436             }
437         } catch (ReadFailedException e) {
438             LOG.error("{} getTargetDpnForPacketOut: Failed to read data store for elan {}", LOGGING_PREFIX,
439                     elanInfo.getName());
440         }
441         return null;
442     }
443
444     public boolean isTunnel(String interfaceName) {
445         return interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName).augmentation(IfTunnel.class) != null;
446     }
447 }