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.mdsal.binding.util.Datastore.CONFIGURATION;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
18 import java.util.Objects;
19 import java.util.Optional;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.ExecutionException;
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
24 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
25 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
26 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
27 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
28 import org.opendaylight.genius.itm.cache.TunnelStateCache;
29 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
30 import org.opendaylight.genius.itm.impl.ItmUtils;
31 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
32 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
33 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
34 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
35 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
36 import org.opendaylight.mdsal.binding.api.DataBroker;
37 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
38 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
39 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
40 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
41 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
42 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
43 import org.opendaylight.mdsal.common.api.ReadFailedException;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPointsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembershipKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
71 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.opendaylight.yangtools.yang.common.OperationFailedException;
74 import org.opendaylight.yangtools.yang.common.Uint64;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
78 public class ItmInternalTunnelDeleteWorker {
80 private static final Logger LOG = LoggerFactory.getLogger(ItmInternalTunnelDeleteWorker.class) ;
82 private final DataBroker dataBroker;
83 private final ManagedNewTransactionRunner txRunner;
84 private final JobCoordinator jobCoordinator;
85 private final TunnelMonitoringConfig tunnelMonitoringConfig;
86 private final IInterfaceManager interfaceManager;
87 private final DpnTepStateCache dpnTepStateCache;
88 private final OvsBridgeEntryCache ovsBridgeEntryCache;
89 private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
90 private final TunnelStateCache tunnelStateCache;
91 private final DirectTunnelUtils directTunnelUtils;
92 private final TombstonedNodeManager tombstonedNodeManager;
94 public ItmInternalTunnelDeleteWorker(DataBroker dataBroker, JobCoordinator jobCoordinator,
95 TunnelMonitoringConfig tunnelMonitoringConfig,
96 IInterfaceManager interfaceManager, DpnTepStateCache dpnTepStateCache,
97 OvsBridgeEntryCache ovsBridgeEntryCache,
98 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
99 TunnelStateCache tunnelStateCache,
100 DirectTunnelUtils directTunnelUtils,
101 TombstonedNodeManager tombstonedNodeManager) {
102 this.dataBroker = dataBroker;
103 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
104 this.jobCoordinator = jobCoordinator;
105 this.tunnelMonitoringConfig = tunnelMonitoringConfig;
106 this.interfaceManager = interfaceManager;
107 this.dpnTepStateCache = dpnTepStateCache;
108 this.ovsBridgeEntryCache = ovsBridgeEntryCache;
109 this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
110 this.tunnelStateCache = tunnelStateCache;
111 this.directTunnelUtils = directTunnelUtils;
112 this.tombstonedNodeManager = tombstonedNodeManager;
115 @SuppressWarnings("checkstyle:IllegalCatch")
116 public List<? extends ListenableFuture<?>> deleteTunnels(IMdsalApiManager mdsalManager,
117 Collection<DPNTEPsInfo> dpnTepsList, Collection<DPNTEPsInfo> meshedDpnList) {
118 LOG.trace("TEPs to be deleted {} " , dpnTepsList);
119 return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
120 if (dpnTepsList == null || dpnTepsList.size() == 0) {
121 LOG.debug("no vtep to delete");
125 if (meshedDpnList == null || meshedDpnList.size() == 0) {
126 LOG.debug("No Meshed Vteps");
129 for (DPNTEPsInfo srcDpn : dpnTepsList) {
130 LOG.trace("Processing srcDpn {}", srcDpn);
131 List<TunnelEndPoints> meshedEndPtCache = ItmUtils.getTEPsForDpn(srcDpn.getDPNID(), meshedDpnList);
132 if (meshedEndPtCache == null) {
133 LOG.debug("No Tunnel End Point configured for this DPN {}", srcDpn.getDPNID());
136 LOG.debug("Entries in meshEndPointCache {} for DPN Id{} ", meshedEndPtCache.size(), srcDpn.getDPNID());
137 for (TunnelEndPoints srcTep : srcDpn.nonnullTunnelEndPoints()) {
138 LOG.trace("Processing srcTep {}", srcTep);
139 Boolean isDpnTombstoned = tombstonedNodeManager.isDpnTombstoned(srcDpn.getDPNID());
140 @NonNull Map<TzMembershipKey, TzMembership> srcTZones = srcTep.nonnullTzMembership();
141 boolean tepDeleteFlag = false;
142 // First, take care of tunnel removal, so run through all other DPNS other than srcDpn
143 // In the tep received from Delete DCN, the membership list will always be 1
144 // as the DCN is at transport zone level
145 // Hence if a tunnel is shared across TZs, compare the original membership list between end points
146 // to decide if tunnel to be deleted.
147 for (DPNTEPsInfo dstDpn : meshedDpnList) {
148 if (!Objects.equals(srcDpn.getDPNID(), dstDpn.getDPNID())) {
149 for (TunnelEndPoints dstTep : dstDpn.nonnullTunnelEndPoints()) {
150 if (!ItmUtils.getIntersection(dstTep.nonnullTzMembership(), srcTZones).isEmpty()) {
151 Map<TzMembershipKey, TzMembership> originalTzMembership =
152 ItmUtils.getOriginalTzMembership(srcTep, srcDpn.getDPNID(), meshedDpnList);
153 if (ItmUtils.getIntersection(dstTep.getTzMembership(),
154 originalTzMembership).size() == 1) {
155 if (interfaceManager.isItmDirectTunnelsEnabled()) {
156 if (checkIfTepInterfaceExists(dstDpn.getDPNID(), srcDpn.getDPNID())) {
157 // remove all trunk interfaces
158 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
159 + "Destination TEP {} " ,srcTep , dstTep);
160 removeTunnelInterfaceFromOvsdb(tx, srcTep, dstTep, srcDpn.getDPNID(),
162 if (isDpnTombstoned) {
163 LOG.trace("Removing tunnelState entry for {} while tombstoned "
164 + "is set {}", srcDpn.getDPNID(), isDpnTombstoned);
165 removeTunnelState(srcTep,dstTep);
169 if (checkIfTrunkExists(dstDpn.getDPNID(), srcDpn.getDPNID(),
170 srcTep.getTunnelType(), dataBroker)) {
171 // remove all trunk interfaces
172 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
173 + "Destination TEP {} ", srcTep, dstTep);
174 removeTrunkInterface(tx, srcTep, dstTep, srcDpn.getDPNID(),
184 for (DPNTEPsInfo dstDpn : meshedDpnList) {
185 // Second, take care of Tep TZ membership and identify if tep can be removed
186 if (Objects.equals(srcDpn.getDPNID(), dstDpn.getDPNID())) {
187 // Same DPN, so remove the TZ membership
188 for (TunnelEndPoints dstTep : dstDpn.nonnullTunnelEndPoints()) {
189 if (Objects.equals(dstTep.getIpAddress(), srcTep.getIpAddress())) {
190 // Remove the deleted TZ membership from the TEP
191 LOG.debug("Removing TZ list {} from Existing TZ list {} ", srcTZones,
192 dstTep.getTzMembership());
193 List<TzMembership> updatedList =
194 ItmUtils.removeTransportZoneMembership(dstTep, srcTZones);
195 if (updatedList.isEmpty()) {
196 LOG.debug(" This TEP can be deleted {}", srcTep);
197 tepDeleteFlag = true;
199 TunnelEndPointsBuilder modifiedTepBld = new TunnelEndPointsBuilder(dstTep);
200 modifiedTepBld.setTzMembership(updatedList);
201 TunnelEndPoints modifiedTep = modifiedTepBld.build() ;
202 InstanceIdentifier<TunnelEndPoints> tepPath = InstanceIdentifier
203 .builder(DpnEndpoints.class)
204 .child(DPNTEPsInfo.class, dstDpn.key())
205 .child(TunnelEndPoints.class, dstTep.key()).build();
207 LOG.debug(" Store the modified Tep in DS {} ", modifiedTep);
208 tx.put(tepPath, modifiedTep);
215 // Third, removing vtep / dpn from Tunnels OpDs.
216 InstanceIdentifier<TunnelEndPoints> tepPath =
217 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
218 .child(TunnelEndPoints.class, srcTep.key()).build();
220 LOG.trace("Tep Removal of TEP {} from DPNTEPSINFO CONFIG DS with Key {} ", srcTep,
223 // remove the tep from the cache
224 meshedEndPtCache.remove(srcTep);
225 Class<? extends TunnelMonitoringTypeBase> monitorProtocol =
226 tunnelMonitoringConfig.getMonitorProtocol();
227 InstanceIdentifier<DPNTEPsInfo> dpnPath =
228 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
231 if (meshedEndPtCache.isEmpty()) {
232 // remove dpn if no vteps exist on dpn
233 if (monitorProtocol.isAssignableFrom(TunnelMonitoringTypeLldp.class)) {
234 LOG.debug("Removing Terminating Service Table Flow ");
235 ItmUtils.removeTerminatingServiceTable(tx, srcDpn.getDPNID(), mdsalManager);
237 LOG.trace("DPN Removal from DPNTEPSINFO CONFIG DS {}", srcDpn.getDPNID());
239 InstanceIdentifier<DpnEndpoints> tnlContainerPath =
240 InstanceIdentifier.builder(DpnEndpoints.class).build();
241 Optional<DpnEndpoints> containerOptional = tx.read(tnlContainerPath).get();
242 // remove container if no DPNs are present
243 if (containerOptional.isPresent()) {
244 DpnEndpoints deps = containerOptional.get();
245 if (deps.getDPNTEPsInfo() == null || deps.getDPNTEPsInfo().isEmpty()) {
246 LOG.trace("Container Removal from DPNTEPSINFO CONFIG DS");
247 tx.delete(tnlContainerPath);
252 if (interfaceManager.isItmDirectTunnelsEnabled()) {
253 // SF419 Remove the DPNSTEPs DS
254 LOG.debug("Deleting TEP Interface information from Config datastore with DPNs-Teps "
255 + "for source Dpn {}", srcDpn.getDPNID());
256 // Clean up the DPN TEPs State DS
257 dpnTepStateCache.removeTepFromDpnTepInterfaceConfigDS(srcDpn.getDPNID());
264 private void removeTrunkInterface(TypedWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
265 TunnelEndPoints dstTep, Uint64 srcDpnId, Uint64 dstDpnId) {
266 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
267 srcTep.getIpAddress().stringValue(),
268 dstTep.getIpAddress().stringValue(),
269 srcTep.getTunnelType().getName());
270 LOG.trace("Removing forward Trunk Interface {}" , trunkfwdIfName);
271 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkfwdIfName);
272 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
273 trunkfwdIfName, trunkIdentifier) ;
274 tx.delete(trunkIdentifier);
275 ItmUtils.ITM_CACHE.removeInterface(trunkfwdIfName);
276 // also update itm-state ds -- Delete the forward tunnel-interface from the tunnel list
277 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
278 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, srcTep.getTunnelType()));
280 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkfwdIfName);
281 // Release the Ids for the forward trunk interface Name
282 ItmUtils.releaseIdForTrunkInterfaceName(srcTep.getInterfaceName(),
283 srcTep.getIpAddress().stringValue(),
284 dstTep.getIpAddress().stringValue(),
285 srcTep.getTunnelType().getName());
286 removeLogicalGroupTunnel(srcDpnId, dstDpnId);
288 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
289 dstTep.getIpAddress().stringValue(),
290 srcTep.getIpAddress().stringValue(),
291 srcTep.getTunnelType().getName());
292 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
293 trunkIdentifier = ItmUtils.buildId(trunkRevIfName);
294 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
295 trunkRevIfName, trunkIdentifier) ;
296 tx.delete(trunkIdentifier);
297 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkRevIfName);
298 // also update itm-state ds -- Delete the reverse tunnel-interface from the tunnel list
299 path = InstanceIdentifier.create(TunnelList.class)
300 .child(InternalTunnel.class, new InternalTunnelKey(srcDpnId, dstDpnId, dstTep.getTunnelType()));
303 // Release the Ids for the reverse trunk interface Name
304 ItmUtils.releaseIdForTrunkInterfaceName(dstTep.getInterfaceName(),
305 dstTep.getIpAddress().stringValue(),
306 srcTep.getIpAddress().stringValue(),
307 dstTep.getTunnelType().getName());
308 removeLogicalGroupTunnel(dstDpnId, srcDpnId);
311 private static boolean checkIfTrunkExists(Uint64 srcDpnId, Uint64 dstDpnId,
312 Class<? extends TunnelTypeBase> tunType, DataBroker dataBroker) {
313 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
314 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, tunType));
315 return ItmUtils.read(LogicalDatastoreType.CONFIGURATION,path, dataBroker).isPresent();
318 private void removeLogicalGroupTunnel(Uint64 srcDpnId, Uint64 dstDpnId) {
319 boolean tunnelAggregationEnabled = ItmTunnelAggregationHelper.isTunnelAggregationEnabled();
320 if (!tunnelAggregationEnabled) {
323 String logicTunnelName = ItmUtils.getLogicalTunnelGroupName(srcDpnId, dstDpnId);
324 ItmTunnelAggregationDeleteWorker addWorker =
325 new ItmTunnelAggregationDeleteWorker(logicTunnelName, srcDpnId, dstDpnId, dataBroker);
326 jobCoordinator.enqueueJob(logicTunnelName, addWorker);
329 private static class ItmTunnelAggregationDeleteWorker implements Callable<List<? extends ListenableFuture<?>>> {
331 private final String logicTunnelName;
332 private final Uint64 srcDpnId;
333 private final Uint64 dstDpnId;
334 private final ManagedNewTransactionRunner txRunner;
336 ItmTunnelAggregationDeleteWorker(String groupName, Uint64 srcDpnId, Uint64 dstDpnId, DataBroker db) {
337 this.logicTunnelName = groupName;
338 this.srcDpnId = srcDpnId;
339 this.dstDpnId = dstDpnId;
340 this.txRunner = new ManagedNewTransactionRunnerImpl(db);
344 public List<? extends ListenableFuture<?>> call() {
345 Collection<InternalTunnel> tunnels = ItmUtils.ITM_CACHE.getAllInternalTunnel();
347 //The logical tunnel interface be removed only when the last tunnel interface on each OVS is deleted
348 boolean emptyTunnelGroup = true;
349 boolean foundLogicGroupIface = false;
350 for (InternalTunnel tunl : tunnels) {
351 if (Objects.equals(tunl.getSourceDPN(), srcDpnId) && Objects.equals(tunl.getDestinationDPN(),
353 if (tunl.getTransportType() != null && tunl.getTransportType().isAssignableFrom(
354 TunnelTypeVxlan.class)
355 && tunl.getTunnelInterfaceNames() != null && !tunl.getTunnelInterfaceNames().isEmpty()) {
356 emptyTunnelGroup = false;
358 } else if (tunl.getTransportType() != null && tunl.getTransportType().isAssignableFrom(
359 TunnelTypeLogicalGroup.class)) {
360 foundLogicGroupIface = true;
364 if (emptyTunnelGroup && foundLogicGroupIface) {
365 return singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
366 LOG.debug("MULTIPLE_VxLAN_TUNNELS: remove the logical tunnel group {} because a last tunnel"
367 + " interface on srcDpnId {} dstDpnId {} is removed", logicTunnelName, srcDpnId, dstDpnId);
368 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(logicTunnelName);
369 tx.delete(trunkIdentifier);
370 ItmUtils.ITM_CACHE.removeInterface(logicTunnelName);
371 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
372 .child(InternalTunnel.class,
373 new InternalTunnelKey(dstDpnId, srcDpnId, TunnelTypeLogicalGroup.class));
375 ItmUtils.ITM_CACHE.removeInternalTunnel(logicTunnelName);
377 } else if (!emptyTunnelGroup) {
378 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not last tunnel in logical tunnel group {}", logicTunnelName);
380 return Collections.emptyList();
384 private void removeTunnelInterfaceFromOvsdb(TypedReadWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
385 TunnelEndPoints dstTep, Uint64 srcDpnId, Uint64 dstDpnId) {
386 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
387 srcTep.getIpAddress().getIpv4Address().getValue(),
388 dstTep.getIpAddress().getIpv4Address().getValue(),
389 srcTep.getTunnelType().getName());
390 LOG.trace("Removing forward Trunk Interface {}", trunkfwdIfName);
391 ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(srcDpnId).build();
392 Interface iface = dpnTepStateCache.getInterfaceFromCache(trunkfwdIfName);
393 // ITM DIRECT TUNNELS -- Call the OVS Worker directly
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);
401 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
402 dstTep.getIpAddress().getIpv4Address().getValue(),
403 srcTep.getIpAddress().getIpv4Address().getValue(),
404 srcTep.getTunnelType().getName());
405 parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dstDpnId).build();
406 iface = dpnTepStateCache.getInterfaceFromCache(trunkRevIfName);
410 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
411 removeConfiguration(tx, iface, parentRefs);
412 } catch (ExecutionException | InterruptedException | OperationFailedException e) {
413 LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", iface.getName(), e);
418 private void removeTunnelState(TunnelEndPoints srcTep, TunnelEndPoints dstTep) {
419 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
420 srcTep.getIpAddress().getIpv4Address().getValue(),
421 dstTep.getIpAddress().getIpv4Address().getValue(),
422 srcTep.getTunnelType().getName());
423 LOG.trace("Removing tunnelstate for {}", trunkfwdIfName);
424 directTunnelUtils.deleteTunnelStateEntry(trunkfwdIfName);
426 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
427 dstTep.getIpAddress().getIpv4Address().getValue(),
428 srcTep.getIpAddress().getIpv4Address().getValue(),
429 srcTep.getTunnelType().getName());
430 LOG.trace("Removing tunnelstate for {}", trunkRevIfName);
431 directTunnelUtils.deleteTunnelStateEntry(trunkRevIfName);
434 private boolean checkIfTepInterfaceExists(Uint64 srcDpnId, Uint64 dstDpnId) {
435 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, dstDpnId);
436 if (dpnTepInterfaceInfo != null) {
437 return dpnTepInterfaceInfo.getTunnelName() != null;
442 private void removeConfiguration(TypedReadWriteTransaction<Configuration> tx, Interface interfaceOld,
443 ParentRefs parentRefs) throws ExecutionException, InterruptedException, OperationFailedException {
444 IfTunnel ifTunnel = interfaceOld.augmentation(IfTunnel.class);
445 if (ifTunnel != null) {
446 // Check if the same transaction can be used across Config and operational shards
447 removeTunnelConfiguration(tx, parentRefs, interfaceOld.getName(), ifTunnel);
451 private void removeTunnelConfiguration(TypedReadWriteTransaction<Configuration> tx, ParentRefs parentRefs,
452 String interfaceName, IfTunnel ifTunnel)
453 throws ExecutionException, InterruptedException, OperationFailedException {
455 LOG.info("removing tunnel configuration for {}", interfaceName);
457 if (parentRefs != null) {
458 dpId = parentRefs.getDatapathNodeIdentifier();
465 Optional<OvsBridgeRefEntry> ovsBridgeRefEntryOptional = ovsBridgeRefEntryCache.get(dpId);
466 Optional<OvsBridgeEntry> ovsBridgeEntryOptional;
467 OvsdbBridgeRef ovsdbBridgeRef = null;
468 if (ovsBridgeRefEntryOptional.isPresent()) {
469 ovsdbBridgeRef = ovsBridgeRefEntryOptional.get().getOvsBridgeReference();
471 ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
472 if (ovsBridgeEntryOptional.isPresent()) {
473 ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference();
477 if (ovsdbBridgeRef != null) {
478 removeTerminationEndPoint(ovsdbBridgeRef.getValue(), interfaceName);
480 removeTunnelIngressFlow(tx, interfaceName, dpId);
482 // delete bridge to tunnel interface mappings
483 OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpId);
484 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid =
485 DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey);
486 ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
489 if (ovsBridgeEntryOptional.isPresent()) {
490 @NonNull Map<OvsBridgeTunnelEntryKey, OvsBridgeTunnelEntry> bridgeTunnelEntries =
491 ovsBridgeEntryOptional.get().nonnullOvsBridgeTunnelEntry();
493 deleteBridgeInterfaceEntry(bridgeEntryKey, bridgeTunnelEntries, bridgeEntryIid, interfaceName);
494 // IfIndex needs to be removed only during State Clean up not Config
495 cleanUpInterfaceWithUnknownState(interfaceName, parentRefs, ifTunnel);
496 directTunnelUtils.removeLportTagInterfaceMap(interfaceName);
500 private void removeTerminationEndPoint(InstanceIdentifier<?> bridgeIid, String interfaceName) {
501 LOG.debug("removing termination point for {}", interfaceName);
502 InstanceIdentifier<TerminationPoint> tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier(
503 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceName);
504 ITMBatchingUtils.delete(tpIid, ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
507 private void removeTunnelIngressFlow(TypedReadWriteTransaction<Configuration> tx, String interfaceName,
508 Uint64 dpId) throws ExecutionException, InterruptedException {
509 directTunnelUtils.removeTunnelIngressFlow(tx, dpId, interfaceName);
512 // if the node is shutdown, there will be stale interface state entries,
513 // with unknown op-state, clear them.
514 private void cleanUpInterfaceWithUnknownState(String interfaceName, ParentRefs parentRefs, IfTunnel ifTunnel)
515 throws ReadFailedException {
516 Optional<StateTunnelList> stateTunnelList =
517 tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
518 if (stateTunnelList.isPresent() && stateTunnelList.get().getOperState() == TunnelOperStatus.Unknown) {
519 String staleInterface = ifTunnel != null ? interfaceName : parentRefs.getParentInterface();
520 LOG.debug("cleaning up parent-interface for {}, since the oper-status is UNKNOWN", interfaceName);
521 directTunnelUtils.deleteTunnelStateEntry(staleInterface);
525 private void deleteBridgeInterfaceEntry(OvsBridgeEntryKey bridgeEntryKey,
526 Map<OvsBridgeTunnelEntryKey, OvsBridgeTunnelEntry> bridgeTunnelEntries,
527 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid,
528 String interfaceName) {
529 OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(interfaceName);
530 InstanceIdentifier<OvsBridgeTunnelEntry> bridgeTunnelEntryIid =
531 DirectTunnelUtils.getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey);
532 ITMBatchingUtils.delete(bridgeTunnelEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
533 if (bridgeTunnelEntries.size() <= 1) {
534 ITMBatchingUtils.delete(bridgeEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);