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 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;
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;
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;
95 LOG.info("{} start", getClass().getSimpleName());
96 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
100 protected InstanceIdentifier<VpnInstance> getWildCardPath() {
101 return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
105 protected VpnInstanceListener getDataTreeChangeListener() {
106 return VpnInstanceListener.this;
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);
116 //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
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);
126 if (!vpnOpValue.isPresent()) {
127 LOG.error("{} remove: Unable to retrieve VpnInstanceOpDataEntry for VPN {}. ", LOGGING_PREFIX_DELETE,
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());
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());
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);
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(dataBroker, value),
158 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
161 private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
162 private final Logger log = LoggerFactory.getLogger(AddVpnInstanceWorker.class);
163 VpnInstance vpnInstance;
166 AddVpnInstanceWorker(DataBroker broker,
168 this.broker = broker;
169 this.vpnInstance = value;
173 public List<ListenableFuture<Void>> call() {
174 // If another renderer(for eg : CSS) needs to be supported, check can be performed here
175 // to call the respective helpers.
176 WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
177 WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
178 addVpnInstance(vpnInstance, writeConfigTxn, writeOperTxn);
180 writeOperTxn.submit().get();
181 } catch (InterruptedException | ExecutionException e) {
182 log.error("{} call: Error creating vpn {} ", LOGGING_PREFIX_ADD, vpnInstance.getVpnInstanceName());
183 throw new RuntimeException(e.getMessage(), e);
185 List<ListenableFuture<Void>> futures = new ArrayList<>();
186 futures.add(writeConfigTxn.submit());
187 ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
188 Futures.addCallback(listenableFuture,
189 new PostAddVpnInstanceWorker(vpnInstance , vpnInstance.getVpnInstanceName()),
190 MoreExecutors.directExecutor());
195 // TODO Clean up the exception handling
196 @SuppressWarnings("checkstyle:IllegalCatch")
197 private void addVpnInstance(VpnInstance value, WriteTransaction writeConfigTxn,
198 WriteTransaction writeOperTxn) {
199 VpnAfConfig config = value.getIpv4Family();
200 String vpnInstanceName = value.getVpnInstanceName();
202 long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
204 LOG.error("{} addVpnInstance: Unable to fetch label from Id Manager. Bailing out of adding operational"
205 + " data for Vpn Instance {}", LOGGING_PREFIX_ADD, value.getVpnInstanceName());
208 LOG.info("{} addVpnInstance: VPN Id {} generated for VpnInstanceName {}", LOGGING_PREFIX_ADD, vpnId,
210 String primaryRd = VpnUtil.getPrimaryRd(value);
211 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
212 vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, primaryRd);
214 if (writeConfigTxn != null) {
215 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
216 VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
217 vpnInstanceToVpnId, WriteTransaction.CREATE_MISSING_PARENTS);
219 TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
220 VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
224 VpnIds vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
225 primaryRd, VpnUtil.isBgpVpn(vpnInstanceName, primaryRd));
227 if (writeConfigTxn != null) {
228 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
229 VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
230 vpnIdToVpnInstance, WriteTransaction.CREATE_MISSING_PARENTS);
232 TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
233 VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
238 String cachedTransType = fibManager.getConfTransType();
239 if (cachedTransType.equals("Invalid")) {
241 fibManager.setConfTransType("L3VPN", "VXLAN");
242 } catch (Exception e) {
243 LOG.error("{} addVpnInstance: Exception caught setting the L3VPN tunnel transportType for vpn {}",
244 LOGGING_PREFIX_ADD, vpnInstanceName, e);
247 LOG.debug("{} addVpnInstance: Configured tunnel transport type for L3VPN {} as {}", LOGGING_PREFIX_ADD,
248 vpnInstanceName, cachedTransType);
250 } catch (Exception e) {
251 LOG.error("{} addVpnInstance: Error when trying to retrieve tunnel transport type for L3VPN {}",
252 LOGGING_PREFIX_ADD, vpnInstanceName, e);
255 VpnInstanceOpDataEntryBuilder builder =
256 new VpnInstanceOpDataEntryBuilder().setVrfId(primaryRd).setVpnId(vpnId)
257 .setVpnInstanceName(vpnInstanceName)
258 .setVpnState(VpnInstanceOpDataEntry.VpnState.Created)
259 .setIpv4Configured(false).setIpv6Configured(false);
260 if (VpnUtil.isBgpVpn(vpnInstanceName, primaryRd)) {
261 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
262 .instance.op.data.entry.vpntargets.VpnTarget> opVpnTargetList = new ArrayList<>();
263 builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal);
264 if (value.getL3vni() != null) {
265 builder.setL3vni(value.getL3vni());
267 if (value.getType() == VpnInstance.Type.L2) {
268 builder.setType(VpnInstanceOpDataEntry.Type.L2);
270 VpnTargets vpnTargets = config.getVpnTargets();
271 if (vpnTargets != null) {
272 List<VpnTarget> vpnTargetList = vpnTargets.getVpnTarget();
273 if (vpnTargetList != null) {
274 for (VpnTarget vpnTarget : vpnTargetList) {
275 VpnTargetBuilder vpnTargetBuilder =
276 new VpnTargetBuilder().setKey(new VpnTargetKey(vpnTarget.getKey().getVrfRTValue()))
277 .setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
278 .instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget.VrfRTType
279 .forValue(vpnTarget.getVrfRTType().getIntValue())).setVrfRTValue(
280 vpnTarget.getVrfRTValue());
281 opVpnTargetList.add(vpnTargetBuilder.build());
285 VpnTargetsBuilder vpnTargetsBuilder = new VpnTargetsBuilder().setVpnTarget(opVpnTargetList);
286 builder.setVpnTargets(vpnTargetsBuilder.build());
288 List<String> rds = config.getRouteDistinguisher();
291 builder.setBgpvpnType(VpnInstanceOpDataEntry.BgpvpnType.VPN);
293 if (writeOperTxn != null) {
294 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
295 VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd),
296 builder.build(), true);
298 TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
299 VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd),
302 LOG.info("{} addVpnInstance: VpnInstanceOpData populated successfully for vpn {} rd {}", LOGGING_PREFIX_ADD,
303 vpnInstanceName, primaryRd);
306 private class PostAddVpnInstanceWorker implements FutureCallback<List<Void>> {
307 private final Logger log = LoggerFactory.getLogger(PostAddVpnInstanceWorker.class);
308 VpnInstance vpnInstance;
311 PostAddVpnInstanceWorker(VpnInstance vpnInstance, String vpnName) {
312 this.vpnInstance = vpnInstance;
313 this.vpnName = vpnName;
317 * This implies that all the future instances have returned success. -- TODO: Confirm this
320 public void onSuccess(List<Void> voids) {
322 if rd is null, then its either a router vpn instance (or) a vlan external network vpn instance.
323 if rd is non-null, then it is a bgpvpn instance
325 VpnAfConfig config = vpnInstance.getIpv4Family();
326 List<String> rd = config.getRouteDistinguisher();
327 if (rd == null || addBgpVrf()) {
329 vpnInterfaceManager.vpnInstanceIsReady(vpnName);
331 log.info("{} onSuccess: Vpn Instance Op Data addition for {} successful.", LOGGING_PREFIX_ADD, vpnName);
332 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker,
333 VpnUtil.getPrimaryRd(vpnInstance));
335 // bind service on each tunnel interface
336 //TODO (KIRAN): Add a new listener to handle creation of new DC-GW binding and deletion of existing DC-GW.
337 if (VpnUtil.isL3VpnOverVxLan(vpnInstance.getL3vni())) { //Handled for L3VPN Over VxLAN
338 for (String tunnelInterfaceName: getDcGatewayTunnelInterfaceNameList()) {
339 VpnUtil.bindService(vpnInstance.getVpnInstanceName(), tunnelInterfaceName, dataBroker,
340 true/*isTunnelInterface*/, jobCoordinator);
344 List<MatchInfo> mkMatches = new ArrayList<>();
345 mkMatches.add(new MatchTunnelId(BigInteger.valueOf(vpnInstance.getL3vni())));
347 List<InstructionInfo> instructions =
348 Arrays.asList(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnInstanceOpDataEntry
349 .getVpnId()), MetaDataUtil.METADATA_MASK_VRFID),
350 new InstructionGotoTable(NwConstants.L3_GW_MAC_TABLE));
352 for (BigInteger dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
353 String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
354 vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
355 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
356 NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef, VpnConstants.DEFAULT_FLOW_PRIORITY,
357 "VxLAN VPN Tunnel Bind Service", 0, 0, NwConstants.COOKIE_VM_FIB_TABLE,
358 mkMatches, instructions);
359 mdsalManager.installFlow(dpnId, flowEntity);
362 ///////////////////////
366 // TODO Clean up the exception handling
367 @SuppressWarnings("checkstyle:IllegalCatch")
368 private boolean addBgpVrf() {
369 VpnAfConfig config = vpnInstance.getIpv4Family();
370 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
371 List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
373 if (vpnTargetList == null) {
374 log.error("{} addBgpVrf: vpn target list is empty for vpn {} RD {}", LOGGING_PREFIX_ADD,
375 this.vpnName, primaryRd);
378 vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, primaryRd);
382 private void notifyTask() {
383 vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnInstanceToId, vpnName);
384 vpnOpDataNotifier.notifyVpnOpDataReady(VpnOpDataSyncer.VpnOpDataType.vpnOpData, vpnName);
388 * This method is used to handle failure callbacks.
389 * If more retry needed, the retrycount is decremented and mainworker is executed again.
390 * After retries completed, rollbackworker is executed.
391 * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
395 public void onFailure(Throwable throwable) {
396 log.error("{} onFailure: Job for vpnInstance: {} failed with exception:", LOGGING_PREFIX_ADD, vpnName,
398 vpnInterfaceManager.vpnInstanceFailed(vpnName);
402 protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
403 InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
404 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
405 TransactionUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
406 if (vpnInstanceOpData.isPresent()) {
407 return vpnInstanceOpData.get();
412 private List<String> getDcGatewayTunnelInterfaceNameList() {
413 List<String> tunnelInterfaceNameList = new ArrayList<>();
415 InstanceIdentifier<DcGatewayIpList> dcGatewayIpListInstanceIdentifier = InstanceIdentifier
416 .create(DcGatewayIpList.class);
417 Optional<DcGatewayIpList> dcGatewayIpListOptional = VpnUtil.read(dataBroker,
418 LogicalDatastoreType.CONFIGURATION, dcGatewayIpListInstanceIdentifier);
419 if (!dcGatewayIpListOptional.isPresent()) {
420 LOG.info("No DC gateways configured.");
421 return tunnelInterfaceNameList;
423 List<DcGatewayIp> dcGatewayIps = dcGatewayIpListOptional.get().getDcGatewayIp();
425 InstanceIdentifier<ExternalTunnelList> externalTunnelListId = InstanceIdentifier
426 .create(ExternalTunnelList.class);
428 Optional<ExternalTunnelList> externalTunnelListOptional = VpnUtil.read(dataBroker,
429 LogicalDatastoreType.OPERATIONAL, externalTunnelListId);
430 if (externalTunnelListOptional.isPresent()) {
431 List<ExternalTunnel> externalTunnels = externalTunnelListOptional.get().getExternalTunnel();
433 List<String> externalTunnelIpList = new ArrayList<>();
434 for (ExternalTunnel externalTunnel: externalTunnels) {
435 externalTunnelIpList.add(externalTunnel.getDestinationDevice());
438 List<String> dcGatewayIpList = new ArrayList<>();
439 for (DcGatewayIp dcGatewayIp: dcGatewayIps) {
440 dcGatewayIpList.add(dcGatewayIp.getIpAddress().getIpv4Address().toString());
443 // Find all externalTunnelIps present in dcGateWayIpList
444 List<String> externalTunnelIpsInDcGatewayIpList = new ArrayList<>();
445 for (String externalTunnelIp: externalTunnelIpList) {
446 for (String dcGateWayIp: dcGatewayIpList) {
447 if (externalTunnelIp.contentEquals(dcGateWayIp)) {
448 externalTunnelIpsInDcGatewayIpList.add(externalTunnelIp);
454 for (String externalTunnelIpsInDcGatewayIp: externalTunnelIpsInDcGatewayIpList) {
455 for (ExternalTunnel externalTunnel: externalTunnels) {
456 if (externalTunnel.getDestinationDevice().contentEquals(externalTunnelIpsInDcGatewayIp)) {
457 tunnelInterfaceNameList.add(externalTunnel.getTunnelInterfaceName());
463 return tunnelInterfaceNameList;
466 private String getFibFlowRef(BigInteger dpnId, short tableId, String vpnName, int priority) {
467 return VpnConstants.FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
468 + NwConstants.FLOWID_SEPARATOR + vpnName + NwConstants.FLOWID_SEPARATOR + priority;