Drop unused exceptions in vpnmanager
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnInstanceListener.java
1 /*
2  * Copyright (c) 2015 - 2017 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.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.ExecutionException;
22 import javax.annotation.PostConstruct;
23 import javax.inject.Inject;
24 import javax.inject.Singleton;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
29 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
30 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
31 import org.opendaylight.genius.mdsalutil.FlowEntity;
32 import org.opendaylight.genius.mdsalutil.InstructionInfo;
33 import org.opendaylight.genius.mdsalutil.MDSALUtil;
34 import org.opendaylight.genius.mdsalutil.MatchInfo;
35 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
36 import org.opendaylight.genius.mdsalutil.NWUtil;
37 import org.opendaylight.genius.mdsalutil.NwConstants;
38 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
39 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
40 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
41 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
42 import org.opendaylight.genius.utils.SystemPropertyReader;
43 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
44 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
46 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
48 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
49 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnTargetsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetKey;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @Singleton
66 public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInstance, VpnInstanceListener> {
67     private static final Logger LOG = LoggerFactory.getLogger(VpnInstanceListener.class);
68     private static final String LOGGING_PREFIX_ADD = "VPN-ADD:";
69     private static final String LOGGING_PREFIX_DELETE = "VPN-REMOVE:";
70     private final DataBroker dataBroker;
71     private final IdManagerService idManager;
72     private final VpnInterfaceManager vpnInterfaceManager;
73     private final IFibManager fibManager;
74     private final VpnOpDataSyncer vpnOpDataNotifier;
75     private final IMdsalApiManager mdsalManager;
76     private final JobCoordinator jobCoordinator;
77
78     @Inject
79     public VpnInstanceListener(final DataBroker dataBroker, final IdManagerService idManager,
80             final VpnInterfaceManager vpnInterfaceManager, final IFibManager fibManager,
81             final VpnOpDataSyncer vpnOpDataSyncer, final IMdsalApiManager mdsalManager,
82             final JobCoordinator jobCoordinator) {
83         super(VpnInstance.class, VpnInstanceListener.class);
84         this.dataBroker = dataBroker;
85         this.idManager = idManager;
86         this.vpnInterfaceManager = vpnInterfaceManager;
87         this.fibManager = fibManager;
88         this.vpnOpDataNotifier = vpnOpDataSyncer;
89         this.mdsalManager = mdsalManager;
90         this.jobCoordinator = jobCoordinator;
91     }
92
93     @PostConstruct
94     public void start() {
95         LOG.info("{} start", getClass().getSimpleName());
96         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
97     }
98
99     @Override
100     protected InstanceIdentifier<VpnInstance> getWildCardPath() {
101         return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
102     }
103
104     @Override
105     protected VpnInstanceListener getDataTreeChangeListener() {
106         return VpnInstanceListener.this;
107     }
108
109     @Override
110     protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
111         LOG.trace("{} remove: VPN event key: {}, value: {}", LOGGING_PREFIX_DELETE, identifier, del);
112         final String vpnName = del.getVpnInstanceName();
113         Optional<VpnInstanceOpDataEntry> vpnOpValue;
114         String primaryRd = VpnUtil.getPrimaryRd(del);
115
116         //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
117         try {
118             vpnOpValue = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
119                     VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd));
120         } catch (ReadFailedException e) {
121             LOG.error("{} remove: Exception when attempting to retrieve VpnInstanceOpDataEntry for VPN {}. ",
122                     LOGGING_PREFIX_DELETE,  vpnName, e);
123             return;
124         }
125
126         if (!vpnOpValue.isPresent()) {
127             LOG.error("{} remove: Unable to retrieve VpnInstanceOpDataEntry for VPN {}. ", LOGGING_PREFIX_DELETE,
128                     vpnName);
129             return;
130         } else {
131             jobCoordinator.enqueueJob("VPN-" + vpnName, () -> {
132                 VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder().setVrfId(primaryRd)
133                         .setVpnState(VpnInstanceOpDataEntry.VpnState.PendingDelete);
134                 InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd);
135                 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
136                 writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build());
137
138                 LOG.info("{} call: Operational status set to PENDING_DELETE for vpn {} with rd {}",
139                         LOGGING_PREFIX_DELETE, vpnName, primaryRd);
140                 return Collections.singletonList(writeTxn.submit());
141             }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
142         }
143     }
144
145     @Override
146     protected void update(InstanceIdentifier<VpnInstance> identifier,
147         VpnInstance original, VpnInstance update) {
148         LOG.trace("VPN-UPDATE: update: VPN event key: {}, value: {}. Ignoring", identifier, update);
149         String vpnName = update.getVpnInstanceName();
150         vpnInterfaceManager.updateVpnInterfacesForUnProcessAdjancencies(vpnName);
151     }
152
153     @Override
154     protected void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
155         LOG.trace("{} add: Add VPN event key: {}, value: {}", LOGGING_PREFIX_ADD, identifier, value);
156         final String vpnName = value.getVpnInstanceName();
157         jobCoordinator.enqueueJob("VPN-" + vpnName, new AddVpnInstanceWorker(idManager, dataBroker, value),
158                 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
159     }
160
161     private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
162         private final Logger log = LoggerFactory.getLogger(AddVpnInstanceWorker.class);
163         IdManagerService idManager;
164         VpnInstance vpnInstance;
165         DataBroker broker;
166
167         AddVpnInstanceWorker(IdManagerService idManager,
168             DataBroker broker,
169             VpnInstance value) {
170             this.idManager = idManager;
171             this.broker = broker;
172             this.vpnInstance = value;
173         }
174
175         @Override
176         public List<ListenableFuture<Void>> call() {
177             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
178             // to call the respective helpers.
179             WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
180             WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
181             addVpnInstance(vpnInstance, writeConfigTxn, writeOperTxn);
182             try {
183                 writeOperTxn.submit().get();
184             } catch (InterruptedException | ExecutionException e) {
185                 log.error("{} call: Error creating vpn {} ", LOGGING_PREFIX_ADD, vpnInstance.getVpnInstanceName());
186                 throw new RuntimeException(e.getMessage(), e);
187             }
188             List<ListenableFuture<Void>> futures = new ArrayList<>();
189             futures.add(writeConfigTxn.submit());
190             ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
191             Futures.addCallback(listenableFuture,
192                                 new PostAddVpnInstanceWorker(vpnInstance , vpnInstance.getVpnInstanceName()),
193                                 MoreExecutors.directExecutor());
194             return futures;
195         }
196     }
197
198     // TODO Clean up the exception handling
199     @SuppressWarnings("checkstyle:IllegalCatch")
200     private void addVpnInstance(VpnInstance value, WriteTransaction writeConfigTxn,
201         WriteTransaction writeOperTxn) {
202         VpnAfConfig config = value.getIpv4Family();
203         String vpnInstanceName = value.getVpnInstanceName();
204
205         long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
206         if (vpnId == 0) {
207             LOG.error("{} addVpnInstance: Unable to fetch label from Id Manager. Bailing out of adding operational"
208                     + " data for Vpn Instance {}", LOGGING_PREFIX_ADD, value.getVpnInstanceName());
209             return;
210         }
211         LOG.info("{} addVpnInstance: VPN Id {} generated for VpnInstanceName {}", LOGGING_PREFIX_ADD, vpnId,
212                 vpnInstanceName);
213         String primaryRd = VpnUtil.getPrimaryRd(value);
214         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
215             vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, primaryRd);
216
217         if (writeConfigTxn != null) {
218             writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
219                 VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
220                 vpnInstanceToVpnId, WriteTransaction.CREATE_MISSING_PARENTS);
221         } else {
222             TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
223                 VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
224                 vpnInstanceToVpnId, TransactionUtil.DEFAULT_CALLBACK);
225         }
226
227         VpnIds vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
228             primaryRd, VpnUtil.isBgpVpn(vpnInstanceName, primaryRd));
229
230         if (writeConfigTxn != null) {
231             writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
232                 VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
233                 vpnIdToVpnInstance, WriteTransaction.CREATE_MISSING_PARENTS);
234         } else {
235             TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
236                 VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
237                 vpnIdToVpnInstance, TransactionUtil.DEFAULT_CALLBACK);
238         }
239
240         try {
241             String cachedTransType = fibManager.getConfTransType();
242             if (cachedTransType.equals("Invalid")) {
243                 try {
244                     fibManager.setConfTransType("L3VPN", "VXLAN");
245                 } catch (Exception e) {
246                     LOG.error("{} addVpnInstance: Exception caught setting the L3VPN tunnel transportType for vpn {}",
247                             LOGGING_PREFIX_ADD, vpnInstanceName, e);
248                 }
249             } else {
250                 LOG.debug("{} addVpnInstance: Configured tunnel transport type for L3VPN {} as {}", LOGGING_PREFIX_ADD,
251                         vpnInstanceName, cachedTransType);
252             }
253         } catch (Exception e) {
254             LOG.error("{} addVpnInstance: Error when trying to retrieve tunnel transport type for L3VPN {}",
255                     LOGGING_PREFIX_ADD, vpnInstanceName, e);
256         }
257
258         VpnInstanceOpDataEntryBuilder builder =
259                 new VpnInstanceOpDataEntryBuilder().setVrfId(primaryRd).setVpnId(vpnId)
260                         .setVpnInstanceName(vpnInstanceName)
261                         .setVpnState(VpnInstanceOpDataEntry.VpnState.Created)
262                         .setIpv4Configured(false).setIpv6Configured(false);
263         if (VpnUtil.isBgpVpn(vpnInstanceName, primaryRd)) {
264             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
265                 .instance.op.data.entry.vpntargets.VpnTarget> opVpnTargetList = new ArrayList<>();
266             builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal);
267             if (value.getL3vni() != null) {
268                 builder.setL3vni(value.getL3vni());
269             }
270             if (value.getType() == VpnInstance.Type.L2) {
271                 builder.setType(VpnInstanceOpDataEntry.Type.L2);
272             }
273             VpnTargets vpnTargets = config.getVpnTargets();
274             if (vpnTargets != null) {
275                 List<VpnTarget> vpnTargetList = vpnTargets.getVpnTarget();
276                 if (vpnTargetList != null) {
277                     for (VpnTarget vpnTarget : vpnTargetList) {
278                         VpnTargetBuilder vpnTargetBuilder =
279                             new VpnTargetBuilder().setKey(new VpnTargetKey(vpnTarget.getKey().getVrfRTValue()))
280                                 .setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
281                                     .instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget.VrfRTType
282                                     .forValue(vpnTarget.getVrfRTType().getIntValue())).setVrfRTValue(
283                                 vpnTarget.getVrfRTValue());
284                         opVpnTargetList.add(vpnTargetBuilder.build());
285                     }
286                 }
287             }
288             VpnTargetsBuilder vpnTargetsBuilder = new VpnTargetsBuilder().setVpnTarget(opVpnTargetList);
289             builder.setVpnTargets(vpnTargetsBuilder.build());
290
291             List<String> rds = config.getRouteDistinguisher();
292             builder.setRd(rds);
293         } else {
294             builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.VPN);
295         }
296         if (writeOperTxn != null) {
297             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
298                 VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd),
299                 builder.build(), true);
300         } else {
301             TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
302                 VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd),
303                 builder.build(), TransactionUtil.DEFAULT_CALLBACK);
304         }
305         LOG.info("{} addVpnInstance: VpnInstanceOpData populated successfully for vpn {} rd {}", LOGGING_PREFIX_ADD,
306                 vpnInstanceName, primaryRd);
307     }
308
309     private class PostAddVpnInstanceWorker implements FutureCallback<List<Void>> {
310         private final Logger log = LoggerFactory.getLogger(PostAddVpnInstanceWorker.class);
311         VpnInstance vpnInstance;
312         String vpnName;
313
314         PostAddVpnInstanceWorker(VpnInstance vpnInstance, String vpnName) {
315             this.vpnInstance = vpnInstance;
316             this.vpnName = vpnName;
317         }
318
319         /**
320          * This implies that all the future instances have returned success. -- TODO: Confirm this
321          */
322         @Override
323         public void onSuccess(List<Void> voids) {
324             /*
325             if rd is null, then its either a router vpn instance (or) a vlan external network vpn instance.
326             if rd is non-null, then it is a bgpvpn instance
327              */
328             VpnAfConfig config = vpnInstance.getIpv4Family();
329             List<String> rd = config.getRouteDistinguisher();
330             if (rd == null || addBgpVrf(voids)) {
331                 notifyTask();
332                 vpnInterfaceManager.vpnInstanceIsReady(vpnName);
333             }
334             log.info("{} onSuccess: Vpn Instance Op Data addition for {} successful.", LOGGING_PREFIX_ADD, vpnName);
335             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker,
336                     VpnUtil.getPrimaryRd(vpnInstance));
337
338             // bind service on each tunnel interface
339             //TODO (KIRAN): Add a new listener to handle creation of new DC-GW binding and deletion of existing DC-GW.
340             if (VpnUtil.isL3VpnOverVxLan(vpnInstance.getL3vni())) { //Handled for L3VPN Over VxLAN
341                 for (String tunnelInterfaceName: getDcGatewayTunnelInterfaceNameList()) {
342                     VpnUtil.bindService(vpnInstance.getVpnInstanceName(), tunnelInterfaceName, dataBroker,
343                             true/*isTunnelInterface*/, jobCoordinator);
344                 }
345
346                 // install flow
347                 List<MatchInfo> mkMatches = new ArrayList<>();
348                 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(vpnInstance.getL3vni())));
349
350                 List<InstructionInfo> instructions =
351                         Arrays.asList(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnInstanceOpDataEntry
352                                 .getVpnId()), MetaDataUtil.METADATA_MASK_VRFID),
353                                 new InstructionGotoTable(NwConstants.L3_GW_MAC_TABLE));
354
355                 for (BigInteger dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
356                     String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
357                             vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
358                     FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
359                             NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef, VpnConstants.DEFAULT_FLOW_PRIORITY,
360                             "VxLAN VPN Tunnel Bind Service", 0, 0, NwConstants.COOKIE_VM_FIB_TABLE,
361                             mkMatches, instructions);
362                     mdsalManager.installFlow(dpnId, flowEntity);
363                 }
364
365                 ///////////////////////
366             }
367         }
368
369         // TODO Clean up the exception handling
370         @SuppressWarnings("checkstyle:IllegalCatch")
371         private boolean addBgpVrf(List<Void> voids) {
372             VpnAfConfig config = vpnInstance.getIpv4Family();
373             String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
374             List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
375
376             if (vpnTargetList == null) {
377                 log.error("{} addBgpVrf: vpn target list is empty for vpn {} RD {}", LOGGING_PREFIX_ADD,
378                         this.vpnName, primaryRd);
379                 return false;
380             }
381             vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, primaryRd);
382             return true;
383         }
384
385         private void notifyTask() {
386             vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName);
387             vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnOpData, vpnName);
388         }
389
390         /**
391          * This method is used to handle failure callbacks.
392          * If more retry needed, the retrycount is decremented and mainworker is executed again.
393          * After retries completed, rollbackworker is executed.
394          * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
395          */
396
397         @Override
398         public void onFailure(Throwable throwable) {
399             log.error("{} onFailure: Job for vpnInstance: {} failed with exception:", LOGGING_PREFIX_ADD, vpnName,
400                     throwable);
401             vpnInterfaceManager.vpnInstanceFailed(vpnName);
402         }
403     }
404
405     protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
406         InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
407         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
408             TransactionUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
409         if (vpnInstanceOpData.isPresent()) {
410             return vpnInstanceOpData.get();
411         }
412         return null;
413     }
414
415     private List<String> getDcGatewayTunnelInterfaceNameList() {
416         List<String> tunnelInterfaceNameList = new ArrayList<>();
417
418         InstanceIdentifier<DcGatewayIpList> dcGatewayIpListInstanceIdentifier = InstanceIdentifier
419                 .create(DcGatewayIpList.class);
420         Optional<DcGatewayIpList> dcGatewayIpListOptional = VpnUtil.read(dataBroker,
421                 LogicalDatastoreType.CONFIGURATION, dcGatewayIpListInstanceIdentifier);
422         if (!dcGatewayIpListOptional.isPresent()) {
423             LOG.info("No DC gateways configured.");
424             return tunnelInterfaceNameList;
425         }
426         List<DcGatewayIp> dcGatewayIps = dcGatewayIpListOptional.get().getDcGatewayIp();
427
428         InstanceIdentifier<ExternalTunnelList> externalTunnelListId = InstanceIdentifier
429                 .create(ExternalTunnelList.class);
430
431         Optional<ExternalTunnelList> externalTunnelListOptional = VpnUtil.read(dataBroker,
432                 LogicalDatastoreType.OPERATIONAL, externalTunnelListId);
433         if (externalTunnelListOptional.isPresent()) {
434             List<ExternalTunnel> externalTunnels = externalTunnelListOptional.get().getExternalTunnel();
435
436             List<String> externalTunnelIpList = new ArrayList<>();
437             for (ExternalTunnel externalTunnel: externalTunnels) {
438                 externalTunnelIpList.add(externalTunnel.getDestinationDevice());
439             }
440
441             List<String> dcGatewayIpList = new ArrayList<>();
442             for (DcGatewayIp dcGatewayIp: dcGatewayIps) {
443                 dcGatewayIpList.add(dcGatewayIp.getIpAddress().getIpv4Address().toString());
444             }
445
446             // Find all externalTunnelIps present in dcGateWayIpList
447             List<String> externalTunnelIpsInDcGatewayIpList = new ArrayList<>();
448             for (String externalTunnelIp: externalTunnelIpList) {
449                 for (String dcGateWayIp: dcGatewayIpList) {
450                     if (externalTunnelIp.contentEquals(dcGateWayIp)) {
451                         externalTunnelIpsInDcGatewayIpList.add(externalTunnelIp);
452                     }
453                 }
454             }
455
456
457             for (String externalTunnelIpsInDcGatewayIp: externalTunnelIpsInDcGatewayIpList) {
458                 for (ExternalTunnel externalTunnel: externalTunnels) {
459                     if (externalTunnel.getDestinationDevice().contentEquals(externalTunnelIpsInDcGatewayIp)) {
460                         tunnelInterfaceNameList.add(externalTunnel.getTunnelInterfaceName());
461                     }
462                 }
463             }
464
465         }
466         return tunnelInterfaceNameList;
467     }
468
469     private String getFibFlowRef(BigInteger dpnId, short tableId, String vpnName, int priority) {
470         return VpnConstants.FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
471                 + NwConstants.FLOWID_SEPARATOR + vpnName + NwConstants.FLOWID_SEPARATOR + priority;
472     }
473 }