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.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.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.OfEndPointCache;
32 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
33 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
34 import org.opendaylight.genius.itm.cache.TunnelStateCache;
35 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
36 import org.opendaylight.genius.itm.impl.ItmUtils;
37 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
38 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
39 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
40 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
41 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
42 import org.opendaylight.mdsal.binding.api.DataBroker;
43 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
44 import org.opendaylight.mdsal.common.api.ReadFailedException;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPointsBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembershipKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
72 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
73 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.common.OperationFailedException;
76 import org.opendaylight.yangtools.yang.common.Uint64;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
80 public class ItmInternalTunnelDeleteWorker {
82 private static final Logger LOG = LoggerFactory.getLogger(ItmInternalTunnelDeleteWorker.class) ;
84 private final DataBroker dataBroker;
85 private final ManagedNewTransactionRunner txRunner;
86 private final JobCoordinator jobCoordinator;
87 private final TunnelMonitoringConfig tunnelMonitoringConfig;
88 private final IInterfaceManager interfaceManager;
89 private final DpnTepStateCache dpnTepStateCache;
90 private final OvsBridgeEntryCache ovsBridgeEntryCache;
91 private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
92 private final TunnelStateCache tunnelStateCache;
93 private final DirectTunnelUtils directTunnelUtils;
94 private final OfEndPointCache ofEndPointCache;
95 private final ItmConfig itmConfig;
96 private final TombstonedNodeManager tombstonedNodeManager;
98 public ItmInternalTunnelDeleteWorker(DataBroker dataBroker, JobCoordinator jobCoordinator,
99 TunnelMonitoringConfig tunnelMonitoringConfig,
100 IInterfaceManager interfaceManager, DpnTepStateCache dpnTepStateCache,
101 OvsBridgeEntryCache ovsBridgeEntryCache,
102 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
103 TunnelStateCache tunnelStateCache,
104 DirectTunnelUtils directTunnelUtils,
105 OfEndPointCache ofEndPointCache,
107 TombstonedNodeManager tombstonedNodeManager) {
108 this.dataBroker = dataBroker;
109 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
110 this.jobCoordinator = jobCoordinator;
111 this.tunnelMonitoringConfig = tunnelMonitoringConfig;
112 this.interfaceManager = interfaceManager;
113 this.dpnTepStateCache = dpnTepStateCache;
114 this.ovsBridgeEntryCache = ovsBridgeEntryCache;
115 this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
116 this.tunnelStateCache = tunnelStateCache;
117 this.directTunnelUtils = directTunnelUtils;
118 this.ofEndPointCache = ofEndPointCache;
119 this.itmConfig = itmConfig;
120 this.tombstonedNodeManager = tombstonedNodeManager;
123 @SuppressWarnings("checkstyle:IllegalCatch")
124 public List<ListenableFuture<Void>> deleteTunnels(IMdsalApiManager mdsalManager,
125 Collection<DPNTEPsInfo> dpnTepsList, Collection<DPNTEPsInfo> meshedDpnList) {
126 LOG.trace("TEPs to be deleted {} " , dpnTepsList);
127 return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
128 if (dpnTepsList == null || dpnTepsList.size() == 0) {
129 LOG.debug("no vtep to delete");
133 if (meshedDpnList == null || meshedDpnList.size() == 0) {
134 LOG.debug("No Meshed Vteps");
137 for (DPNTEPsInfo srcDpn : dpnTepsList) {
138 LOG.trace("Processing srcDpn {}", srcDpn);
140 List<TunnelEndPoints> meshedEndPtCache = ItmUtils.getTEPsForDpn(srcDpn.getDPNID(), meshedDpnList);
141 if (meshedEndPtCache == null) {
142 LOG.debug("No Tunnel End Point configured for this DPN {}", srcDpn.getDPNID());
145 LOG.debug("Entries in meshEndPointCache {} for DPN Id{} ", meshedEndPtCache.size(), srcDpn.getDPNID());
146 for (TunnelEndPoints srcTep : srcDpn.nonnullTunnelEndPoints()) {
147 LOG.trace("Processing srcTep {}", srcTep);
148 Boolean isDpnTombstoned = tombstonedNodeManager.isDpnTombstoned(srcDpn.getDPNID());
149 @NonNull Map<TzMembershipKey, TzMembership> srcTZones = srcTep.nonnullTzMembership();
150 boolean tepDeleteFlag = false;
151 // First, take care of tunnel removal, so run through all other DPNS other than srcDpn
152 // In the tep received from Delete DCN, the membership list will always be 1
153 // as the DCN is at transport zone level
154 // Hence if a tunnel is shared across TZs, compare the original membership list between end points
155 // to decide if tunnel to be deleted.
156 for (DPNTEPsInfo dstDpn : meshedDpnList) {
157 if (!Objects.equals(srcDpn.getDPNID(), dstDpn.getDPNID())) {
158 for (TunnelEndPoints dstTep : dstDpn.nonnullTunnelEndPoints()) {
159 if (!ItmUtils.getIntersection(dstTep.nonnullTzMembership(), srcTZones).isEmpty()) {
160 Map<TzMembershipKey, TzMembership> originalTzMembership =
161 ItmUtils.getOriginalTzMembership(srcTep, srcDpn.getDPNID(), meshedDpnList);
162 if (ItmUtils.getIntersection(dstTep.getTzMembership(),
163 originalTzMembership).size() == 1) {
164 if (interfaceManager.isItmDirectTunnelsEnabled()) {
165 if (checkIfTepInterfaceExists(dstDpn.getDPNID(), srcDpn.getDPNID())) {
166 // remove all trunk interfaces
167 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
168 + "Destination TEP {} " ,srcTep , dstTep);
169 removeTunnelInterfaceFromOvsdb(tx, srcTep, dstTep, srcDpn.getDPNID(),
171 if (isDpnTombstoned) {
172 LOG.trace("Removing tunnelState entry for {} while tombstoned "
173 + "is set {}", srcDpn.getDPNID(), isDpnTombstoned);
174 removeTunnelState(srcTep,dstTep);
178 if (checkIfTrunkExists(dstDpn.getDPNID(), srcDpn.getDPNID(),
179 srcTep.getTunnelType(), dataBroker)) {
180 // remove all trunk interfaces
181 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
182 + "Destination TEP {} ", srcTep, dstTep);
183 removeTrunkInterface(tx, srcTep, dstTep, srcDpn.getDPNID(),
193 for (DPNTEPsInfo dstDpn : meshedDpnList) {
194 // Second, take care of Tep TZ membership and identify if tep can be removed
195 if (Objects.equals(srcDpn.getDPNID(), dstDpn.getDPNID())) {
196 // Same DPN, so remove the TZ membership
197 for (TunnelEndPoints dstTep : dstDpn.nonnullTunnelEndPoints()) {
198 if (Objects.equals(dstTep.getIpAddress(), srcTep.getIpAddress())) {
199 // Remove the deleted TZ membership from the TEP
200 LOG.debug("Removing TZ list {} from Existing TZ list {} ", srcTZones,
201 dstTep.getTzMembership());
202 List<TzMembership> updatedList =
203 ItmUtils.removeTransportZoneMembership(dstTep, srcTZones);
204 if (updatedList.isEmpty()) {
205 LOG.debug(" This TEP can be deleted {}", srcTep);
206 tepDeleteFlag = true;
208 TunnelEndPointsBuilder modifiedTepBld = new TunnelEndPointsBuilder(dstTep);
209 modifiedTepBld.setTzMembership(updatedList);
210 TunnelEndPoints modifiedTep = modifiedTepBld.build() ;
211 InstanceIdentifier<TunnelEndPoints> tepPath = InstanceIdentifier
212 .builder(DpnEndpoints.class)
213 .child(DPNTEPsInfo.class, dstDpn.key())
214 .child(TunnelEndPoints.class, dstTep.key()).build();
216 LOG.debug(" Store the modified Tep in DS {} ", modifiedTep);
217 tx.put(tepPath, modifiedTep);
224 // Third, removing vtep / dpn from Tunnels OpDs.
225 InstanceIdentifier<TunnelEndPoints> tepPath =
226 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
227 .child(TunnelEndPoints.class, srcTep.key()).build();
229 LOG.trace("Tep Removal of TEP {} from DPNTEPSINFO CONFIG DS with Key {} ", srcTep,
232 // remove the tep from the cache
233 meshedEndPtCache.remove(srcTep);
234 Class<? extends TunnelMonitoringTypeBase> monitorProtocol =
235 tunnelMonitoringConfig.getMonitorProtocol();
236 InstanceIdentifier<DPNTEPsInfo> dpnPath =
237 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
240 if (meshedEndPtCache.isEmpty()) {
241 // remove dpn if no vteps exist on dpn
242 if (monitorProtocol.isAssignableFrom(TunnelMonitoringTypeLldp.class)) {
243 LOG.debug("Removing Terminating Service Table Flow ");
244 ItmUtils.removeTerminatingServiceTable(tx, srcDpn.getDPNID(), mdsalManager);
246 LOG.trace("DPN Removal from DPNTEPSINFO CONFIG DS {}", srcDpn.getDPNID());
248 InstanceIdentifier<DpnEndpoints> tnlContainerPath =
249 InstanceIdentifier.builder(DpnEndpoints.class).build();
250 Optional<DpnEndpoints> containerOptional = tx.read(tnlContainerPath).get();
251 // remove container if no DPNs are present
252 if (containerOptional.isPresent()) {
253 DpnEndpoints deps = containerOptional.get();
254 if (deps.getDPNTEPsInfo() == null || deps.getDPNTEPsInfo().isEmpty()) {
255 LOG.trace("Container Removal from DPNTEPSINFO CONFIG DS");
256 tx.delete(tnlContainerPath);
261 if (interfaceManager.isItmDirectTunnelsEnabled()) {
262 // SF419 Remove the DPNSTEPs DS
263 LOG.debug("Deleting TEP Interface information from Config datastore with DPNs-Teps "
264 + "for source Dpn {}", srcDpn.getDPNID());
265 // Clean up the DPN TEPs State DS
266 dpnTepStateCache.removeTepFromDpnTepInterfaceConfigDS(srcDpn.getDPNID());
273 private void removeTrunkInterface(TypedWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
274 TunnelEndPoints dstTep, Uint64 srcDpnId, Uint64 dstDpnId) {
275 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
276 srcTep.getIpAddress().stringValue(),
277 dstTep.getIpAddress().stringValue(),
278 srcTep.getTunnelType().getName());
279 LOG.trace("Removing forward Trunk Interface {}" , trunkfwdIfName);
280 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkfwdIfName);
281 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
282 trunkfwdIfName, trunkIdentifier) ;
283 tx.delete(trunkIdentifier);
284 ItmUtils.ITM_CACHE.removeInterface(trunkfwdIfName);
285 // also update itm-state ds -- Delete the forward tunnel-interface from the tunnel list
286 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
287 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, srcTep.getTunnelType()));
289 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkfwdIfName);
290 // Release the Ids for the forward trunk interface Name
291 ItmUtils.releaseIdForTrunkInterfaceName(srcTep.getInterfaceName(),
292 srcTep.getIpAddress().stringValue(),
293 dstTep.getIpAddress().stringValue(),
294 srcTep.getTunnelType().getName());
295 removeLogicalGroupTunnel(srcDpnId, dstDpnId);
297 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
298 dstTep.getIpAddress().stringValue(),
299 srcTep.getIpAddress().stringValue(),
300 srcTep.getTunnelType().getName());
301 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
302 trunkIdentifier = ItmUtils.buildId(trunkRevIfName);
303 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
304 trunkRevIfName, trunkIdentifier) ;
305 tx.delete(trunkIdentifier);
306 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkRevIfName);
307 // also update itm-state ds -- Delete the reverse tunnel-interface from the tunnel list
308 path = InstanceIdentifier.create(TunnelList.class)
309 .child(InternalTunnel.class, new InternalTunnelKey(srcDpnId, dstDpnId, dstTep.getTunnelType()));
312 // Release the Ids for the reverse trunk interface Name
313 ItmUtils.releaseIdForTrunkInterfaceName(dstTep.getInterfaceName(),
314 dstTep.getIpAddress().stringValue(),
315 srcTep.getIpAddress().stringValue(),
316 dstTep.getTunnelType().getName());
317 removeLogicalGroupTunnel(dstDpnId, srcDpnId);
320 private static boolean checkIfTrunkExists(Uint64 srcDpnId, Uint64 dstDpnId,
321 Class<? extends TunnelTypeBase> tunType, DataBroker dataBroker) {
322 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
323 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, tunType));
324 return ItmUtils.read(LogicalDatastoreType.CONFIGURATION,path, dataBroker).isPresent();
327 private void removeLogicalGroupTunnel(Uint64 srcDpnId, Uint64 dstDpnId) {
328 boolean tunnelAggregationEnabled = ItmTunnelAggregationHelper.isTunnelAggregationEnabled();
329 if (!tunnelAggregationEnabled) {
332 String logicTunnelName = ItmUtils.getLogicalTunnelGroupName(srcDpnId, dstDpnId);
333 ItmTunnelAggregationDeleteWorker addWorker =
334 new ItmTunnelAggregationDeleteWorker(logicTunnelName, srcDpnId, dstDpnId, dataBroker);
335 jobCoordinator.enqueueJob(logicTunnelName, addWorker);
338 private static class ItmTunnelAggregationDeleteWorker implements Callable<List<? extends ListenableFuture<?>>> {
340 private final String logicTunnelName;
341 private final Uint64 srcDpnId;
342 private final Uint64 dstDpnId;
343 private final ManagedNewTransactionRunner txRunner;
345 ItmTunnelAggregationDeleteWorker(String groupName, Uint64 srcDpnId, Uint64 dstDpnId, DataBroker db) {
346 this.logicTunnelName = groupName;
347 this.srcDpnId = srcDpnId;
348 this.dstDpnId = dstDpnId;
349 this.txRunner = new ManagedNewTransactionRunnerImpl(db);
353 public List<ListenableFuture<Void>> call() {
354 Collection<InternalTunnel> tunnels = ItmUtils.ITM_CACHE.getAllInternalTunnel();
356 //The logical tunnel interface be removed only when the last tunnel interface on each OVS is deleted
357 boolean emptyTunnelGroup = true;
358 boolean foundLogicGroupIface = false;
359 for (InternalTunnel tunl : tunnels) {
360 if (Objects.equals(tunl.getSourceDPN(), srcDpnId) && Objects.equals(tunl.getDestinationDPN(),
362 if (tunl.getTransportType() != null && tunl.getTransportType().isAssignableFrom(
363 TunnelTypeVxlan.class)
364 && tunl.getTunnelInterfaceNames() != null && !tunl.getTunnelInterfaceNames().isEmpty()) {
365 emptyTunnelGroup = false;
367 } else if (tunl.getTransportType() != null && tunl.getTransportType().isAssignableFrom(
368 TunnelTypeLogicalGroup.class)) {
369 foundLogicGroupIface = true;
373 if (emptyTunnelGroup && foundLogicGroupIface) {
374 return singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
375 LOG.debug("MULTIPLE_VxLAN_TUNNELS: remove the logical tunnel group {} because a last tunnel"
376 + " interface on srcDpnId {} dstDpnId {} is removed", logicTunnelName, srcDpnId, dstDpnId);
377 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(logicTunnelName);
378 tx.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
379 ItmUtils.ITM_CACHE.removeInterface(logicTunnelName);
380 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
381 .child(InternalTunnel.class,
382 new InternalTunnelKey(dstDpnId, srcDpnId, TunnelTypeLogicalGroup.class));
383 tx.delete(LogicalDatastoreType.CONFIGURATION, path);
384 ItmUtils.ITM_CACHE.removeInternalTunnel(logicTunnelName);
386 } else if (!emptyTunnelGroup) {
387 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not last tunnel in logical tunnel group {}", logicTunnelName);
389 return Collections.emptyList();
393 private void removeTunnelInterfaceFromOvsdb(TypedReadWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
394 TunnelEndPoints dstTep, Uint64 srcDpnId, Uint64 dstDpnId) {
395 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
396 srcTep.getIpAddress().getIpv4Address().getValue(),
397 dstTep.getIpAddress().getIpv4Address().getValue(),
398 srcTep.getTunnelType().getName());
399 LOG.trace("Removing forward Trunk Interface {}", trunkfwdIfName);
400 ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(srcDpnId).build();
401 Interface iface = dpnTepStateCache.getInterfaceFromCache(trunkfwdIfName);
402 // ITM DIRECT TUNNELS -- Call the OVS Worker directly
405 removeConfiguration(tx, iface, parentRefs);
406 } catch (ExecutionException | InterruptedException | OperationFailedException e) {
407 LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", iface.getName(), e);
410 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
411 dstTep.getIpAddress().getIpv4Address().getValue(),
412 srcTep.getIpAddress().getIpv4Address().getValue(),
413 srcTep.getTunnelType().getName());
414 parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dstDpnId).build();
415 iface = dpnTepStateCache.getInterfaceFromCache(trunkRevIfName);
419 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
420 removeConfiguration(tx, iface, parentRefs);
421 } catch (ExecutionException | InterruptedException | OperationFailedException e) {
422 LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", iface.getName(), e);
427 private void removeTunnelState(TunnelEndPoints srcTep, TunnelEndPoints dstTep) {
428 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
429 srcTep.getIpAddress().getIpv4Address().getValue(),
430 dstTep.getIpAddress().getIpv4Address().getValue(),
431 srcTep.getTunnelType().getName());
432 LOG.trace("Removing tunnelstate for {}", trunkfwdIfName);
433 directTunnelUtils.deleteTunnelStateEntry(trunkfwdIfName);
435 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
436 dstTep.getIpAddress().getIpv4Address().getValue(),
437 srcTep.getIpAddress().getIpv4Address().getValue(),
438 srcTep.getTunnelType().getName());
439 LOG.trace("Removing tunnelstate for {}", trunkRevIfName);
440 directTunnelUtils.deleteTunnelStateEntry(trunkRevIfName);
443 private boolean checkIfTepInterfaceExists(Uint64 srcDpnId, Uint64 dstDpnId) {
444 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, dstDpnId);
445 if (dpnTepInterfaceInfo != null) {
446 return dpnTepInterfaceInfo.getTunnelName() != null;
451 private void removeConfiguration(TypedReadWriteTransaction<Configuration> tx, Interface interfaceOld,
452 ParentRefs parentRefs) throws ExecutionException, InterruptedException, OperationFailedException {
453 IfTunnel ifTunnel = interfaceOld.augmentation(IfTunnel.class);
454 if (ifTunnel != null) {
455 // Check if the same transaction can be used across Config and operational shards
456 removeTunnelConfiguration(tx, parentRefs, interfaceOld.getName(), ifTunnel);
460 private void removeTunnelConfiguration(TypedReadWriteTransaction<Configuration> tx, ParentRefs parentRefs,
461 String interfaceName, IfTunnel ifTunnel)
462 throws ExecutionException, InterruptedException, OperationFailedException {
464 LOG.info("removing tunnel configuration for {}", interfaceName);
466 if (parentRefs != null) {
467 dpId = parentRefs.getDatapathNodeIdentifier();
474 OvsdbBridgeRef ovsdbBridgeRef = getOvsdbBridgeRef(dpId);
475 Optional<OvsBridgeEntry> ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
477 // delete bridge to tunnel interface mappings
478 OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpId);
479 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid =
480 DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey);
483 if (ovsBridgeEntryOptional.isPresent()) {
484 @NonNull Map<OvsBridgeTunnelEntryKey, OvsBridgeTunnelEntry> bridgeTunnelEntries =
485 ovsBridgeEntryOptional.get().nonnullOvsBridgeTunnelEntry();
487 if (ovsdbBridgeRef != null) {
488 if (!itmConfig.isUseOfTunnels()) {
489 removeTerminationEndPoint(ovsdbBridgeRef.getValue(), interfaceName);
490 } else if (bridgeTunnelEntries.size() <= 1) {
491 removeTerminationEndPoint(ovsdbBridgeRef.getValue(), ofEndPointCache.get(dpId));
492 ofEndPointCache.remove(dpId);
496 deleteBridgeInterfaceEntry(bridgeEntryKey, bridgeTunnelEntries, bridgeEntryIid, interfaceName);
497 // IfIndex needs to be removed only during State Clean up not Config
500 directTunnelUtils.deleteTunnelStateEntry(interfaceName);
501 // delete tunnel ingress flow
502 removeTunnelIngressFlow(tx, interfaceName, dpId);
503 directTunnelUtils.removeTunnelEgressFlow(tx, dpId, interfaceName);
504 cleanUpInterfaceWithUnknownState(interfaceName, parentRefs, ifTunnel);
505 directTunnelUtils.removeLportTagInterfaceMap(interfaceName);
508 private OvsdbBridgeRef getOvsdbBridgeRef(Uint64 dpId) throws ReadFailedException {
509 Optional<OvsBridgeRefEntry> ovsBridgeRefEntryOptional = ovsBridgeRefEntryCache.get(dpId);
510 Optional<OvsBridgeEntry> ovsBridgeEntryOptional;
511 OvsdbBridgeRef ovsdbBridgeRef = null;
512 if (ovsBridgeRefEntryOptional.isPresent()) {
513 ovsdbBridgeRef = ovsBridgeRefEntryOptional.get().getOvsBridgeReference();
515 ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
516 if (ovsBridgeEntryOptional.isPresent()) {
517 ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference();
520 return ovsdbBridgeRef;
523 private void removeTerminationEndPoint(InstanceIdentifier<?> bridgeIid, String interfaceName) {
524 LOG.debug("removing termination point for {}", interfaceName);
525 InstanceIdentifier<TerminationPoint> tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier(
526 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceName);
527 ITMBatchingUtils.delete(tpIid, ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
530 private void removeTunnelIngressFlow(TypedReadWriteTransaction<Configuration> tx, String interfaceName,
531 Uint64 dpId) throws ExecutionException, InterruptedException {
532 directTunnelUtils.removeTunnelIngressFlow(tx, dpId, interfaceName);
535 // if the node is shutdown, there will be stale interface state entries,
536 // with unknown op-state, clear them.
537 private void cleanUpInterfaceWithUnknownState(String interfaceName, ParentRefs parentRefs, IfTunnel ifTunnel)
538 throws ReadFailedException {
539 Optional<StateTunnelList> stateTunnelList =
540 tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
541 if (stateTunnelList.isPresent() && stateTunnelList.get().getOperState() == TunnelOperStatus.Unknown) {
542 String staleInterface = ifTunnel != null ? interfaceName : parentRefs.getParentInterface();
543 LOG.debug("cleaning up parent-interface for {}, since the oper-status is UNKNOWN", interfaceName);
544 directTunnelUtils.deleteTunnelStateEntry(staleInterface);
548 private void deleteBridgeInterfaceEntry(OvsBridgeEntryKey bridgeEntryKey,
549 Map<OvsBridgeTunnelEntryKey, OvsBridgeTunnelEntry> bridgeTunnelEntries,
550 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid,
551 String interfaceName) {
552 OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(interfaceName);
553 InstanceIdentifier<OvsBridgeTunnelEntry> bridgeTunnelEntryIid =
554 DirectTunnelUtils.getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey);
555 ITMBatchingUtils.delete(bridgeTunnelEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
556 if (bridgeTunnelEntries.size() <= 1) {
557 ITMBatchingUtils.delete(bridgeEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);