2 * Copyright (c) 2016, 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.genius.itm.confighelpers;
10 import static java.util.Collections.singletonList;
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import com.google.common.base.Optional;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.concurrent.Callable;
20 import java.util.concurrent.ExecutionException;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
24 import org.opendaylight.genius.infra.Datastore.Configuration;
25 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
26 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
27 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
28 import org.opendaylight.genius.infra.TypedWriteTransaction;
29 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
30 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
31 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
32 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
33 import org.opendaylight.genius.itm.cache.TunnelStateCache;
34 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
35 import org.opendaylight.genius.itm.impl.ItmUtils;
36 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
37 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
38 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
39 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
40 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPointsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
68 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
69 import org.opendaylight.yangtools.yang.common.OperationFailedException;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
73 public class ItmInternalTunnelDeleteWorker {
75 private static final Logger LOG = LoggerFactory.getLogger(ItmInternalTunnelDeleteWorker.class) ;
77 private final DataBroker dataBroker;
78 private final ManagedNewTransactionRunner txRunner;
79 private final JobCoordinator jobCoordinator;
80 private final TunnelMonitoringConfig tunnelMonitoringConfig;
81 private final IInterfaceManager interfaceManager;
82 private final DpnTepStateCache dpnTepStateCache;
83 private final OvsBridgeEntryCache ovsBridgeEntryCache;
84 private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
85 private final TunnelStateCache tunnelStateCache;
86 private final DirectTunnelUtils directTunnelUtils;
88 public ItmInternalTunnelDeleteWorker(DataBroker dataBroker, JobCoordinator jobCoordinator,
89 TunnelMonitoringConfig tunnelMonitoringConfig,
90 IInterfaceManager interfaceManager, DpnTepStateCache dpnTepStateCache,
91 OvsBridgeEntryCache ovsBridgeEntryCache,
92 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
93 TunnelStateCache tunnelStateCache,
94 DirectTunnelUtils directTunnelUtils) {
95 this.dataBroker = dataBroker;
96 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
97 this.jobCoordinator = jobCoordinator;
98 this.tunnelMonitoringConfig = tunnelMonitoringConfig;
99 this.interfaceManager = interfaceManager;
100 this.dpnTepStateCache = dpnTepStateCache;
101 this.ovsBridgeEntryCache = ovsBridgeEntryCache;
102 this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
103 this.tunnelStateCache = tunnelStateCache;
104 this.directTunnelUtils = directTunnelUtils;
107 @SuppressWarnings("checkstyle:IllegalCatch")
108 public List<ListenableFuture<Void>> deleteTunnels(IMdsalApiManager mdsalManager,
109 Collection<DPNTEPsInfo> dpnTepsList, Collection<DPNTEPsInfo> meshedDpnList) {
110 LOG.trace("TEPs to be deleted {} " , dpnTepsList);
111 return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
112 if (dpnTepsList == null || dpnTepsList.size() == 0) {
113 LOG.debug("no vtep to delete");
117 if (meshedDpnList == null || meshedDpnList.size() == 0) {
118 LOG.debug("No Meshed Vteps");
121 for (DPNTEPsInfo srcDpn : dpnTepsList) {
122 LOG.trace("Processing srcDpn {}", srcDpn);
124 List<TunnelEndPoints> meshedEndPtCache = ItmUtils.getTEPsForDpn(srcDpn.getDPNID(), meshedDpnList);
125 if (meshedEndPtCache == null) {
126 LOG.debug("No Tunnel End Point configured for this DPN {}", srcDpn.getDPNID());
129 LOG.debug("Entries in meshEndPointCache {} for DPN Id{} ", meshedEndPtCache.size(), srcDpn.getDPNID());
130 for (TunnelEndPoints srcTep : srcDpn.getTunnelEndPoints()) {
131 LOG.trace("Processing srcTep {}", srcTep);
132 List<TzMembership> srcTZones = srcTep.getTzMembership();
133 boolean tepDeleteFlag = false;
134 // First, take care of tunnel removal, so run through all other DPNS other than srcDpn
135 // In the tep received from Delete DCN, the membership list will always be 1
136 // as the DCN is at transport zone level
137 // Hence if a tunnel is shared across TZs, compare the original membership list between end points
138 // to decide if tunnel to be deleted.
139 for (DPNTEPsInfo dstDpn : meshedDpnList) {
140 if (!srcDpn.getDPNID().equals(dstDpn.getDPNID())) {
141 for (TunnelEndPoints dstTep : dstDpn.getTunnelEndPoints()) {
142 if (!ItmUtils.getIntersection(dstTep.getTzMembership(), srcTZones).isEmpty()) {
143 List<TzMembership> originalTzMembership =
144 ItmUtils.getOriginalTzMembership(srcTep, srcDpn.getDPNID(), meshedDpnList);
145 if (ItmUtils.getIntersection(dstTep.getTzMembership(),
146 originalTzMembership).size() == 1) {
147 if (interfaceManager.isItmDirectTunnelsEnabled()) {
148 if (checkIfTepInterfaceExists(dstDpn.getDPNID(), srcDpn.getDPNID())) {
149 // remove all trunk interfaces
150 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
151 + "Destination TEP {} " ,srcTep , dstTep);
152 removeTunnelInterfaceFromOvsdb(tx, srcTep, dstTep, srcDpn.getDPNID(),
158 if (checkIfTrunkExists(dstDpn.getDPNID(), srcDpn.getDPNID(),
159 srcTep.getTunnelType(), dataBroker)) {
160 // remove all trunk interfaces
161 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
162 + "Destination TEP {} ", srcTep, dstTep);
163 removeTrunkInterface(tx, srcTep, dstTep, srcDpn.getDPNID(),
172 for (DPNTEPsInfo dstDpn : meshedDpnList) {
173 // Second, take care of Tep TZ membership and identify if tep can be removed
174 if (srcDpn.getDPNID().equals(dstDpn.getDPNID())) {
175 // Same DPN, so remove the TZ membership
176 for (TunnelEndPoints dstTep : dstDpn.getTunnelEndPoints()) {
177 if (dstTep.getIpAddress().equals(srcTep.getIpAddress())) {
178 // Remove the deleted TZ membership from the TEP
179 LOG.debug("Removing TZ list {} from Existing TZ list {} ", srcTZones,
180 dstTep.getTzMembership());
181 List<TzMembership> updatedList =
182 ItmUtils.removeTransportZoneMembership(dstTep, srcTZones);
183 if (updatedList.isEmpty()) {
184 LOG.debug(" This TEP can be deleted {}", srcTep);
185 tepDeleteFlag = true;
187 TunnelEndPointsBuilder modifiedTepBld = new TunnelEndPointsBuilder(dstTep);
188 modifiedTepBld.setTzMembership(updatedList);
189 TunnelEndPoints modifiedTep = modifiedTepBld.build() ;
190 InstanceIdentifier<TunnelEndPoints> tepPath = InstanceIdentifier
191 .builder(DpnEndpoints.class)
192 .child(DPNTEPsInfo.class, dstDpn.key())
193 .child(TunnelEndPoints.class, dstTep.key()).build();
195 LOG.debug(" Store the modified Tep in DS {} ", modifiedTep);
196 tx.put(tepPath, modifiedTep);
203 // Third, removing vtep / dpn from Tunnels OpDs.
204 InstanceIdentifier<TunnelEndPoints> tepPath =
205 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
206 .child(TunnelEndPoints.class, srcTep.key()).build();
208 LOG.trace("Tep Removal of TEP {} from DPNTEPSINFO CONFIG DS with Key {} ", srcTep,
211 // remove the tep from the cache
212 meshedEndPtCache.remove(srcTep);
213 Class<? extends TunnelMonitoringTypeBase> monitorProtocol =
214 tunnelMonitoringConfig.getMonitorProtocol();
215 InstanceIdentifier<DPNTEPsInfo> dpnPath =
216 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
219 if (meshedEndPtCache.isEmpty()) {
220 // remove dpn if no vteps exist on dpn
221 if (monitorProtocol.isAssignableFrom(TunnelMonitoringTypeLldp.class)) {
222 LOG.debug("Removing Terminating Service Table Flow ");
223 ItmUtils.removeTerminatingServiceTable(tx, srcDpn.getDPNID(), mdsalManager);
225 LOG.trace("DPN Removal from DPNTEPSINFO CONFIG DS {}", srcDpn.getDPNID());
227 InstanceIdentifier<DpnEndpoints> tnlContainerPath =
228 InstanceIdentifier.builder(DpnEndpoints.class).build();
229 Optional<DpnEndpoints> containerOptional = tx.read(tnlContainerPath).get();
230 // remove container if no DPNs are present
231 if (containerOptional.isPresent()) {
232 DpnEndpoints deps = containerOptional.get();
233 if (deps.getDPNTEPsInfo() == null || deps.getDPNTEPsInfo().isEmpty()) {
234 LOG.trace("Container Removal from DPNTEPSINFO CONFIG DS");
235 tx.delete(tnlContainerPath);
240 if (interfaceManager.isItmDirectTunnelsEnabled()) {
241 // SF419 Remove the DPNSTEPs DS
242 LOG.debug("Deleting TEP Interface information from Config datastore with DPNs-Teps "
243 + "for source Dpn {}", srcDpn.getDPNID());
244 // Clean up the DPN TEPs State DS
245 dpnTepStateCache.removeTepFromDpnTepInterfaceConfigDS(srcDpn.getDPNID());
252 private void removeTrunkInterface(TypedWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
253 TunnelEndPoints dstTep, BigInteger srcDpnId, BigInteger dstDpnId) {
254 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
255 new String(srcTep.getIpAddress().getValue()),
256 new String(dstTep.getIpAddress().getValue()),
257 srcTep.getTunnelType().getName());
258 LOG.trace("Removing forward Trunk Interface {}" , trunkfwdIfName);
259 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkfwdIfName);
260 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
261 trunkfwdIfName, trunkIdentifier) ;
262 tx.delete(trunkIdentifier);
263 ItmUtils.ITM_CACHE.removeInterface(trunkfwdIfName);
264 // also update itm-state ds -- Delete the forward tunnel-interface from the tunnel list
265 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
266 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, srcTep.getTunnelType()));
268 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkfwdIfName);
269 // Release the Ids for the forward trunk interface Name
270 ItmUtils.releaseIdForTrunkInterfaceName(srcTep.getInterfaceName(),
271 new String(srcTep.getIpAddress().getValue()),
272 new String(dstTep.getIpAddress().getValue()),
273 srcTep.getTunnelType().getName());
274 removeLogicalGroupTunnel(srcDpnId, dstDpnId);
276 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
277 new String(dstTep.getIpAddress().getValue()),
278 new String(srcTep.getIpAddress().getValue()),
279 srcTep.getTunnelType().getName());
280 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
281 trunkIdentifier = ItmUtils.buildId(trunkRevIfName);
282 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
283 trunkRevIfName, trunkIdentifier) ;
284 tx.delete(trunkIdentifier);
285 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkRevIfName);
286 // also update itm-state ds -- Delete the reverse tunnel-interface from the tunnel list
287 path = InstanceIdentifier.create(TunnelList.class)
288 .child(InternalTunnel.class, new InternalTunnelKey(srcDpnId, dstDpnId, dstTep.getTunnelType()));
291 // Release the Ids for the reverse trunk interface Name
292 ItmUtils.releaseIdForTrunkInterfaceName(dstTep.getInterfaceName(),
293 new String(dstTep.getIpAddress().getValue()),
294 new String(srcTep.getIpAddress().getValue()),
295 dstTep.getTunnelType().getName());
296 removeLogicalGroupTunnel(dstDpnId, srcDpnId);
299 private static boolean checkIfTrunkExists(BigInteger srcDpnId, BigInteger dstDpnId,
300 Class<? extends TunnelTypeBase> tunType, DataBroker dataBroker) {
301 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
302 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, tunType));
303 return ItmUtils.read(LogicalDatastoreType.CONFIGURATION,path, dataBroker).isPresent();
306 private void removeLogicalGroupTunnel(BigInteger srcDpnId, BigInteger dstDpnId) {
307 boolean tunnelAggregationEnabled = ItmTunnelAggregationHelper.isTunnelAggregationEnabled();
308 if (!tunnelAggregationEnabled) {
311 String logicTunnelName = ItmUtils.getLogicalTunnelGroupName(srcDpnId, dstDpnId);
312 ItmTunnelAggregationDeleteWorker addWorker =
313 new ItmTunnelAggregationDeleteWorker(logicTunnelName, srcDpnId, dstDpnId, dataBroker);
314 jobCoordinator.enqueueJob(logicTunnelName, addWorker);
317 private static class ItmTunnelAggregationDeleteWorker implements Callable<List<ListenableFuture<Void>>> {
319 private final String logicTunnelName;
320 private final BigInteger srcDpnId;
321 private final BigInteger dstDpnId;
322 private final ManagedNewTransactionRunner txRunner;
324 ItmTunnelAggregationDeleteWorker(String groupName, BigInteger srcDpnId, BigInteger dstDpnId, DataBroker db) {
325 this.logicTunnelName = groupName;
326 this.srcDpnId = srcDpnId;
327 this.dstDpnId = dstDpnId;
328 this.txRunner = new ManagedNewTransactionRunnerImpl(db);
332 public List<ListenableFuture<Void>> call() {
333 Collection<InternalTunnel> tunnels = ItmUtils.ITM_CACHE.getAllInternalTunnel();
335 //The logical tunnel interface be removed only when the last tunnel interface on each OVS is deleted
336 boolean emptyTunnelGroup = true;
337 boolean foundLogicGroupIface = false;
338 for (InternalTunnel tunl : tunnels) {
339 if (tunl.getSourceDPN().equals(srcDpnId) && tunl.getDestinationDPN().equals(dstDpnId)) {
340 if (tunl.getTransportType().isAssignableFrom(TunnelTypeVxlan.class)
341 && tunl.getTunnelInterfaceNames() != null && !tunl.getTunnelInterfaceNames().isEmpty()) {
342 emptyTunnelGroup = false;
344 } else if (tunl.getTransportType().isAssignableFrom(TunnelTypeLogicalGroup.class)) {
345 foundLogicGroupIface = true;
349 if (emptyTunnelGroup && foundLogicGroupIface) {
350 return singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
351 LOG.debug("MULTIPLE_VxLAN_TUNNELS: remove the logical tunnel group {} because a last tunnel"
352 + " interface on srcDpnId {} dstDpnId {} is removed", logicTunnelName, srcDpnId, dstDpnId);
353 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(logicTunnelName);
354 tx.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
355 ItmUtils.ITM_CACHE.removeInterface(logicTunnelName);
356 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
357 .child(InternalTunnel.class,
358 new InternalTunnelKey(dstDpnId, srcDpnId, TunnelTypeLogicalGroup.class));
359 tx.delete(LogicalDatastoreType.CONFIGURATION, path);
360 ItmUtils.ITM_CACHE.removeInternalTunnel(logicTunnelName);
362 } else if (!emptyTunnelGroup) {
363 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not last tunnel in logical tunnel group {}", logicTunnelName);
365 return Collections.emptyList();
369 private void removeTunnelInterfaceFromOvsdb(TypedReadWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
370 TunnelEndPoints dstTep, BigInteger srcDpnId, BigInteger dstDpnId) {
371 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
372 srcTep.getIpAddress().getIpv4Address().getValue(),
373 dstTep.getIpAddress().getIpv4Address().getValue(),
374 srcTep.getTunnelType().getName());
375 LOG.trace("Removing forward Trunk Interface {}", trunkfwdIfName);
376 ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(srcDpnId).build();
377 Interface iface = dpnTepStateCache.getInterfaceFromCache(trunkfwdIfName);
378 // ITM DIRECT TUNNELS -- Call the OVS Worker directly
381 removeConfiguration(tx, iface, parentRefs);
382 } catch (ExecutionException | InterruptedException | OperationFailedException e) {
383 LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", iface.getName(), e);
386 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
387 dstTep.getIpAddress().getIpv4Address().getValue(),
388 srcTep.getIpAddress().getIpv4Address().getValue(),
389 srcTep.getTunnelType().getName());
390 parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dstDpnId).build();
391 iface = dpnTepStateCache.getInterfaceFromCache(trunkRevIfName);
395 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
396 removeConfiguration(tx, iface, parentRefs);
397 } catch (ExecutionException | InterruptedException | OperationFailedException e) {
398 LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", iface.getName(), e);
403 private boolean checkIfTepInterfaceExists(BigInteger srcDpnId, BigInteger dstDpnId) {
404 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId,dstDpnId);
405 if (dpnTepInterfaceInfo != null) {
406 return dpnTepInterfaceInfo.getTunnelName() != null;
411 private void removeConfiguration(TypedReadWriteTransaction<Configuration> tx, Interface interfaceOld,
412 ParentRefs parentRefs) throws ExecutionException, InterruptedException, OperationFailedException {
413 IfTunnel ifTunnel = interfaceOld.augmentation(IfTunnel.class);
414 if (ifTunnel != null) {
415 // Check if the same transaction can be used across Config and operational shards
416 removeTunnelConfiguration(tx, parentRefs, interfaceOld.getName(), ifTunnel);
420 private void removeTunnelConfiguration(TypedReadWriteTransaction<Configuration> tx, ParentRefs parentRefs,
421 String interfaceName, IfTunnel ifTunnel)
422 throws ExecutionException, InterruptedException, OperationFailedException {
424 LOG.info("removing tunnel configuration for {}", interfaceName);
425 BigInteger dpId = null;
426 if (parentRefs != null) {
427 dpId = parentRefs.getDatapathNodeIdentifier();
434 Optional<OvsBridgeRefEntry> ovsBridgeRefEntryOptional = ovsBridgeRefEntryCache.get(dpId);
435 Optional<OvsBridgeEntry> ovsBridgeEntryOptional;
436 OvsdbBridgeRef ovsdbBridgeRef = null;
437 if (ovsBridgeRefEntryOptional.isPresent()) {
438 ovsdbBridgeRef = ovsBridgeRefEntryOptional.get().getOvsBridgeReference();
440 ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
441 if (ovsBridgeEntryOptional.isPresent()) {
442 ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference();
446 if (ovsdbBridgeRef != null) {
447 removeTerminationEndPoint(ovsdbBridgeRef.getValue(), interfaceName);
450 // delete tunnel ingress flow
451 removeTunnelIngressFlow(tx, interfaceName, dpId);
453 // delete bridge to tunnel interface mappings
454 OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpId);
455 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid =
456 DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey);
458 ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
459 if (ovsBridgeEntryOptional.isPresent()) {
460 List<OvsBridgeTunnelEntry> bridgeTunnelEntries = ovsBridgeEntryOptional.get().getOvsBridgeTunnelEntry();
461 deleteBridgeInterfaceEntry(bridgeEntryKey, bridgeTunnelEntries, bridgeEntryIid, interfaceName);
462 // IfIndex needs to be removed only during State Clean up not Config
463 // TunnelMetaUtils.removeLportTagInterfaceMap(idManager, defaultOperationalShardTransaction, interfaceName);
464 cleanUpInterfaceWithUnknownState(interfaceName, parentRefs, ifTunnel);
465 directTunnelUtils.removeLportTagInterfaceMap(interfaceName);
469 private void removeTerminationEndPoint(InstanceIdentifier<?> bridgeIid, String interfaceName) {
470 LOG.debug("removing termination point for {}", interfaceName);
471 InstanceIdentifier<TerminationPoint> tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier(
472 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceName);
473 ITMBatchingUtils.delete(tpIid, ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
476 private void removeTunnelIngressFlow(TypedReadWriteTransaction<Configuration> tx, String interfaceName,
477 BigInteger dpId) throws ExecutionException, InterruptedException {
478 directTunnelUtils.removeTunnelIngressFlow(tx, dpId, interfaceName);
481 // if the node is shutdown, there will be stale interface state entries,
482 // with unknown op-state, clear them.
483 private void cleanUpInterfaceWithUnknownState(String interfaceName, ParentRefs parentRefs, IfTunnel ifTunnel)
484 throws ReadFailedException {
485 Optional<StateTunnelList> stateTunnelList =
486 tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
487 if (stateTunnelList.isPresent() && stateTunnelList.get().getOperState() == TunnelOperStatus.Unknown) {
488 String staleInterface = ifTunnel != null ? interfaceName : parentRefs.getParentInterface();
489 LOG.debug("cleaning up parent-interface for {}, since the oper-status is UNKNOWN", interfaceName);
490 directTunnelUtils.deleteTunnelStateEntry(staleInterface);
494 private void deleteBridgeInterfaceEntry(OvsBridgeEntryKey bridgeEntryKey,
495 List<OvsBridgeTunnelEntry> bridgeTunnelEntries,
496 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid,
497 String interfaceName) {
498 OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(interfaceName);
499 InstanceIdentifier<OvsBridgeTunnelEntry> bridgeTunnelEntryIid =
500 DirectTunnelUtils.getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey);
501 ITMBatchingUtils.delete(bridgeTunnelEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
502 if (bridgeTunnelEntries.size() <= 1) {
503 ITMBatchingUtils.delete(bridgeEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);