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;
17 import java.util.Objects;
18 import java.util.Optional;
19 import java.util.concurrent.Callable;
20 import java.util.concurrent.ExecutionException;
21 import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
22 import org.opendaylight.genius.infra.Datastore.Configuration;
23 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
24 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
25 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
26 import org.opendaylight.genius.infra.TypedWriteTransaction;
27 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
28 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
29 import org.opendaylight.genius.itm.cache.OfEndPointCache;
30 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
31 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
32 import org.opendaylight.genius.itm.cache.TunnelStateCache;
33 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
34 import org.opendaylight.genius.itm.impl.ItmUtils;
35 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
36 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
37 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
38 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
39 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
40 import org.opendaylight.mdsal.binding.api.DataBroker;
41 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
42 import org.opendaylight.mdsal.common.api.ReadFailedException;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
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.tunnel.list.InternalTunnel;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.opendaylight.yangtools.yang.common.OperationFailedException;
73 import org.opendaylight.yangtools.yang.common.Uint64;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
77 public class ItmInternalTunnelDeleteWorker {
79 private static final Logger LOG = LoggerFactory.getLogger(ItmInternalTunnelDeleteWorker.class) ;
81 private final DataBroker dataBroker;
82 private final ManagedNewTransactionRunner txRunner;
83 private final JobCoordinator jobCoordinator;
84 private final TunnelMonitoringConfig tunnelMonitoringConfig;
85 private final IInterfaceManager interfaceManager;
86 private final DpnTepStateCache dpnTepStateCache;
87 private final OvsBridgeEntryCache ovsBridgeEntryCache;
88 private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
89 private final TunnelStateCache tunnelStateCache;
90 private final DirectTunnelUtils directTunnelUtils;
91 private final OfEndPointCache ofEndPointCache;
92 private final ItmConfig itmConfig;
93 private final TombstonedNodeManager tombstonedNodeManager;
95 public ItmInternalTunnelDeleteWorker(DataBroker dataBroker, JobCoordinator jobCoordinator,
96 TunnelMonitoringConfig tunnelMonitoringConfig,
97 IInterfaceManager interfaceManager, DpnTepStateCache dpnTepStateCache,
98 OvsBridgeEntryCache ovsBridgeEntryCache,
99 OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
100 TunnelStateCache tunnelStateCache,
101 DirectTunnelUtils directTunnelUtils,
102 OfEndPointCache ofEndPointCache,
104 TombstonedNodeManager tombstonedNodeManager) {
105 this.dataBroker = dataBroker;
106 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
107 this.jobCoordinator = jobCoordinator;
108 this.tunnelMonitoringConfig = tunnelMonitoringConfig;
109 this.interfaceManager = interfaceManager;
110 this.dpnTepStateCache = dpnTepStateCache;
111 this.ovsBridgeEntryCache = ovsBridgeEntryCache;
112 this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
113 this.tunnelStateCache = tunnelStateCache;
114 this.directTunnelUtils = directTunnelUtils;
115 this.ofEndPointCache = ofEndPointCache;
116 this.itmConfig = itmConfig;
117 this.tombstonedNodeManager = tombstonedNodeManager;
120 @SuppressWarnings("checkstyle:IllegalCatch")
121 public List<ListenableFuture<Void>> deleteTunnels(IMdsalApiManager mdsalManager,
122 Collection<DPNTEPsInfo> dpnTepsList, Collection<DPNTEPsInfo> meshedDpnList) {
123 LOG.trace("TEPs to be deleted {} " , dpnTepsList);
124 return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
125 if (dpnTepsList == null || dpnTepsList.size() == 0) {
126 LOG.debug("no vtep to delete");
130 if (meshedDpnList == null || meshedDpnList.size() == 0) {
131 LOG.debug("No Meshed Vteps");
134 for (DPNTEPsInfo srcDpn : dpnTepsList) {
135 LOG.trace("Processing srcDpn {}", srcDpn);
137 List<TunnelEndPoints> meshedEndPtCache = ItmUtils.getTEPsForDpn(srcDpn.getDPNID(), meshedDpnList);
138 if (meshedEndPtCache == null) {
139 LOG.debug("No Tunnel End Point configured for this DPN {}", srcDpn.getDPNID());
142 LOG.debug("Entries in meshEndPointCache {} for DPN Id{} ", meshedEndPtCache.size(), srcDpn.getDPNID());
143 for (TunnelEndPoints srcTep : srcDpn.nonnullTunnelEndPoints()) {
144 LOG.trace("Processing srcTep {}", srcTep);
145 Boolean isDpnTombstoned = tombstonedNodeManager.isDpnTombstoned(srcDpn.getDPNID());
146 List<TzMembership> srcTZones = srcTep.nonnullTzMembership();
147 boolean tepDeleteFlag = false;
148 // First, take care of tunnel removal, so run through all other DPNS other than srcDpn
149 // In the tep received from Delete DCN, the membership list will always be 1
150 // as the DCN is at transport zone level
151 // Hence if a tunnel is shared across TZs, compare the original membership list between end points
152 // to decide if tunnel to be deleted.
153 for (DPNTEPsInfo dstDpn : meshedDpnList) {
154 if (!Objects.equals(srcDpn.getDPNID(), dstDpn.getDPNID())) {
155 for (TunnelEndPoints dstTep : dstDpn.nonnullTunnelEndPoints()) {
156 if (!ItmUtils.getIntersection(dstTep.nonnullTzMembership(), srcTZones).isEmpty()) {
157 List<TzMembership> originalTzMembership =
158 ItmUtils.getOriginalTzMembership(srcTep, srcDpn.getDPNID(), meshedDpnList);
159 if (ItmUtils.getIntersection(dstTep.getTzMembership(),
160 originalTzMembership).size() == 1) {
161 if (interfaceManager.isItmDirectTunnelsEnabled()) {
162 if (checkIfTepInterfaceExists(dstDpn.getDPNID(), srcDpn.getDPNID())) {
163 // remove all trunk interfaces
164 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
165 + "Destination TEP {} " ,srcTep , dstTep);
166 removeTunnelInterfaceFromOvsdb(tx, srcTep, dstTep, srcDpn.getDPNID(),
168 if (isDpnTombstoned) {
169 LOG.trace("Removing tunnelState entry for {} while tombstoned "
170 + "is set {}", srcDpn.getDPNID(), isDpnTombstoned);
171 removeTunnelState(srcTep,dstTep);
175 if (checkIfTrunkExists(dstDpn.getDPNID(), srcDpn.getDPNID(),
176 srcTep.getTunnelType(), dataBroker)) {
177 // remove all trunk interfaces
178 LOG.trace("Invoking removeTrunkInterface between source TEP {} , "
179 + "Destination TEP {} ", srcTep, dstTep);
180 removeTrunkInterface(tx, srcTep, dstTep, srcDpn.getDPNID(),
190 for (DPNTEPsInfo dstDpn : meshedDpnList) {
191 // Second, take care of Tep TZ membership and identify if tep can be removed
192 if (Objects.equals(srcDpn.getDPNID(), dstDpn.getDPNID())) {
193 // Same DPN, so remove the TZ membership
194 for (TunnelEndPoints dstTep : dstDpn.nonnullTunnelEndPoints()) {
195 if (Objects.equals(dstTep.getIpAddress(), srcTep.getIpAddress())) {
196 // Remove the deleted TZ membership from the TEP
197 LOG.debug("Removing TZ list {} from Existing TZ list {} ", srcTZones,
198 dstTep.getTzMembership());
199 List<TzMembership> updatedList =
200 ItmUtils.removeTransportZoneMembership(dstTep, srcTZones);
201 if (updatedList.isEmpty()) {
202 LOG.debug(" This TEP can be deleted {}", srcTep);
203 tepDeleteFlag = true;
205 TunnelEndPointsBuilder modifiedTepBld = new TunnelEndPointsBuilder(dstTep);
206 modifiedTepBld.setTzMembership(updatedList);
207 TunnelEndPoints modifiedTep = modifiedTepBld.build() ;
208 InstanceIdentifier<TunnelEndPoints> tepPath = InstanceIdentifier
209 .builder(DpnEndpoints.class)
210 .child(DPNTEPsInfo.class, dstDpn.key())
211 .child(TunnelEndPoints.class, dstTep.key()).build();
213 LOG.debug(" Store the modified Tep in DS {} ", modifiedTep);
214 tx.put(tepPath, modifiedTep);
221 // Third, removing vtep / dpn from Tunnels OpDs.
222 InstanceIdentifier<TunnelEndPoints> tepPath =
223 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
224 .child(TunnelEndPoints.class, srcTep.key()).build();
226 LOG.trace("Tep Removal of TEP {} from DPNTEPSINFO CONFIG DS with Key {} ", srcTep,
229 // remove the tep from the cache
230 meshedEndPtCache.remove(srcTep);
231 Class<? extends TunnelMonitoringTypeBase> monitorProtocol =
232 tunnelMonitoringConfig.getMonitorProtocol();
233 InstanceIdentifier<DPNTEPsInfo> dpnPath =
234 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.key())
237 if (meshedEndPtCache.isEmpty()) {
238 // remove dpn if no vteps exist on dpn
239 if (monitorProtocol.isAssignableFrom(TunnelMonitoringTypeLldp.class)) {
240 LOG.debug("Removing Terminating Service Table Flow ");
241 ItmUtils.removeTerminatingServiceTable(tx, srcDpn.getDPNID(), mdsalManager);
243 LOG.trace("DPN Removal from DPNTEPSINFO CONFIG DS {}", srcDpn.getDPNID());
245 InstanceIdentifier<DpnEndpoints> tnlContainerPath =
246 InstanceIdentifier.builder(DpnEndpoints.class).build();
247 Optional<DpnEndpoints> containerOptional = tx.read(tnlContainerPath).get();
248 // remove container if no DPNs are present
249 if (containerOptional.isPresent()) {
250 DpnEndpoints deps = containerOptional.get();
251 if (deps.getDPNTEPsInfo() == null || deps.getDPNTEPsInfo().isEmpty()) {
252 LOG.trace("Container Removal from DPNTEPSINFO CONFIG DS");
253 tx.delete(tnlContainerPath);
258 if (interfaceManager.isItmDirectTunnelsEnabled()) {
259 // SF419 Remove the DPNSTEPs DS
260 LOG.debug("Deleting TEP Interface information from Config datastore with DPNs-Teps "
261 + "for source Dpn {}", srcDpn.getDPNID());
262 // Clean up the DPN TEPs State DS
263 dpnTepStateCache.removeTepFromDpnTepInterfaceConfigDS(srcDpn.getDPNID());
270 private void removeTrunkInterface(TypedWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
271 TunnelEndPoints dstTep, Uint64 srcDpnId, Uint64 dstDpnId) {
272 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
273 srcTep.getIpAddress().stringValue(),
274 dstTep.getIpAddress().stringValue(),
275 srcTep.getTunnelType().getName());
276 LOG.trace("Removing forward Trunk Interface {}" , trunkfwdIfName);
277 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkfwdIfName);
278 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
279 trunkfwdIfName, trunkIdentifier) ;
280 tx.delete(trunkIdentifier);
281 ItmUtils.ITM_CACHE.removeInterface(trunkfwdIfName);
282 // also update itm-state ds -- Delete the forward tunnel-interface from the tunnel list
283 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
284 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, srcTep.getTunnelType()));
286 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkfwdIfName);
287 // Release the Ids for the forward trunk interface Name
288 ItmUtils.releaseIdForTrunkInterfaceName(srcTep.getInterfaceName(),
289 srcTep.getIpAddress().stringValue(),
290 dstTep.getIpAddress().stringValue(),
291 srcTep.getTunnelType().getName());
292 removeLogicalGroupTunnel(srcDpnId, dstDpnId);
294 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
295 dstTep.getIpAddress().stringValue(),
296 srcTep.getIpAddress().stringValue(),
297 srcTep.getTunnelType().getName());
298 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
299 trunkIdentifier = ItmUtils.buildId(trunkRevIfName);
300 LOG.debug(" Removing Trunk Interface Name - {} , Id - {} from Config DS ",
301 trunkRevIfName, trunkIdentifier) ;
302 tx.delete(trunkIdentifier);
303 ItmUtils.ITM_CACHE.removeInternalTunnel(trunkRevIfName);
304 // also update itm-state ds -- Delete the reverse tunnel-interface from the tunnel list
305 path = InstanceIdentifier.create(TunnelList.class)
306 .child(InternalTunnel.class, new InternalTunnelKey(srcDpnId, dstDpnId, dstTep.getTunnelType()));
309 // Release the Ids for the reverse trunk interface Name
310 ItmUtils.releaseIdForTrunkInterfaceName(dstTep.getInterfaceName(),
311 dstTep.getIpAddress().stringValue(),
312 srcTep.getIpAddress().stringValue(),
313 dstTep.getTunnelType().getName());
314 removeLogicalGroupTunnel(dstDpnId, srcDpnId);
317 private static boolean checkIfTrunkExists(Uint64 srcDpnId, Uint64 dstDpnId,
318 Class<? extends TunnelTypeBase> tunType, DataBroker dataBroker) {
319 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
320 .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, tunType));
321 return ItmUtils.read(LogicalDatastoreType.CONFIGURATION,path, dataBroker).isPresent();
324 private void removeLogicalGroupTunnel(Uint64 srcDpnId, Uint64 dstDpnId) {
325 boolean tunnelAggregationEnabled = ItmTunnelAggregationHelper.isTunnelAggregationEnabled();
326 if (!tunnelAggregationEnabled) {
329 String logicTunnelName = ItmUtils.getLogicalTunnelGroupName(srcDpnId, dstDpnId);
330 ItmTunnelAggregationDeleteWorker addWorker =
331 new ItmTunnelAggregationDeleteWorker(logicTunnelName, srcDpnId, dstDpnId, dataBroker);
332 jobCoordinator.enqueueJob(logicTunnelName, addWorker);
335 private static class ItmTunnelAggregationDeleteWorker implements Callable<List<ListenableFuture<Void>>> {
337 private final String logicTunnelName;
338 private final Uint64 srcDpnId;
339 private final Uint64 dstDpnId;
340 private final ManagedNewTransactionRunner txRunner;
342 ItmTunnelAggregationDeleteWorker(String groupName, Uint64 srcDpnId, Uint64 dstDpnId, DataBroker db) {
343 this.logicTunnelName = groupName;
344 this.srcDpnId = srcDpnId;
345 this.dstDpnId = dstDpnId;
346 this.txRunner = new ManagedNewTransactionRunnerImpl(db);
350 public List<ListenableFuture<Void>> call() {
351 Collection<InternalTunnel> tunnels = ItmUtils.ITM_CACHE.getAllInternalTunnel();
353 //The logical tunnel interface be removed only when the last tunnel interface on each OVS is deleted
354 boolean emptyTunnelGroup = true;
355 boolean foundLogicGroupIface = false;
356 for (InternalTunnel tunl : tunnels) {
357 if (Objects.equals(tunl.getSourceDPN(), srcDpnId) && Objects.equals(tunl.getDestinationDPN(),
359 if (tunl.getTransportType() != null && tunl.getTransportType().isAssignableFrom(
360 TunnelTypeVxlan.class)
361 && tunl.getTunnelInterfaceNames() != null && !tunl.getTunnelInterfaceNames().isEmpty()) {
362 emptyTunnelGroup = false;
364 } else if (tunl.getTransportType() != null && tunl.getTransportType().isAssignableFrom(
365 TunnelTypeLogicalGroup.class)) {
366 foundLogicGroupIface = true;
370 if (emptyTunnelGroup && foundLogicGroupIface) {
371 return singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
372 LOG.debug("MULTIPLE_VxLAN_TUNNELS: remove the logical tunnel group {} because a last tunnel"
373 + " interface on srcDpnId {} dstDpnId {} is removed", logicTunnelName, srcDpnId, dstDpnId);
374 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(logicTunnelName);
375 tx.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
376 ItmUtils.ITM_CACHE.removeInterface(logicTunnelName);
377 InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(TunnelList.class)
378 .child(InternalTunnel.class,
379 new InternalTunnelKey(dstDpnId, srcDpnId, TunnelTypeLogicalGroup.class));
380 tx.delete(LogicalDatastoreType.CONFIGURATION, path);
381 ItmUtils.ITM_CACHE.removeInternalTunnel(logicTunnelName);
383 } else if (!emptyTunnelGroup) {
384 LOG.debug("MULTIPLE_VxLAN_TUNNELS: not last tunnel in logical tunnel group {}", logicTunnelName);
386 return Collections.emptyList();
390 private void removeTunnelInterfaceFromOvsdb(TypedReadWriteTransaction<Configuration> tx, TunnelEndPoints srcTep,
391 TunnelEndPoints dstTep, Uint64 srcDpnId, Uint64 dstDpnId) {
392 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
393 srcTep.getIpAddress().getIpv4Address().getValue(),
394 dstTep.getIpAddress().getIpv4Address().getValue(),
395 srcTep.getTunnelType().getName());
396 LOG.trace("Removing forward Trunk Interface {}", trunkfwdIfName);
397 ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(srcDpnId).build();
398 Interface iface = dpnTepStateCache.getInterfaceFromCache(trunkfwdIfName);
399 // ITM DIRECT TUNNELS -- Call the OVS Worker directly
402 removeConfiguration(tx, iface, parentRefs);
403 } catch (ExecutionException | InterruptedException | OperationFailedException e) {
404 LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", iface.getName(), e);
407 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
408 dstTep.getIpAddress().getIpv4Address().getValue(),
409 srcTep.getIpAddress().getIpv4Address().getValue(),
410 srcTep.getTunnelType().getName());
411 parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dstDpnId).build();
412 iface = dpnTepStateCache.getInterfaceFromCache(trunkRevIfName);
416 LOG.trace("Removing Reverse Trunk Interface {}", trunkRevIfName);
417 removeConfiguration(tx, iface, parentRefs);
418 } catch (ExecutionException | InterruptedException | OperationFailedException e) {
419 LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", iface.getName(), e);
424 private void removeTunnelState(TunnelEndPoints srcTep, TunnelEndPoints dstTep) {
425 String trunkfwdIfName = ItmUtils.getTrunkInterfaceName(srcTep.getInterfaceName(),
426 srcTep.getIpAddress().getIpv4Address().getValue(),
427 dstTep.getIpAddress().getIpv4Address().getValue(),
428 srcTep.getTunnelType().getName());
429 LOG.trace("Removing tunnelstate for {}", trunkfwdIfName);
430 directTunnelUtils.deleteTunnelStateEntry(trunkfwdIfName);
432 String trunkRevIfName = ItmUtils.getTrunkInterfaceName(dstTep.getInterfaceName(),
433 dstTep.getIpAddress().getIpv4Address().getValue(),
434 srcTep.getIpAddress().getIpv4Address().getValue(),
435 srcTep.getTunnelType().getName());
436 LOG.trace("Removing tunnelstate for {}", trunkRevIfName);
437 directTunnelUtils.deleteTunnelStateEntry(trunkRevIfName);
440 private boolean checkIfTepInterfaceExists(Uint64 srcDpnId, Uint64 dstDpnId) {
441 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepStateCache.getDpnTepInterface(srcDpnId, dstDpnId);
442 if (dpnTepInterfaceInfo != null) {
443 return dpnTepInterfaceInfo.getTunnelName() != null;
448 private void removeConfiguration(TypedReadWriteTransaction<Configuration> tx, Interface interfaceOld,
449 ParentRefs parentRefs) throws ExecutionException, InterruptedException, OperationFailedException {
450 IfTunnel ifTunnel = interfaceOld.augmentation(IfTunnel.class);
451 if (ifTunnel != null) {
452 // Check if the same transaction can be used across Config and operational shards
453 removeTunnelConfiguration(tx, parentRefs, interfaceOld.getName(), ifTunnel);
457 private void removeTunnelConfiguration(TypedReadWriteTransaction<Configuration> tx, ParentRefs parentRefs,
458 String interfaceName, IfTunnel ifTunnel)
459 throws ExecutionException, InterruptedException, OperationFailedException {
461 LOG.info("removing tunnel configuration for {}", interfaceName);
463 if (parentRefs != null) {
464 dpId = parentRefs.getDatapathNodeIdentifier();
471 OvsdbBridgeRef ovsdbBridgeRef = getOvsdbBridgeRef(dpId);
472 Optional<OvsBridgeEntry> ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
474 // delete bridge to tunnel interface mappings
475 OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpId);
476 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid =
477 DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey);
480 if (ovsBridgeEntryOptional.isPresent()) {
481 List<OvsBridgeTunnelEntry> bridgeTunnelEntries = ovsBridgeEntryOptional.get().nonnullOvsBridgeTunnelEntry();
483 if (ovsdbBridgeRef != null) {
484 if (!itmConfig.isUseOfTunnels()) {
485 removeTerminationEndPoint(ovsdbBridgeRef.getValue(), interfaceName);
486 } else if (bridgeTunnelEntries.size() <= 1) {
487 removeTerminationEndPoint(ovsdbBridgeRef.getValue(), ofEndPointCache.get(dpId));
488 ofEndPointCache.remove(dpId);
492 deleteBridgeInterfaceEntry(bridgeEntryKey, bridgeTunnelEntries, bridgeEntryIid, interfaceName);
493 // IfIndex needs to be removed only during State Clean up not Config
496 directTunnelUtils.deleteTunnelStateEntry(interfaceName);
497 // delete tunnel ingress flow
498 removeTunnelIngressFlow(tx, interfaceName, dpId);
499 directTunnelUtils.removeTunnelEgressFlow(tx, dpId, interfaceName);
500 cleanUpInterfaceWithUnknownState(interfaceName, parentRefs, ifTunnel);
501 directTunnelUtils.removeLportTagInterfaceMap(interfaceName);
504 private OvsdbBridgeRef getOvsdbBridgeRef(Uint64 dpId) throws ReadFailedException {
505 Optional<OvsBridgeRefEntry> ovsBridgeRefEntryOptional = ovsBridgeRefEntryCache.get(dpId);
506 Optional<OvsBridgeEntry> ovsBridgeEntryOptional;
507 OvsdbBridgeRef ovsdbBridgeRef = null;
508 if (ovsBridgeRefEntryOptional.isPresent()) {
509 ovsdbBridgeRef = ovsBridgeRefEntryOptional.get().getOvsBridgeReference();
511 ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId);
512 if (ovsBridgeEntryOptional.isPresent()) {
513 ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference();
516 return ovsdbBridgeRef;
519 private void removeTerminationEndPoint(InstanceIdentifier<?> bridgeIid, String interfaceName) {
520 LOG.debug("removing termination point for {}", interfaceName);
521 InstanceIdentifier<TerminationPoint> tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier(
522 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceName);
523 ITMBatchingUtils.delete(tpIid, ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
526 private void removeTunnelIngressFlow(TypedReadWriteTransaction<Configuration> tx, String interfaceName,
527 Uint64 dpId) throws ExecutionException, InterruptedException {
528 directTunnelUtils.removeTunnelIngressFlow(tx, dpId, interfaceName);
531 // if the node is shutdown, there will be stale interface state entries,
532 // with unknown op-state, clear them.
533 private void cleanUpInterfaceWithUnknownState(String interfaceName, ParentRefs parentRefs, IfTunnel ifTunnel)
534 throws ReadFailedException {
535 Optional<StateTunnelList> stateTunnelList =
536 tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
537 if (stateTunnelList.isPresent() && stateTunnelList.get().getOperState() == TunnelOperStatus.Unknown) {
538 String staleInterface = ifTunnel != null ? interfaceName : parentRefs.getParentInterface();
539 LOG.debug("cleaning up parent-interface for {}, since the oper-status is UNKNOWN", interfaceName);
540 directTunnelUtils.deleteTunnelStateEntry(staleInterface);
544 private void deleteBridgeInterfaceEntry(OvsBridgeEntryKey bridgeEntryKey,
545 List<OvsBridgeTunnelEntry> bridgeTunnelEntries,
546 InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid,
547 String interfaceName) {
548 OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(interfaceName);
549 InstanceIdentifier<OvsBridgeTunnelEntry> bridgeTunnelEntryIid =
550 DirectTunnelUtils.getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey);
551 ITMBatchingUtils.delete(bridgeTunnelEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
552 if (bridgeTunnelEntries.size() <= 1) {
553 ITMBatchingUtils.delete(bridgeEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);