From: Apurba Mukherjee Date: Tue, 7 Jul 2020 16:16:52 +0000 (+0530) Subject: OF port deletion complete implementation X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=a54cd97b399d6e9e7b939f1a0fe6b00be050f03b;p=genius.git OF port deletion complete implementation Change-Id: I485909dd804b049808366c0374a35a3a41511f0e Signed-off-by: Apurba Mukherjee --- diff --git a/interfacemanager/interfacemanager-api/src/main/java/org/opendaylight/genius/interfacemanager/interfaces/IInterfaceManager.java b/interfacemanager/interfacemanager-api/src/main/java/org/opendaylight/genius/interfacemanager/interfaces/IInterfaceManager.java index 9b92e748f..7f405094e 100644 --- a/interfacemanager/interfacemanager-api/src/main/java/org/opendaylight/genius/interfacemanager/interfaces/IInterfaceManager.java +++ b/interfacemanager/interfacemanager-api/src/main/java/org/opendaylight/genius/interfacemanager/interfaces/IInterfaceManager.java @@ -195,4 +195,13 @@ public interface IInterfaceManager { Map getBridgeRefEntryMap(); boolean isItmOfTunnelsEnabled(); + + void addInternalTunnelToCache(String tunnelName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang + .ietf.interfaces.rev140508.interfaces.state.Interface iface); + + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface + getInternalTunnelCacheInfo(String tunnelName); + + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface + removeInternalTunnelFromCache(String tunnelName); } diff --git a/interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/InterfacemgrProvider.java b/interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/InterfacemgrProvider.java index 227a274c6..1cac89ef9 100644 --- a/interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/InterfacemgrProvider.java +++ b/interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/InterfacemgrProvider.java @@ -32,6 +32,7 @@ import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExist import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo; import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceAdminState; import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; +import org.opendaylight.genius.interfacemanager.listeners.InternalTunnelCache; import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils; import org.opendaylight.genius.interfacemanager.rpcservice.InterfaceManagerRpcService; import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils; @@ -119,6 +120,7 @@ public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager { private Map, OvsdbBridgeAugmentation> nodeIidToBridgeMap; private EntityOwnershipCandidateRegistration configEntityCandidate; private EntityOwnershipCandidateRegistration bindingEntityCandidate; + private InternalTunnelCache internalTunnelCache; @Inject public InterfacemgrProvider(@Reference final DataBroker dataBroker, @@ -129,7 +131,8 @@ public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager { final InterfaceManagerCommonUtils interfaceManagerCommonUtils, final InterfaceMetaUtils interfaceMetaUtils, final IfmConfig ifmConfig, - final IfmDiagStatusProvider ifmStatusProvider) { + final IfmDiagStatusProvider ifmStatusProvider, + final InternalTunnelCache internalTunnelCache) { this.dataBroker = dataBroker; this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); this.entityOwnershipService = entityOwnershipService; @@ -140,6 +143,7 @@ public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager { this.interfaceMetaUtils = interfaceMetaUtils; this.ifmConfig = ifmConfig; this.ifmStatusProvider = ifmStatusProvider; + this.internalTunnelCache = internalTunnelCache; start(); } @@ -899,4 +903,22 @@ public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager { public boolean isItmOfTunnelsEnabled() { return ifmConfig.isItmOfTunnels(); } + + @Override + public void addInternalTunnelToCache(String tunnelName, org.opendaylight.yang.gen.v1.urn.ietf.params + .xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface iface) { + internalTunnelCache.add(tunnelName,iface); + } + + @Override + public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces + .rev140508.interfaces.state.Interface getInternalTunnelCacheInfo(String tunnelName) { + return internalTunnelCache.get(tunnelName); + } + + @Override + public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces + .rev140508.interfaces.state.Interface removeInternalTunnelFromCache(String tunnelName) { + return internalTunnelCache.remove(tunnelName); + } } diff --git a/interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/listeners/InternalTunnelCache.java b/interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/listeners/InternalTunnelCache.java new file mode 100644 index 000000000..a43ea0a53 --- /dev/null +++ b/interfacemanager/interfacemanager-impl/src/main/java/org/opendaylight/genius/interfacemanager/listeners/InternalTunnelCache.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.genius.interfacemanager.listeners; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import javax.inject.Singleton; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; + + +@Singleton +public class InternalTunnelCache { + + private volatile ConcurrentMap internalTunnelCache = new ConcurrentHashMap<>(); + + public synchronized void add(String tunnelName, Interface iface) { + internalTunnelCache.putIfAbsent(tunnelName, iface); + } + + public synchronized Interface get(String tunnelName) { + return internalTunnelCache.get(tunnelName); + } + + public synchronized Interface remove(String tunnelName) { + return internalTunnelCache.remove(tunnelName); + } +} diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/OfTepStateCache.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/OfTepStateCache.java index e89e94d65..1fbed8d9e 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/OfTepStateCache.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/OfTepStateCache.java @@ -14,11 +14,17 @@ import javax.inject.Inject; import javax.inject.Singleton; import org.opendaylight.genius.infra.ManagedNewTransactionRunner; import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; +import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; +import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils; import org.opendaylight.genius.itm.servicebinding.BindServiceUtils; +import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.genius.mdsalutil.cache.DataObjectCache; import org.opendaylight.infrautils.caches.CacheProvider; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.OfTepsState; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTepKey; @@ -31,22 +37,45 @@ import org.slf4j.LoggerFactory; public class OfTepStateCache extends DataObjectCache { private final ManagedNewTransactionRunner txRunner; + private final IInterfaceManager interfaceManager; + private final DirectTunnelUtils directTunnelUtils; List> futures = new ArrayList<>(); private static final Logger LOG = LoggerFactory.getLogger(OfTepStateCache.class); @Inject - public OfTepStateCache(DataBroker dataBroker, CacheProvider cacheProvider) { + public OfTepStateCache(DataBroker dataBroker, CacheProvider cacheProvider, + IInterfaceManager interfaceManager, DirectTunnelUtils directTunnelUtils) { super(OfTep.class, dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(OfTepsState.class).child(OfTep.class).build(), cacheProvider, (iid, ofTepList) -> ofTepList.getOfPortName(), ofPortName -> InstanceIdentifier.builder(OfTepsState.class) .child(OfTep.class, new OfTepKey(ofPortName)).build()); + this.interfaceManager = interfaceManager; + this.directTunnelUtils = directTunnelUtils; this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); } protected void added(InstanceIdentifier path, OfTep ofTep) { - LOG.info("Binding default egress dispatcher service for{}", ofTep.getOfPortName()); - BindServiceUtils.bindDefaultEgressDispatcherService(txRunner, futures, "VXLAN_TRUNK_INTERFACE", - String.valueOf(ofTep.getPortNumber()), ofTep.getOfPortName(), - ofTep.getIfIndex()); + LOG.debug("Adding interface name to internal cache."); + List childLowerLayerIfList = new ArrayList<>(); + String lowref = MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + ofTep.getSourceDpnId() + + MDSALUtil.SEPARATOR + ofTep.getPortNumber(); + childLowerLayerIfList.add(0, lowref); + InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setIfIndex(ofTep.getIfIndex().intValue()) + .withKey(new InterfaceKey(ofTep.getOfPortName())) + .setLowerLayerIf(childLowerLayerIfList).setType(Tunnel.class) + .setName(ofTep.getOfPortName()); + interfaceManager.addInternalTunnelToCache(ofTep.getOfPortName(), ifaceBuilder.build()); + + if (directTunnelUtils.isEntityOwner()) { + LOG.info("Binding default egress dispatcher service for{}", ofTep.getOfPortName()); + BindServiceUtils.bindDefaultEgressDispatcherService(txRunner, futures, "VXLAN_TRUNK_INTERFACE", + String.valueOf(ofTep.getPortNumber()), ofTep.getOfPortName(), + ofTep.getIfIndex()); + } + } + + protected void removed(InstanceIdentifier path, OfTep ofTep) { + BindServiceUtils.unbindService(futures, txRunner, ofTep.getOfPortName()); + interfaceManager.removeInternalTunnelFromCache(ofTep.getOfPortName()); } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelAddWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelAddWorker.java index 4eb7376f5..5eebf4fdf 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelAddWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelAddWorker.java @@ -12,10 +12,11 @@ import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION; import com.google.common.util.concurrent.ListenableFuture; import java.time.Duration; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.Callable; @@ -61,6 +62,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.Dpn import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsBuilder; @@ -73,6 +75,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tun import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.OperationFailedException; +import org.opendaylight.yangtools.yang.common.Uint16; import org.opendaylight.yangtools.yang.common.Uint64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -143,10 +146,12 @@ public final class ItmInternalTunnelAddWorker { DirectTunnelUtils directTunnelUtils) throws ExecutionException, InterruptedException, OperationFailedException { LOG.debug("Updating CONFIGURATION datastore with DPN {} ", dpn); InstanceIdentifier dep = InstanceIdentifier.create(DpnEndpoints.class) ; - List dpnList = new ArrayList<>() ; - dpnList.add(new DPNTEPsInfoBuilder(dpn) - .setDstId(directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME, dpn.getDPNID().toString())).build()); - DpnEndpoints tnlBuilder = new DpnEndpointsBuilder().setDPNTEPsInfo(dpnList).build() ; + Map dpnMap = new HashMap<>() ; + DPNTEPsInfo info = new DPNTEPsInfoBuilder(dpn) + .setDstId(directTunnelUtils + .allocateId(ITMConstants.ITM_IDPOOL_NAME, dpn.getDPNID().toString())).build(); + dpnMap.put(info.key(), info); + DpnEndpoints tnlBuilder = new DpnEndpointsBuilder().setDPNTEPsInfo(dpnMap).build() ; tx.merge(dep, tnlBuilder); } @@ -342,42 +347,36 @@ public final class ItmInternalTunnelAddWorker { + " destination IP - {} gateway IP - {}", trunkInterfaceName, parentInterfaceName, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress) ; - boolean useOfTunnel = itmCfg.isUseOfTunnels(); + //boolean useOfTunnel = itmCfg.isUseOfTunnels(); List tunOptions = ItmUtils.buildTunnelOptions(srcte, itmCfg); Boolean isMonitorEnabled = !tunType.isAssignableFrom(TunnelTypeLogicalGroup.class) && isTunnelMonitoringEnabled; Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName, trunkInterfaceDecription(ItmUtils.convertTunnelTypetoString(srcte.getTunnelType())), true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), true, - isMonitorEnabled, monitorProtocol, monitorInterval, useOfTunnel, parentInterfaceName, tunOptions); + isMonitorEnabled, monitorProtocol, monitorInterval, false, parentInterfaceName, tunOptions); LOG.debug("Trunk Interface builder - {} ", iface); final DpnTepsStateBuilder dpnTepsStateBuilder = new DpnTepsStateBuilder(); final DpnsTepsBuilder dpnsTepsBuilder = new DpnsTepsBuilder(); - final List dpnTeps = new ArrayList<>(); - final List remoteDpns = new ArrayList<>(); - String ofTunnelPortName = null; + final Map dpnTeps = new HashMap<>(); + final Map remoteDpns = new HashMap<>(); dpnsTepsBuilder.withKey(new DpnsTepsKey(srcDpnId)); dpnsTepsBuilder.setTunnelType(srcte.getTunnelType()); dpnsTepsBuilder.setSourceDpnId(srcDpnId); - if (useOfTunnel) { - String tunnelType = ItmUtils.convertTunnelTypetoString(srcte.getTunnelType()); - ofTunnelPortName = DirectTunnelUtils.generateOfPortName(srcDpnId, tunnelType); - dpnsTepsBuilder.setOfTunnel(ofTunnelPortName); - } RemoteDpnsBuilder remoteDpn = new RemoteDpnsBuilder(); remoteDpn.withKey(new RemoteDpnsKey(dstDpnId)); remoteDpn.setDestinationDpnId(dstDpnId); remoteDpn.setTunnelName(trunkInterfaceName); remoteDpn.setMonitoringEnabled(isTunnelMonitoringEnabled); - remoteDpn.setMonitoringInterval(monitorInterval); + remoteDpn.setMonitoringInterval(Uint16.valueOf(monitorInterval)); remoteDpn.setInternal(true); - remoteDpns.add(remoteDpn.build()); + remoteDpns.put(remoteDpn.key(),remoteDpn.build()); dpnsTepsBuilder.setRemoteDpns(remoteDpns); - dpnTeps.add(dpnsTepsBuilder.build()); + dpnTeps.put(dpnsTepsBuilder.key(), dpnsTepsBuilder.build()); dpnTepsStateBuilder.setDpnsTeps(dpnTeps); updateDpnTepInterfaceInfoToConfig(dpnTepsStateBuilder.build()); - addTunnelConfiguration(iface, ofTunnelPortName); + addTunnelConfiguration(iface, iface.getName()); } private static void updateDpnTepInterfaceInfoToConfig(DpnTepsState dpnTeps) { @@ -386,13 +385,13 @@ public final class ItmInternalTunnelAddWorker { ITMBatchingUtils.updateContainer(dpnTepsII, dpnTeps, ITMBatchingUtils.EntityType.DEFAULT_CONFIG); } - private void addTunnelConfiguration(Interface iface, String ofTunnelPortName) - throws ReadFailedException { + private void addTunnelConfiguration(Interface iface, String tunnelName) + throws ReadFailedException { // ITM Direct Tunnels This transaction is not being used -- CHECK ParentRefs parentRefs = iface.augmentation(ParentRefs.class); if (parentRefs == null) { LOG.warn("ParentRefs for interface: {} Not Found. Creation of Tunnel OF-Port not supported" - + " when dpid not provided.", iface.getName()); + + " when dpid not provided.", tunnelName); return; } @@ -402,45 +401,39 @@ public final class ItmInternalTunnelAddWorker { iface.getName()); return; } - String tunnelName = ofTunnelPortName != null ? ofTunnelPortName : iface.getName(); // create bridge on switch, if switch is connected - Optional ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(dpId); LOG.info("adding tunnel port configuration for tunnelName: {}", tunnelName); - if (createTunnelPort(dpId)) { - LOG.debug("creating dpn tunnel mapping for dpn: {} tunnelName: {}", dpId, tunnelName); - DirectTunnelUtils.createBridgeTunnelEntryInConfigDS(dpId, iface.getName()); - if (ofTunnelPortName != null) { - ofEndPointCache.add(dpId, tunnelName); - } - if (ovsBridgeRefEntry.isPresent()) { - LOG.debug("creating bridge interface on dpn {}", dpId); - InstanceIdentifier bridgeIid = - (InstanceIdentifier) ovsBridgeRefEntry.get() - .getOvsBridgeReference().getValue(); - LOG.debug("adding port to the bridge:{} tunnelName: {}", bridgeIid, tunnelName); - addPortToBridge(bridgeIid, iface, tunnelName); - } else { - LOG.debug("Bridge not found. Registering Eventcallback for dpid {}", dpId); - - InstanceIdentifier bridgeRefEntryFromDS = - InstanceIdentifier.builder(OvsBridgeRefInfo.class) - .child(OvsBridgeRefEntry.class, new OvsBridgeRefEntryKey(dpId)).build(); - - eventCallbacks.onAdd(LogicalDatastoreType.OPERATIONAL, bridgeRefEntryFromDS, (refEntryIid) -> { - addPortToBridgeOnCallback(iface, tunnelName, refEntryIid); - return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER; - }, Duration.ofMillis(5000), (id) -> { - try { - Optional ovsBridgeRefEntryOnCallback = ovsBridgeRefEntryCache.get(dpId); - InstanceIdentifier bridgeIidOnCallback = - (InstanceIdentifier) ovsBridgeRefEntryOnCallback.get() - .getOvsBridgeReference().getValue(); - addPortToBridge(bridgeIidOnCallback, iface, tunnelName); - } catch (ReadFailedException e) { - LOG.error("Bridge not found in DS/cache for dpId {}", dpId); - } - }); - } + LOG.debug("creating dpn tunnel mapping for dpn: {} tunnelName: {}", dpId, tunnelName); + Optional ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(dpId); + DirectTunnelUtils.createBridgeTunnelEntryInConfigDS(dpId, iface.getName()); + if (ovsBridgeRefEntry.isPresent()) { + LOG.debug("creating bridge interface on dpn {}", dpId); + InstanceIdentifier bridgeIid = + (InstanceIdentifier) ovsBridgeRefEntry.get() + .getOvsBridgeReference().getValue(); + LOG.debug("adding port to the bridge:{} tunnelName: {}", bridgeIid, tunnelName); + addPortToBridge(bridgeIid, iface, tunnelName); + } else { + LOG.debug("Bridge not found. Registering Eventcallback for dpid {}", dpId); + + InstanceIdentifier bridgeRefEntryFromDS = + InstanceIdentifier.builder(OvsBridgeRefInfo.class) + .child(OvsBridgeRefEntry.class, new OvsBridgeRefEntryKey(dpId)).build(); + + eventCallbacks.onAdd(LogicalDatastoreType.OPERATIONAL, bridgeRefEntryFromDS, (refEntryIid) -> { + addPortToBridgeOnCallback(iface, tunnelName, refEntryIid); + return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER; + }, Duration.ofMillis(5000), (id) -> { + try { + Optional ovsBridgeRefEntryOnCallback = ovsBridgeRefEntryCache.get(dpId); + InstanceIdentifier bridgeIidOnCallback = + (InstanceIdentifier) ovsBridgeRefEntryOnCallback.get() + .getOvsBridgeReference().getValue(); + addPortToBridge(bridgeIidOnCallback, iface, tunnelName); + } catch (ReadFailedException e) { + LOG.error("Bridge not found in DS/cache for dpId {}", dpId); + } + }); } } @@ -451,13 +444,6 @@ public final class ItmInternalTunnelAddWorker { } } - private boolean createTunnelPort(Uint64 dpId) { - if (!itmCfg.isUseOfTunnels()) { - return true; - } - return ofEndPointCache.get(dpId) == null; - } - private void addPortToBridgeOnCallback(Interface iface, String portName, OvsBridgeRefEntry bridgeRefEntry) { InstanceIdentifier bridgeIid = (InstanceIdentifier) bridgeRefEntry.getOvsBridgeReference().getValue(); diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelDeleteWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelDeleteWorker.java index e09a15772..a330502dd 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelDeleteWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelDeleteWorker.java @@ -23,7 +23,6 @@ import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager; import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; import org.opendaylight.genius.itm.cache.DpnTepStateCache; -import org.opendaylight.genius.itm.cache.OfEndPointCache; import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache; import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache; import org.opendaylight.genius.itm.cache.TunnelStateCache; @@ -51,7 +50,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeLogicalGroup; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry; @@ -91,8 +89,6 @@ public class ItmInternalTunnelDeleteWorker { private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache; private final TunnelStateCache tunnelStateCache; private final DirectTunnelUtils directTunnelUtils; - private final OfEndPointCache ofEndPointCache; - private final ItmConfig itmConfig; private final TombstonedNodeManager tombstonedNodeManager; public ItmInternalTunnelDeleteWorker(DataBroker dataBroker, JobCoordinator jobCoordinator, @@ -102,8 +98,6 @@ public class ItmInternalTunnelDeleteWorker { OvsBridgeRefEntryCache ovsBridgeRefEntryCache, TunnelStateCache tunnelStateCache, DirectTunnelUtils directTunnelUtils, - OfEndPointCache ofEndPointCache, - ItmConfig itmConfig, TombstonedNodeManager tombstonedNodeManager) { this.dataBroker = dataBroker; this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); @@ -115,8 +109,6 @@ public class ItmInternalTunnelDeleteWorker { this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache; this.tunnelStateCache = tunnelStateCache; this.directTunnelUtils = directTunnelUtils; - this.ofEndPointCache = ofEndPointCache; - this.itmConfig = itmConfig; this.tombstonedNodeManager = tombstonedNodeManager; } @@ -136,7 +128,6 @@ public class ItmInternalTunnelDeleteWorker { } for (DPNTEPsInfo srcDpn : dpnTepsList) { LOG.trace("Processing srcDpn {}", srcDpn); - List meshedEndPtCache = ItmUtils.getTEPsForDpn(srcDpn.getDPNID(), meshedDpnList); if (meshedEndPtCache == null) { LOG.debug("No Tunnel End Point configured for this DPN {}", srcDpn.getDPNID()); @@ -471,53 +462,39 @@ public class ItmInternalTunnelDeleteWorker { return; } - OvsdbBridgeRef ovsdbBridgeRef = getOvsdbBridgeRef(dpId); - Optional ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId); + Optional ovsBridgeRefEntryOptional = ovsBridgeRefEntryCache.get(dpId); + Optional ovsBridgeEntryOptional; + OvsdbBridgeRef ovsdbBridgeRef = null; + if (ovsBridgeRefEntryOptional.isPresent()) { + ovsdbBridgeRef = ovsBridgeRefEntryOptional.get().getOvsBridgeReference(); + } else { + ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId); + if (ovsBridgeEntryOptional.isPresent()) { + ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference(); + } + } + + if (ovsdbBridgeRef != null) { + removeTerminationEndPoint(ovsdbBridgeRef.getValue(), interfaceName); + } + removeTunnelIngressFlow(tx, interfaceName, dpId); // delete bridge to tunnel interface mappings OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpId); InstanceIdentifier bridgeEntryIid = DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey); + ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId); if (ovsBridgeEntryOptional.isPresent()) { @NonNull Map bridgeTunnelEntries = ovsBridgeEntryOptional.get().nonnullOvsBridgeTunnelEntry(); - if (ovsdbBridgeRef != null) { - if (!itmConfig.isUseOfTunnels()) { - removeTerminationEndPoint(ovsdbBridgeRef.getValue(), interfaceName); - } else if (bridgeTunnelEntries.size() <= 1) { - removeTerminationEndPoint(ovsdbBridgeRef.getValue(), ofEndPointCache.get(dpId)); - ofEndPointCache.remove(dpId); - } - } - deleteBridgeInterfaceEntry(bridgeEntryKey, bridgeTunnelEntries, bridgeEntryIid, interfaceName); // IfIndex needs to be removed only during State Clean up not Config + cleanUpInterfaceWithUnknownState(interfaceName, parentRefs, ifTunnel); + directTunnelUtils.removeLportTagInterfaceMap(interfaceName); } - - directTunnelUtils.deleteTunnelStateEntry(interfaceName); - // delete tunnel ingress flow - removeTunnelIngressFlow(tx, interfaceName, dpId); - directTunnelUtils.removeTunnelEgressFlow(tx, dpId, interfaceName); - cleanUpInterfaceWithUnknownState(interfaceName, parentRefs, ifTunnel); - directTunnelUtils.removeLportTagInterfaceMap(interfaceName); - } - - private OvsdbBridgeRef getOvsdbBridgeRef(Uint64 dpId) throws ReadFailedException { - Optional ovsBridgeRefEntryOptional = ovsBridgeRefEntryCache.get(dpId); - Optional ovsBridgeEntryOptional; - OvsdbBridgeRef ovsdbBridgeRef = null; - if (ovsBridgeRefEntryOptional.isPresent()) { - ovsdbBridgeRef = ovsBridgeRefEntryOptional.get().getOvsBridgeReference(); - } else { - ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpId); - if (ovsBridgeEntryOptional.isPresent()) { - ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference(); - } - } - return ovsdbBridgeRef; } private void removeTerminationEndPoint(InstanceIdentifier bridgeIid, String interfaceName) { diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfPortRemoveWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfPortRemoveWorker.java index 5d375ba11..3f06baf77 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfPortRemoveWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfPortRemoveWorker.java @@ -9,20 +9,33 @@ package org.opendaylight.genius.itm.confighelpers; import com.google.common.util.concurrent.ListenableFuture; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; -import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTepKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ItmOfPortRemoveWorker implements Callable>> { - public ItmOfPortRemoveWorker(Map oldDpnTepList, DataBroker dataBroker, + + private static final Logger LOG = LoggerFactory.getLogger(ItmOfPortRemoveWorker.class); + + private Map oldDpnTepMap; + private final ItmOfTunnelDeleteWorker itmOfTunnelDeleteWorker; + + public ItmOfPortRemoveWorker(Map oldDpnTepMap, ItmOfTunnelDeleteWorker itmOfTunnelDeleteWorker) { + this.itmOfTunnelDeleteWorker = itmOfTunnelDeleteWorker; + this.oldDpnTepMap = oldDpnTepMap; } @Override - public List> call() throws Exception { - return null; + public List> call() throws Exception { + List> futures = new ArrayList<>(); + futures.addAll(itmOfTunnelDeleteWorker.deleteOfTeps(oldDpnTepMap.values())); + LOG.debug("Invoking OfTep delete method with OfTep list to be deleted {}", oldDpnTepMap.values()); + return futures; } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfTunnelDeleteWorker.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfTunnelDeleteWorker.java index b1ecc3b54..67578bf2a 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfTunnelDeleteWorker.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmOfTunnelDeleteWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -8,16 +8,209 @@ package org.opendaylight.genius.itm.confighelpers; -import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar; +import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION; + +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager; +import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; +import org.opendaylight.genius.itm.cache.OfDpnTepConfigCache; +import org.opendaylight.genius.itm.cache.OfTepStateCache; +import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache; import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache; +import org.opendaylight.genius.itm.impl.ITMBatchingUtils; import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils; -import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; import org.opendaylight.mdsal.binding.api.DataBroker; -import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig; +import org.opendaylight.mdsal.binding.util.Datastore.Configuration; +import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner; +import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl; +import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction; +import org.opendaylight.mdsal.common.api.ReadFailedException; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.OperationFailedException; +import org.opendaylight.yangtools.yang.common.Uint64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ItmOfTunnelDeleteWorker { - public ItmOfTunnelDeleteWorker(DataBroker dataBroker, JobCoordinator jobCoordinator, ItmConfig itmConfig, - DirectTunnelUtils directTunnelUtils, OvsBridgeRefEntryCache ovsBridgeRefEntryCache, - DataTreeEventCallbackRegistrar eventCallbackRegistrar) { + + private static final Logger LOG = LoggerFactory.getLogger(ItmOfTunnelDeleteWorker.class); + private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger"); + + private final ManagedNewTransactionRunner txRunner; + private final DataBroker dataBroker; + private final OfDpnTepConfigCache ofDpnTepConfigCache; + private final TombstonedNodeManager tombstonedNodeManager; + private final IInterfaceManager interfaceManager; + private final DirectTunnelUtils directTunnelUtils; + private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache; + private final OvsBridgeEntryCache ovsBridgeEntryCache; + private final OfTepStateCache ofTepStateCache; + + public ItmOfTunnelDeleteWorker(DataBroker dataBroker, + OfDpnTepConfigCache ofDpnTepConfigCache, + TombstonedNodeManager tombstonedNodeManager, + IInterfaceManager interfaceManager, + DirectTunnelUtils directTunnelUtils, + OvsBridgeRefEntryCache ovsBridgeRefEntryCache, + OvsBridgeEntryCache ovsBridgeEntryCache, + OfTepStateCache ofTepStateCache) { + this.dataBroker = dataBroker; + this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); + this.ofDpnTepConfigCache = ofDpnTepConfigCache; + this.tombstonedNodeManager = tombstonedNodeManager; + this.interfaceManager = interfaceManager; + this.directTunnelUtils = directTunnelUtils; + this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache; + this.ovsBridgeEntryCache = ovsBridgeEntryCache; + this.ofTepStateCache = ofTepStateCache; + } + + @SuppressWarnings("checkstyle:IllegalCatch") + public List> deleteOfTeps(Collection ofTepsList) { + LOG.trace("OFTeps to be deleted {} " , ofTepsList); + return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> { + if (ofTepsList == null || ofTepsList.size() == 0) { + LOG.debug("no ofteps to delete"); + return; + } + + for (OfDpnTep srcDpn : ofTepsList) { + LOG.trace("Processing srcDpn {}", srcDpn); + + Boolean isDpnTombstoned = tombstonedNodeManager.isDpnTombstoned(srcDpn.getSourceDpnId()); + + removeOfTepInterfaceFromOvsdb(srcDpn, tx); + if (isDpnTombstoned) { + EVENT_LOGGER.debug("OfTep-DeleteWorker, Tombstoned, DpnTep for {} removed", + srcDpn.getSourceDpnId()); + LOG.trace("Removing tunnelState entry for {} while tombstoned is set true",srcDpn.getSourceDpnId()); + removeOfTepState(srcDpn); + } + LOG.debug("Deleting OFTEP Interface information from Config datastore with DPNs-Tep " + + "for source Dpn {}", srcDpn.getSourceDpnId()); + // Clean up the DPNs TEP State DS + DirectTunnelUtils.removeOfTepFromDpnsTepConfigDS(dataBroker, srcDpn.getSourceDpnId()); + EVENT_LOGGER.debug("OfTep-DeleteWorker, DpnTep for {} removed", srcDpn.getSourceDpnId()); + } + })); + } + + private void removeOfTepState(OfDpnTep srcDpn) { + LOG.trace("Removing ofTepstate for {} with tomstoned enable", srcDpn.getOfPortName()); + directTunnelUtils.deleteOfTepStateEntry(srcDpn.getOfPortName()); + } + + private void removeOfTepInterfaceFromOvsdb(OfDpnTep dpnTep, TypedReadWriteTransaction tx) { + LOG.trace("Removing ofTep Interface {}", dpnTep.getOfPortName()); + try { + removeConfiguration(dpnTep, tx); + } catch (ExecutionException | InterruptedException | OperationFailedException e) { + LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", dpnTep.getTunnelType(), e); + } + } + + private void removeConfiguration(OfDpnTep dpnsTep, TypedReadWriteTransaction tx) + throws ExecutionException, InterruptedException, OperationFailedException { + // Check if the same transaction can be used across Config and operational shards + removeTunnelConfiguration(dpnsTep, tx); + } + + private void removeTunnelConfiguration(OfDpnTep dpnTep, TypedReadWriteTransaction tx) + throws ExecutionException, InterruptedException, OperationFailedException { + + LOG.info("removing ofTep configuration for {}", dpnTep.getOfPortName()); + + Optional ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(dpnTep.getSourceDpnId()); + Optional ovsBridgeEntryOptional; + OvsdbBridgeRef ovsdbBridgeRef = null; + if (ovsBridgeRefEntry.isPresent()) { + ovsdbBridgeRef = ovsBridgeRefEntry.get().getOvsBridgeReference(); + } else { + ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpnTep.getSourceDpnId()); + if (ovsBridgeEntryOptional.isPresent()) { + ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference(); + } + } + + if (ovsdbBridgeRef != null) { + removeTerminationEndPoint(ovsdbBridgeRef.getValue(), dpnTep.getOfPortName()); + } + + // delete tunnel ingress flow + removeOfPortIngressFlow(tx, dpnTep.getOfPortName(), dpnTep.getSourceDpnId()); + + // delete bridge to tunnel interface mappings + OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpnTep.getSourceDpnId()); + InstanceIdentifier bridgeEntryIid = + DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey); + + ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpnTep.getSourceDpnId()); + if (ovsBridgeEntryOptional.isPresent()) { + Map bridgeTunnelEntries = ovsBridgeEntryOptional + .get().getOvsBridgeTunnelEntry(); + deleteBridgeInterfaceEntry(bridgeEntryKey, + bridgeTunnelEntries.values().stream().collect(Collectors.toList()), + bridgeEntryIid, dpnTep.getOfPortName()); + // IfIndex needs to be removed only during State Clean up not Config + cleanUpOfTepWithUnknownState(dpnTep.getOfPortName(), tx); + directTunnelUtils.removeLportTagInterfaceMap(dpnTep.getOfPortName()); + } + } + + private void removeTerminationEndPoint(InstanceIdentifier bridgeIid, String ofPortName) { + LOG.debug("removing termination point for {}", ofPortName); + InstanceIdentifier tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier( + InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), ofPortName); + ITMBatchingUtils.delete(tpIid, ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG); + } + + private void removeOfPortIngressFlow(TypedReadWriteTransaction tx, + String ofTepName, + Uint64 dpId) throws ExecutionException, InterruptedException { + directTunnelUtils.removeTunnelIngressFlow(tx, dpId, ofTepName); + } + + private void deleteBridgeInterfaceEntry(OvsBridgeEntryKey bridgeEntryKey, + List bridgeTunnelEntries, + InstanceIdentifier bridgeEntryIid, + String ofTepName) { + OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(ofTepName); + InstanceIdentifier bridgeTunnelEntryIid = + DirectTunnelUtils.getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey); + ITMBatchingUtils.delete(bridgeTunnelEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG); + if (bridgeTunnelEntries.size() <= 1) { + ITMBatchingUtils.delete(bridgeEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG); + } + } + + // if the node is shutdown, there will be stale ofTep state entries, + // with unknown op-state, clear them. + private void cleanUpOfTepWithUnknownState(String ofTepName, TypedReadWriteTransaction tx) + throws ReadFailedException { + Optional ofTepList = ofTepStateCache.get(ofTepName); + if (ofTepList.isPresent() && ofTepList.get().getOfTepState() == TunnelOperStatus.Unknown) { + LOG.debug("cleaning up dpnTep for {}, since the oper-status is {}", ofTepName, + ofTepList.get().getOfTepState()); + directTunnelUtils.deleteOfTepStateEntry(ofTepName); + } } + } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/impl/ItmUtils.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/impl/ItmUtils.java index 0dea8af64..5b353bc2e 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/impl/ItmUtils.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/impl/ItmUtils.java @@ -848,14 +848,15 @@ public final class ItmUtils { return TUNNEL_TYPE_MAP.get(tunnelType); } - public static List removeTransportZoneMembership(TunnelEndPoints endPts, Map zones) { + public static List removeTransportZoneMembership(TunnelEndPoints endPts, + Map zones) { LOG.trace(" RemoveTransportZoneMembership TEPs {}, Membership to be removed {} ", endPts, zones); List existingTzList = new ArrayList<>(endPts.nonnullTzMembership().values()); for (TzMembership membership : zones.values()) { - existingTzList.remove(new TzMembershipBuilder().setZoneName(membership.getZoneName()).build()); + existingTzList.remove(membership); } - LOG.debug("Modified Membership List {}", existingTzList); + LOG.debug("Modified Membership Map {}", existingTzList); return existingTzList; } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelInventoryStateListener.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelInventoryStateListener.java index 1c08ebf02..31b14e446 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelInventoryStateListener.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelInventoryStateListener.java @@ -7,6 +7,7 @@ */ package org.opendaylight.genius.itm.itmdirecttunnels.listeners; +import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION; import static org.opendaylight.mdsal.binding.util.Datastore.OPERATIONAL; import com.google.common.util.concurrent.ListenableFuture; @@ -14,7 +15,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.Callable; @@ -48,6 +48,7 @@ import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.util.Datastore.Operational; import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner; import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl; +import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction; import org.opendaylight.mdsal.binding.util.TypedWriteTransaction; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.mdsal.common.api.ReadFailedException; @@ -57,6 +58,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types. import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortReason; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTepBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTepKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey; @@ -124,30 +128,37 @@ public class TunnelInventoryStateListener extends public void remove(@NonNull InstanceIdentifier key, @NonNull FlowCapableNodeConnector flowCapableNodeConnector) { String portName = flowCapableNodeConnector.getName(); + NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId(); LOG.debug("InterfaceInventoryState Remove for {}", portName); EVENT_LOGGER.debug("ITM-TunnelInventoryState,REMOVE DTCN received for {}", flowCapableNodeConnector.getName()); - // ITM Direct Tunnels Return if its not tunnel port and if its not Internal - if (!DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && !portName.startsWith("of")) { + + if (!directTunnelUtils.isEntityOwner()) { + return; + } + // ITM Direct Tunnels Return if its not tunnel port or of-ports + if (portName.startsWith("of") && interfaceManager.isItmOfTunnelsEnabled()) { + LOG.debug("OfPortState REMOVE for {}", portName); + EVENT_LOGGER.debug("ITM-OfPortStateState Entity Owner, REMOVE {} {}", nodeConnectorId.getValue(), portName); + OfPortStateRemoveWorker ofPortStateRemoveWorker = new OfPortStateRemoveWorker(nodeConnectorId, + null, flowCapableNodeConnector, portName); + coordinator.enqueueJob(portName, ofPortStateRemoveWorker, ITMConstants.JOB_MAX_RETRIES); + return; + } else if (!DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName)) { LOG.debug("Node Connector Remove - {} Interface is not a tunnel I/f, so no-op", portName); return; - } else { - try { - if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) - && !tunnelStateCache.isInternalBasedOnState(portName)) { - LOG.debug("Node Connector Remove {} Interface is not a internal tunnel I/f, so no-op", portName); - return; - } - } catch (ReadFailedException e) { - LOG.error("Tunnel {} is not present in operational DS ", portName); + } + + try { + if (!tunnelStateCache.isInternalBasedOnState(portName)) { + LOG.debug("Node Connector Remove {} Interface is not a internal tunnel I/f, so no-op", portName); return; } - } - if (!directTunnelUtils.isEntityOwner()) { + } catch (ReadFailedException e) { + LOG.error("Tunnel {} is not present in operational DS ", portName); return; } LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnector); - NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId(); remove(nodeConnectorId, flowCapableNodeConnector, portName); } @@ -381,6 +392,32 @@ public class TunnelInventoryStateListener extends Interface.OperStatus.Unknown); } + private void updateOfTepStateOnNodeRemove(Uint64 srcDpn, String ofTepName, + FlowCapableNodeConnector flowCapableNodeConnector, + TypedReadWriteTransaction tx) throws ReadFailedException { + LOG.debug("Updating oftep oper-status to UNKNOWN for : {}", ofTepName); + Optional dpnTepInfo = ofDpnTepConfigCache.get(srcDpn.toJava()); + if (dpnTepInfo == null || !ofTepName.equals(flowCapableNodeConnector.getName())) { + return; + } + handleOfTepStateUpdates(dpnTepInfo, tx, true, ofTepName, + Interface.OperStatus.Unknown); + } + + private void handleOfTepStateUpdates(Optional dpnTepInfo, TypedReadWriteTransaction tx, + boolean opStateModified, String ofTepName, Interface.OperStatus opState) { + LOG.debug("updating oftep state entry for {}", ofTepName); + InstanceIdentifier ofTepStateId = ItmUtils.buildStateOfTepListId(new OfTepKey(ofTepName)); + OfTepBuilder ofTepBuilder = new OfTepBuilder(); + ofTepBuilder.withKey(new OfTepKey(ofTepName)); + if (opStateModified) { + LOG.debug("updating oftep oper status as {} for {}", opState.getName(), ofTepName); + ofTepBuilder.setOfTepState(DirectTunnelUtils.convertInterfaceToTunnelOperState(opState)); + LOG.trace("updated to {} for {}",opState.getName(), ofTepName); + } + tx.merge(ofTepStateId, ofTepBuilder.build()); + } + private Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector) { return flowCapableNodeConnector.getState().isLive() && !flowCapableNodeConnector.getConfiguration().isPORTDOWN() @@ -433,36 +470,64 @@ public class TunnelInventoryStateListener extends //Remove event is because of connection lost between controller and switch, or switch shutdown. // Hence, dont remove the interface but set the status as "unknown" - if (interfaceName.startsWith("of")) { - LOG.debug("Received remove state for dpid {}", dpId.intValue()); - for (Map.Entry entry : meshedMap.entrySet()) { - if (!dpId.toString().equals(entry.getKey())) { - String fwdTunnel = dpnTepStateCache.getDpnTepInterface(dpId, Uint64.valueOf(entry.getKey())) - .getTunnelName(); - LOG.debug("Fwd Tunnel name for {} : {} is {}", dpId.intValue(), entry.getKey(), fwdTunnel); - futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, - tx -> updateInterfaceStateOnNodeRemove(tx, fwdTunnel, flowCapableNodeConnector))); - String bwdTunnel = dpnTepStateCache.getDpnTepInterface(Uint64.valueOf(entry.getKey()), dpId) - .getTunnelName(); - LOG.debug("Bwd Tunnel name for {} : {} is {}", entry.getKey(), dpId.intValue(), bwdTunnel); - futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, - tx -> updateInterfaceStateOnNodeRemove(tx, bwdTunnel, - entry.getValue().getNodeConnector()))); - } - } - } else { - futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, - tx -> updateInterfaceStateOnNodeRemove(tx, interfaceName, flowCapableNodeConnector))); - } + futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, + tx -> updateInterfaceStateOnNodeRemove(tx, interfaceName, flowCapableNodeConnector))); + } else { LOG.debug("removing interface state for interface: {}", interfaceName); + directTunnelUtils.deleteTunnelStateEntry(interfaceName); + DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName); + if (dpnTepInfo != null) { + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> { + // Do if-index and ingress flow clean-up only for tunnel-interfaces + directTunnelUtils.removeLportTagInterfaceMap(interfaceName); + directTunnelUtils.removeTunnelIngressFlow(tx, dpId, interfaceName); + directTunnelUtils.removeTunnelEgressFlow(tx, dpId, interfaceName); + })); + } else { + LOG.error("DPNTEPInfo is null for Tunnel Interface {}", interfaceName); + } EVENT_LOGGER.debug("ITM-TunnelInventoryState,REMOVE Table 0 flow for {} completed", interfaceName); - // removing interfaces are already done in delete worker - meshedMap.remove(dpId.toString()); } return futures; } + @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", + justification = "https://github.com/spotbugs/spotbugs/issues/811") + private List> removeOfTepStateConfiguration(NodeConnectorId nodeConnectorIdNew, + NodeConnectorId nodeConnectorIdOld, + String ofTepName, + FlowCapableNodeConnector + fcNodeConnectorOld) { + List> futures = new ArrayList<>(); + + NodeConnectorId nodeConnectorId = (nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld)) + ? nodeConnectorIdOld : nodeConnectorIdNew; + + Uint64 dpId = DirectTunnelUtils.getDpnFromNodeConnectorId(nodeConnectorId); + + // In a genuine port delete scenario, the reason will be there in the incoming event, for all remaining + // cases treat the event as DPN disconnect, if old and new ports are same. Else, this is a VM migration + // scenario, and should be treated as port removal. + if (fcNodeConnectorOld.getReason() != PortReason.Delete) { + //Remove event is because of connection lost between controller and switch, or switch shutdown. + // Hence, dont remove the interface but set the status as "unknown" + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> { + updateOfTepStateOnNodeRemove(dpId, ofTepName, fcNodeConnectorOld, tx); + })); + } else { + LOG.debug("removing oftep state for oftep: {}", ofTepName); + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> { + directTunnelUtils.deleteOfTepStateEntry(ofTepName); + directTunnelUtils.removeLportTagInterfaceMap(ofTepName); + directTunnelUtils.removeTunnelIngressFlow(tx, dpId, ofTepName); + })); + EVENT_LOGGER.debug("ITM-OfTepInventoryState,REMOVE Table 0 flow for {} completed", ofTepName); + } + + return futures; + } + private class TunnelInterfaceStateUpdateWorker implements Callable>> { private final InstanceIdentifier key; private final FlowCapableNodeConnector fcNodeConnectorOld; @@ -554,4 +619,34 @@ public class TunnelInventoryStateListener extends })); return futures; } + + private class OfPortStateRemoveWorker implements Callable>> { + + private final NodeConnectorId nodeconnectorIdNew; + private final NodeConnectorId nodeconnectorIdOld; + private final FlowCapableNodeConnector fcNodeConnectorOld; + private final String ofTepName; + + OfPortStateRemoveWorker(NodeConnectorId nodeconnectorIdNew, NodeConnectorId nodeconnectorIdOld, + FlowCapableNodeConnector fcNodeConnectorOld, String ofTepName) { + this.nodeconnectorIdNew = nodeconnectorIdNew; + this.nodeconnectorIdOld = nodeconnectorIdOld; + this.fcNodeConnectorOld = fcNodeConnectorOld; + this.ofTepName = ofTepName; + } + + @Override + public List> call() throws Exception { + // If another renderer(for eg : OVS) needs to be supported, check can be performed here + // to call the respective helpers. + return removeOfTepStateConfiguration(nodeconnectorIdNew, nodeconnectorIdOld, ofTepName, fcNodeConnectorOld); + } + + @Override + public String toString() { + return "OfTepStateRemoveWorker{nodeConnectorInfo=" + nodeconnectorIdNew + ", nodeConnectorIdOld=" + + nodeconnectorIdOld + ", fcNodeConnectorOld=" + fcNodeConnectorOld + ", ofTepName='" + + ofTepName + '\'' + '}'; + } + } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/renderer/ovs/utilities/DirectTunnelUtils.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/renderer/ovs/utilities/DirectTunnelUtils.java index d879309a1..f53faeb7e 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/renderer/ovs/utilities/DirectTunnelUtils.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/renderer/ovs/utilities/DirectTunnelUtils.java @@ -24,6 +24,7 @@ import java.util.regex.Pattern; import javax.inject.Inject; import javax.inject.Singleton; import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; import org.opendaylight.genius.interfacemanager.globals.IfmConstants; import org.opendaylight.genius.itm.globals.ITMConstants; import org.opendaylight.genius.itm.impl.ITMBatchingUtils; @@ -46,9 +47,12 @@ import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchTunnelSourceIp; import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils; import org.opendaylight.infrautils.utils.concurrent.NamedLocks; import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired; +import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.util.Datastore.Configuration; import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction; import org.opendaylight.mdsal.binding.util.TypedWriteTransaction; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; @@ -82,11 +86,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.b import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTepKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTepKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; @@ -605,4 +614,22 @@ public final class DirectTunnelUtils { return "of" + UUID.nameUUIDFromBytes(trunkInterfaceName.getBytes(StandardCharsets.UTF_8)).toString() .substring(0, 12).replace("-", ""); } + + public void deleteOfTepStateEntry(String ofTepName) { + LOG.debug("deleteOfTepStateEntry ofTeps state for {}", ofTepName); + InstanceIdentifier ofTeplId = + ItmUtils.buildStateOfTepListId(new OfTepKey(ofTepName)); + ITMBatchingUtils.delete(ofTeplId, ITMBatchingUtils.EntityType.DEFAULT_OPERATIONAL); + } + + public static void removeOfTepFromDpnsTepConfigDS(DataBroker dataBroker, Uint64 srcDpnId) + throws TransactionCommitFailedException { + // The source DPn id is the one to be removed + InstanceIdentifier dpntepII = buildDpnTepInstanceIdentifier(srcDpnId); + SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, dpntepII); + } + + private static InstanceIdentifier buildDpnTepInstanceIdentifier(Uint64 srcDpnId) { + return InstanceIdentifier.builder(DpnTepConfig.class).child(OfDpnTep.class, new OfDpnTepKey(srcDpnId)).build(); + } } diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/TransportZoneListener.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/TransportZoneListener.java index daad3646f..4785d0032 100644 --- a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/TransportZoneListener.java +++ b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/listeners/TransportZoneListener.java @@ -27,7 +27,9 @@ import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackReg import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache; import org.opendaylight.genius.itm.cache.DpnTepStateCache; +import org.opendaylight.genius.itm.cache.OfDpnTepConfigCache; import org.opendaylight.genius.itm.cache.OfEndPointCache; +import org.opendaylight.genius.itm.cache.OfTepStateCache; import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache; import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache; import org.opendaylight.genius.itm.cache.TunnelStateCache; @@ -111,6 +113,8 @@ public class TransportZoneListener extends AbstractSyncDataTreeChangeListener tunType = ItmUtils.getTunnelType(itmConfig.getDefTzTunnelType()); + if (interfaceManager.isItmOfTunnelsEnabled()) { + Map dpnTepMap = createOfTepInfo(transportZone); - if (!itmConfig.isDefTzEnabled() || !Objects.equals(transportZone.getTunnelType(), tunType)) { - allowTunnelDeletion = true; + if (!dpnTepMap.isEmpty()) { + jobCoordinator.enqueueJob(transportZone.getZoneName(), + new ItmOfPortRemoveWorker(dpnTepMap, itmOfTunnelDeleteWorker)); } else { - // this is case when def-tz removal request is from Northbound. - allowTunnelDeletion = false; - LOG.error("Deletion of {} is an incorrect usage",ITMConstants.DEFAULT_TRANSPORT_ZONE); + EVENT_LOGGER.debug("DPN List in TZ is empty"); } } else { - allowTunnelDeletion = true; - } - - if (allowTunnelDeletion) { - //TODO : DPList code can be refactor with new specific class - // which implement TransportZoneValidator - EVENT_LOGGER.debug("ITM-Transportzone,TunnelDeletion {}", transportZone.getZoneName()); - List opDpnList = createDPNTepInfo(transportZone); - List hwVtepList = createhWVteps(transportZone); - LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList); - if (!opDpnList.isEmpty() || !hwVtepList.isEmpty()) { - LOG.trace("Delete: Invoking ItmManager with hwVtep List {} ", hwVtepList); - jobCoordinator.enqueueJob(transportZone.getZoneName(), - new ItmTepRemoveWorker(opDpnList, hwVtepList, transportZone, mdsalManager, - itmInternalTunnelDeleteWorker, dpnTEPsInfoCache, txRunner, itmConfig)); + // check if TZ received for removal is default-transport-zone, + // if yes, then check if it is received from northbound, then + // do not entertain request and skip tunnels remove operation + // if def-tz removal request is due to def-tz-enabled flag is disabled or + // due to change in def-tz-tunnel-type, then allow def-tz tunnels deletion + if (ITMConstants.DEFAULT_TRANSPORT_ZONE.equalsIgnoreCase(transportZone.getZoneName())) { + // Get TunnelTypeBase object for tunnel-type configured in config file + Class tunType = ItmUtils.getTunnelType(itmConfig.getDefTzTunnelType()); + + if (!itmConfig.isDefTzEnabled() || !Objects.equals(transportZone.getTunnelType(), tunType)) { + allowTunnelDeletion = true; + } else { + // this is case when def-tz removal request is from Northbound. + allowTunnelDeletion = false; + LOG.error("Deletion of {} is an incorrect usage", ITMConstants.DEFAULT_TRANSPORT_ZONE); + } + } else { + allowTunnelDeletion = true; + } - if (transportZone.getVteps() != null && !transportZone.getVteps().isEmpty()) { - Map unknownVteps = - convertVtepListToUnknownVtepList(transportZone.getVteps()); - LOG.trace("Moving Transport Zone {} to tepsInNotHostedTransportZone Oper Ds.", - transportZone.getZoneName()); + if (allowTunnelDeletion) { + //TODO : DPList code can be refactor with new specific class + // which implement TransportZoneValidator + EVENT_LOGGER.debug("ITM-Transportzone,TunnelDeletion {}", transportZone.getZoneName()); + List opDpnList = createDPNTepInfo(transportZone); + List hwVtepList = createhWVteps(transportZone); + LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList); + if (!opDpnList.isEmpty() || !hwVtepList.isEmpty()) { + LOG.trace("Delete: Invoking ItmManager with hwVtep List {} ", hwVtepList); jobCoordinator.enqueueJob(transportZone.getZoneName(), - new ItmTepsNotHostedAddWorker(unknownVteps, transportZone.getZoneName(), - dataBroker, txRunner)); + new ItmTepRemoveWorker(opDpnList, hwVtepList, transportZone, mdsalManager, + itmInternalTunnelDeleteWorker, dpnTEPsInfoCache, txRunner, itmConfig)); + + if (transportZone.getVteps() != null && !transportZone.getVteps().isEmpty()) { + Map unknownVteps = + convertVtepListToUnknownVtepList(transportZone.getVteps()); + LOG.trace("Moving Transport Zone {} to tepsInNotHostedTransportZone Oper Ds.", + transportZone.getZoneName()); + jobCoordinator.enqueueJob(transportZone.getZoneName(), + new ItmTepsNotHostedAddWorker(unknownVteps, transportZone.getZoneName(), + dataBroker, txRunner)); + } } } } @@ -386,7 +405,7 @@ public class TransportZoneListener extends AbstractSyncDataTreeChangeListener> futures, + ManagedNewTransactionRunner txRunner, + String interfaceName) { + LOG.info("Unbinding service for : {}", interfaceName); + futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + tx -> tx.delete(buildDefaultServiceId(interfaceName)))); + } + + public static InstanceIdentifier buildDefaultServiceId(String interfaceName) { + return buildServiceId(interfaceName, ServiceIndex.getIndex(NwConstants.DEFAULT_EGRESS_SERVICE_NAME, + NwConstants.DEFAULT_EGRESS_SERVICE_INDEX), ServiceModeEgress.class); + } + + public static InstanceIdentifier buildServiceId(String interfaceName, short serviceIndex, + Class serviceMode) { + return InstanceIdentifier.builder(ServiceBindings.class) + .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode)) + .child(BoundServices.class, new BoundServicesKey(Uint8.valueOf(serviceIndex))).build(); + } } diff --git a/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmInternalTunnelDeleteTest.java b/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmInternalTunnelDeleteTest.java index b60e9b54a..ada0f2ef0 100644 --- a/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmInternalTunnelDeleteTest.java +++ b/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmInternalTunnelDeleteTest.java @@ -171,7 +171,7 @@ public class ItmInternalTunnelDeleteTest { new OvsBridgeEntryCache(dataBroker, new GuavaCacheProvider(new CacheManagersRegistryImpl())), new OvsBridgeRefEntryCache(dataBroker, new GuavaCacheProvider(new CacheManagersRegistryImpl())), new TunnelStateCache(dataBroker, new GuavaCacheProvider(new CacheManagersRegistryImpl())), - directTunnelUtils, ofEndPointCache, itmConfig, tombstonedNodeManager); + directTunnelUtils, tombstonedNodeManager); } @After diff --git a/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmManagerRpcServiceTest.java b/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmManagerRpcServiceTest.java index c275fb258..5648a2cb5 100644 --- a/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmManagerRpcServiceTest.java +++ b/itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmManagerRpcServiceTest.java @@ -237,7 +237,7 @@ public class ItmManagerRpcServiceTest { new GuavaCacheProvider(new CacheManagersRegistryImpl()), directTunnelUtils, unprocessedOFNCCache); OfTepStateCache ofTepStateCache = new OfTepStateCache(dataBroker, new GuavaCacheProvider( - new CacheManagersRegistryImpl())); + new CacheManagersRegistryImpl()), interfaceManager, directTunnelUtils); itmManagerRpcService = new ItmManagerRpcService(dataBroker, mdsalApiManager, itmConfig, dpntePsInfoCache, interfaceManager, dpnTepStateCache, tunnelStateCache, interfaceManagerService,