2 * Copyright (c) 2015 - 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.vpnmanager;
10 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
14 import com.google.common.base.Optional;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import java.math.BigInteger;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.concurrent.Callable;
25 import java.util.concurrent.locks.ReentrantLock;
26 import javax.annotation.PostConstruct;
27 import javax.inject.Inject;
28 import javax.inject.Singleton;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
33 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
34 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
35 import org.opendaylight.genius.infra.Datastore.Configuration;
36 import org.opendaylight.genius.infra.Datastore.Operational;
37 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
39 import org.opendaylight.genius.infra.TypedWriteTransaction;
40 import org.opendaylight.genius.mdsalutil.FlowEntity;
41 import org.opendaylight.genius.mdsalutil.InstructionInfo;
42 import org.opendaylight.genius.mdsalutil.MDSALUtil;
43 import org.opendaylight.genius.mdsalutil.MatchInfo;
44 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
45 import org.opendaylight.genius.mdsalutil.NWUtil;
46 import org.opendaylight.genius.mdsalutil.NwConstants;
47 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
48 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
49 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
50 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
51 import org.opendaylight.genius.utils.JvmGlobalLocks;
52 import org.opendaylight.genius.utils.SystemPropertyReader;
53 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
54 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
55 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
56 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
57 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
58 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
59 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
60 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnTargetsBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetKey;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
77 public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInstance, VpnInstanceListener> {
78 private static final Logger LOG = LoggerFactory.getLogger(VpnInstanceListener.class);
79 private static final String LOGGING_PREFIX_ADD = "VPN-ADD:";
80 private static final String LOGGING_PREFIX_DELETE = "VPN-REMOVE:";
81 private final DataBroker dataBroker;
82 private final ManagedNewTransactionRunner txRunner;
83 private final IdManagerService idManager;
84 private final VpnInterfaceManager vpnInterfaceManager;
85 private final IFibManager fibManager;
86 private final VpnOpDataSyncer vpnOpDataNotifier;
87 private final IMdsalApiManager mdsalManager;
88 private final JobCoordinator jobCoordinator;
89 private final VpnUtil vpnUtil;
92 public VpnInstanceListener(final DataBroker dataBroker, final IdManagerService idManager,
93 final VpnInterfaceManager vpnInterfaceManager, final IFibManager fibManager,
94 final VpnOpDataSyncer vpnOpDataSyncer, final IMdsalApiManager mdsalManager,
95 final JobCoordinator jobCoordinator, VpnUtil vpnUtil) {
96 super(VpnInstance.class, VpnInstanceListener.class);
97 this.dataBroker = dataBroker;
98 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
99 this.idManager = idManager;
100 this.vpnInterfaceManager = vpnInterfaceManager;
101 this.fibManager = fibManager;
102 this.vpnOpDataNotifier = vpnOpDataSyncer;
103 this.mdsalManager = mdsalManager;
104 this.jobCoordinator = jobCoordinator;
105 this.vpnUtil = vpnUtil;
109 public void start() {
110 LOG.info("{} start", getClass().getSimpleName());
111 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
115 protected InstanceIdentifier<VpnInstance> getWildCardPath() {
116 return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
120 protected VpnInstanceListener getDataTreeChangeListener() {
121 return VpnInstanceListener.this;
125 protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
126 LOG.trace("{} remove: VPN event key: {}, value: {}", LOGGING_PREFIX_DELETE, identifier, del);
127 final String vpnName = del.getVpnInstanceName();
128 Optional<VpnInstanceOpDataEntry> vpnOpValue;
129 String primaryRd = VpnUtil.getPrimaryRd(del);
131 //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
133 vpnOpValue = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
134 VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd));
135 } catch (ReadFailedException e) {
136 LOG.error("{} remove: Exception when attempting to retrieve VpnInstanceOpDataEntry for VPN {}. ",
137 LOGGING_PREFIX_DELETE, vpnName, e);
141 if (!vpnOpValue.isPresent()) {
142 LOG.error("{} remove: Unable to retrieve VpnInstanceOpDataEntry for VPN {}. ", LOGGING_PREFIX_DELETE,
146 jobCoordinator.enqueueJob("VPN-" + vpnName, () ->
147 Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
148 VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder().setVrfId(primaryRd)
149 .setVpnState(VpnInstanceOpDataEntry.VpnState.PendingDelete);
150 InstanceIdentifier<VpnInstanceOpDataEntry> id =
151 VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd);
152 tx.merge(id, builder.build());
154 LOG.info("{} call: Operational status set to PENDING_DELETE for vpn {} with rd {}",
155 LOGGING_PREFIX_DELETE, vpnName, primaryRd);
156 })), SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
161 protected void update(InstanceIdentifier<VpnInstance> identifier,
162 VpnInstance original, VpnInstance update) {
163 LOG.trace("VPN-UPDATE: update: VPN event key: {}, value: {}.", identifier, update);
164 String vpnName = update.getVpnInstanceName();
165 if (original.getIpv4Family() != null && update.getIpv4Family() != null
166 && original.getIpv4Family().getRouteDistinguisher() != null
167 && update.getIpv4Family().getRouteDistinguisher() != null
168 && original.getIpv4Family().getRouteDistinguisher().size()
169 != update.getIpv4Family().getRouteDistinguisher().size()) {
170 LOG.debug("VPN-UPDATE: VpnInstance:{} updated with new RDs: {} from old RDs: {}", vpnName,
171 update.getIpv4Family().getRouteDistinguisher(), original.getIpv4Family().getRouteDistinguisher());
172 vpnUtil.updateVpnInstanceWithRdList(vpnName, update.getIpv4Family().getRouteDistinguisher());
174 vpnInterfaceManager.updateVpnInterfacesForUnProcessAdjancencies(vpnName);
178 protected void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
179 LOG.trace("{} add: Add VPN event key: {}, value: {}", LOGGING_PREFIX_ADD, identifier, value);
180 final String vpnName = value.getVpnInstanceName();
181 jobCoordinator.enqueueJob("VPN-" + vpnName, new AddVpnInstanceWorker(dataBroker, value),
182 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
185 private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
186 private final Logger log = LoggerFactory.getLogger(AddVpnInstanceWorker.class);
187 VpnInstance vpnInstance;
190 AddVpnInstanceWorker(DataBroker broker,
192 this.broker = broker;
193 this.vpnInstance = value;
197 public List<ListenableFuture<Void>> call() {
198 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
199 // to call the respective helpers.
200 List<ListenableFuture<Void>> futures = new ArrayList<>(2);
201 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
202 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx ->
203 addVpnInstance(vpnInstance, confTx, operTx));
204 ListenableFutures.addErrorLogging(future, LOG, "{} call: error creating VPN {}", LOGGING_PREFIX_ADD,
205 vpnInstance.getVpnInstanceName());
208 Futures.addCallback(Futures.allAsList(futures),
209 new PostAddVpnInstanceWorker(vpnInstance , vpnInstance.getVpnInstanceName()),
210 MoreExecutors.directExecutor());
215 // TODO Clean up the exception handling
216 @SuppressWarnings("checkstyle:IllegalCatch")
217 private void addVpnInstance(VpnInstance value, TypedWriteTransaction<Configuration> writeConfigTxn,
218 TypedWriteTransaction<Operational> writeOperTxn) {
219 if (writeConfigTxn == null) {
220 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx ->
221 addVpnInstance(value, tx, writeOperTxn)), LOG, "Error adding VPN instance {}", value);
224 if (writeOperTxn == null) {
225 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx ->
226 addVpnInstance(value, writeConfigTxn, tx)), LOG, "Error adding VPN instance {}", value);
229 VpnAfConfig config = value.getIpv4Family();
230 String vpnInstanceName = value.getVpnInstanceName();
232 long vpnId = vpnUtil.getUniqueId(VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
234 LOG.error("{} addVpnInstance: Unable to fetch label from Id Manager. Bailing out of adding operational"
235 + " data for Vpn Instance {}", LOGGING_PREFIX_ADD, value.getVpnInstanceName());
238 LOG.info("{} addVpnInstance: VPN Id {} generated for VpnInstanceName {}", LOGGING_PREFIX_ADD, vpnId,
240 String primaryRd = VpnUtil.getPrimaryRd(value);
241 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
242 vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, primaryRd);
244 writeConfigTxn.put(VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
245 vpnInstanceToVpnId, CREATE_MISSING_PARENTS);
247 VpnIds vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
248 primaryRd, VpnUtil.isBgpVpn(vpnInstanceName, primaryRd));
250 writeConfigTxn.put(VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId), vpnIdToVpnInstance, CREATE_MISSING_PARENTS);
253 String cachedTransType = fibManager.getConfTransType();
254 if (cachedTransType.equals("Invalid")) {
256 fibManager.setConfTransType("L3VPN", "VXLAN");
257 } catch (Exception e) {
258 LOG.error("{} addVpnInstance: Exception caught setting the L3VPN tunnel transportType for vpn {}",
259 LOGGING_PREFIX_ADD, vpnInstanceName, e);
262 LOG.debug("{} addVpnInstance: Configured tunnel transport type for L3VPN {} as {}", LOGGING_PREFIX_ADD,
263 vpnInstanceName, cachedTransType);
265 } catch (Exception e) {
266 LOG.error("{} addVpnInstance: Error when trying to retrieve tunnel transport type for L3VPN {}",
267 LOGGING_PREFIX_ADD, vpnInstanceName, e);
270 VpnInstanceOpDataEntryBuilder builder =
271 new VpnInstanceOpDataEntryBuilder().setVrfId(primaryRd).setVpnId(vpnId)
272 .setVpnInstanceName(vpnInstanceName)
273 .setVpnState(VpnInstanceOpDataEntry.VpnState.Created)
274 .setIpv4Configured(false).setIpv6Configured(false);
275 if (VpnUtil.isBgpVpn(vpnInstanceName, primaryRd)) {
276 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
277 .instance.op.data.entry.vpntargets.VpnTarget> opVpnTargetList = new ArrayList<>();
278 builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal);
279 if (value.getL3vni() != null) {
280 builder.setL3vni(value.getL3vni());
282 if (value.getType() == VpnInstance.Type.L2) {
283 builder.setType(VpnInstanceOpDataEntry.Type.L2);
285 VpnTargets vpnTargets = config.getVpnTargets();
286 if (vpnTargets != null) {
287 List<VpnTarget> vpnTargetList = vpnTargets.getVpnTarget();
288 if (vpnTargetList != null) {
289 for (VpnTarget vpnTarget : vpnTargetList) {
290 VpnTargetBuilder vpnTargetBuilder =
291 new VpnTargetBuilder().withKey(new VpnTargetKey(vpnTarget.key().getVrfRTValue()))
292 .setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
293 .instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget.VrfRTType
294 .forValue(vpnTarget.getVrfRTType().getIntValue())).setVrfRTValue(
295 vpnTarget.getVrfRTValue());
296 opVpnTargetList.add(vpnTargetBuilder.build());
300 VpnTargetsBuilder vpnTargetsBuilder = new VpnTargetsBuilder().setVpnTarget(opVpnTargetList);
301 builder.setVpnTargets(vpnTargetsBuilder.build());
303 List<String> rds = config.getRouteDistinguisher();
306 builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.VPN);
308 writeOperTxn.merge(VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd), builder.build(), CREATE_MISSING_PARENTS);
309 LOG.info("{} addVpnInstance: VpnInstanceOpData populated successfully for vpn {} rd {}", LOGGING_PREFIX_ADD,
310 vpnInstanceName, primaryRd);
313 private class PostAddVpnInstanceWorker implements FutureCallback<List<Void>> {
314 private final Logger log = LoggerFactory.getLogger(PostAddVpnInstanceWorker.class);
315 VpnInstance vpnInstance;
318 PostAddVpnInstanceWorker(VpnInstance vpnInstance, String vpnName) {
319 this.vpnInstance = vpnInstance;
320 this.vpnName = vpnName;
324 * This implies that all the future instances have returned success. -- TODO: Confirm this
327 public void onSuccess(List<Void> voids) {
329 if rd is null, then its either a router vpn instance (or) a vlan external network vpn instance.
330 if rd is non-null, then it is a bgpvpn instance
332 VpnAfConfig config = vpnInstance.getIpv4Family();
333 List<String> rd = config.getRouteDistinguisher();
334 if (rd == null || addBgpVrf()) {
336 vpnInterfaceManager.vpnInstanceIsReady(vpnName);
338 log.info("{} onSuccess: Vpn Instance Op Data addition for {} successful.", LOGGING_PREFIX_ADD, vpnName);
339 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(
340 VpnUtil.getPrimaryRd(vpnInstance));
342 // bind service on each tunnel interface
343 //TODO (KIRAN): Add a new listener to handle creation of new DC-GW binding and deletion of existing DC-GW.
344 if (VpnUtil.isL3VpnOverVxLan(vpnInstance.getL3vni())) { //Handled for L3VPN Over VxLAN
345 for (String tunnelInterfaceName: getDcGatewayTunnelInterfaceNameList()) {
346 vpnUtil.bindService(vpnInstance.getVpnInstanceName(), tunnelInterfaceName,
347 true/*isTunnelInterface*/);
351 List<MatchInfo> mkMatches = new ArrayList<>();
352 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(vpnInstance.getL3vni())));
354 List<InstructionInfo> instructions =
355 Arrays.asList(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnInstanceOpDataEntry
356 .getVpnId()), MetaDataUtil.METADATA_MASK_VRFID),
357 new InstructionGotoTable(NwConstants.L3_GW_MAC_TABLE));
359 for (BigInteger dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
360 String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
361 vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
362 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
363 NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef, VpnConstants.DEFAULT_FLOW_PRIORITY,
364 "VxLAN VPN Tunnel Bind Service", 0, 0, NwConstants.COOKIE_VM_FIB_TABLE,
365 mkMatches, instructions);
366 mdsalManager.installFlow(dpnId, flowEntity);
369 ///////////////////////
373 // TODO Clean up the exception handling
374 @SuppressWarnings("checkstyle:IllegalCatch")
375 private boolean addBgpVrf() {
376 VpnAfConfig config = vpnInstance.getIpv4Family();
377 String primaryRd = vpnUtil.getPrimaryRd(vpnName);
378 List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
380 if (vpnTargetList == null) {
381 log.error("{} addBgpVrf: vpn target list is empty for vpn {} RD {}", LOGGING_PREFIX_ADD,
382 this.vpnName, primaryRd);
385 // FIXME: separate out to somehow?
386 final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
389 fibManager.addVrfTable(primaryRd, null);
393 vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, primaryRd);
397 private void notifyTask() {
398 vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName);
399 vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnOpData, vpnName);
403 * This method is used to handle failure callbacks.
404 * If more retry needed, the retrycount is decremented and mainworker is executed again.
405 * After retries completed, rollbackworker is executed.
406 * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
410 public void onFailure(Throwable throwable) {
411 log.error("{} onFailure: Job for vpnInstance: {} failed with exception:", LOGGING_PREFIX_ADD, vpnName,
413 vpnInterfaceManager.vpnInstanceFailed(vpnName);
418 protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
419 InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
421 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
423 } catch (ReadFailedException e) {
424 throw new RuntimeException("Error reading VPN instance data for " + rd, e);
428 private List<String> getDcGatewayTunnelInterfaceNameList() {
429 List<String> tunnelInterfaceNameList = new ArrayList<>();
431 InstanceIdentifier<DcGatewayIpList> dcGatewayIpListInstanceIdentifier = InstanceIdentifier
432 .create(DcGatewayIpList.class);
433 Optional<DcGatewayIpList> dcGatewayIpListOptional = SingleTransactionDataBroker.syncReadOptional(
434 dataBroker, LogicalDatastoreType.CONFIGURATION, dcGatewayIpListInstanceIdentifier);
435 if (!dcGatewayIpListOptional.isPresent()) {
436 LOG.info("No DC gateways configured.");
437 return tunnelInterfaceNameList;
439 List<DcGatewayIp> dcGatewayIps = dcGatewayIpListOptional.get().nonnullDcGatewayIp();
440 InstanceIdentifier<ExternalTunnelList> externalTunnelListId = InstanceIdentifier
441 .create(ExternalTunnelList.class);
442 Optional<ExternalTunnelList> externalTunnelListOptional = SingleTransactionDataBroker.syncReadOptional(
443 dataBroker, LogicalDatastoreType.OPERATIONAL, externalTunnelListId);
444 if (externalTunnelListOptional.isPresent()) {
445 List<ExternalTunnel> externalTunnels = externalTunnelListOptional.get().nonnullExternalTunnel();
446 List<String> externalTunnelIpList = new ArrayList<>();
447 for (ExternalTunnel externalTunnel: externalTunnels) {
448 externalTunnelIpList.add(externalTunnel.getDestinationDevice());
450 List<String> dcGatewayIpList = new ArrayList<>();
451 for (DcGatewayIp dcGatewayIp: dcGatewayIps) {
452 dcGatewayIpList.add(dcGatewayIp.getIpAddress().getIpv4Address().toString());
454 // Find all externalTunnelIps present in dcGateWayIpList
455 List<String> externalTunnelIpsInDcGatewayIpList = new ArrayList<>();
456 for (String externalTunnelIp: externalTunnelIpList) {
457 for (String dcGateWayIp: dcGatewayIpList) {
458 if (externalTunnelIp.contentEquals(dcGateWayIp)) {
459 externalTunnelIpsInDcGatewayIpList.add(externalTunnelIp);
463 for (String externalTunnelIpsInDcGatewayIp: externalTunnelIpsInDcGatewayIpList) {
464 for (ExternalTunnel externalTunnel: externalTunnels) {
465 if (externalTunnel.getDestinationDevice().contentEquals(externalTunnelIpsInDcGatewayIp)) {
466 tunnelInterfaceNameList.add(externalTunnel.getTunnelInterfaceName());
472 } catch (ReadFailedException e) {
473 LOG.error("getDcGatewayTunnelInterfaceNameList: Failed to read data store");
475 return tunnelInterfaceNameList;
478 private String getFibFlowRef(BigInteger dpnId, short tableId, String vpnName, int priority) {
479 return VpnConstants.FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
480 + NwConstants.FLOWID_SEPARATOR + vpnName + NwConstants.FLOWID_SEPARATOR + priority;