Implemented tunnel state updation 37/70237/28
authorEdw7n <n.edwin.anthony@ericsson.com>
Wed, 4 Apr 2018 14:59:13 +0000 (20:29 +0530)
committerEdw7n <n.edwin.anthony@ericsson.com>
Fri, 20 Apr 2018 09:10:39 +0000 (14:40 +0530)
Listening to the inventory DS and create tunnel state information and also
program the ingress flows related to the tunnel
Fixed issues while testing

Change-Id: I83b0b6e95156ad7013cd8b3ff9902dcfed0a35ee
Signed-off-by: Edw7n <n.edwin.anthony@ericsson.com>
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/AbstractTunnelListenerBase.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelInventoryStateListener.java [new file with mode: 0644]
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelListenerCreator.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelTopologyStateListener.java

index 916da916134789a91b5f3f5ba4fbae7b0755f9ae..1df11954c34e7fcfcfeb2681d35bda52d16dfa67 100644 (file)
@@ -17,8 +17,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
 import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
 import org.opendaylight.genius.itm.cache.UnprocessedNodeConnectorCache;
@@ -49,6 +51,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBfd;
@@ -244,7 +248,7 @@ abstract class AbstractTunnelListenerBase<T extends DataObject> extends Abstract
                 ifindex, NwConstants.ADD_FLOW);
     }
 
-    private void makeTunnelIngressFlow(DpnTepInterfaceInfo dpnTepConfigInfo, BigInteger dpnId, long portNo,
+    protected void makeTunnelIngressFlow(DpnTepInterfaceInfo dpnTepConfigInfo, BigInteger dpnId, long portNo,
                                        String interfaceName, int ifIndex, int addOrRemoveFlow) {
         LOG.debug("make tunnel ingress flow for {}", interfaceName);
         String flowRef = getTunnelInterfaceFlowRef(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, interfaceName);
@@ -389,4 +393,41 @@ abstract class AbstractTunnelListenerBase<T extends DataObject> extends Abstract
 
         ITMBatchingUtils.write(tpIid, tpBuilder.build(), ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
     }
+
+    public void deleteTunnelStateEntry(String interfaceName) {
+        LOG.debug(" deleteTunnelStateEntry tunnels state for {}", interfaceName);
+        InstanceIdentifier<StateTunnelList> stateTnlId =
+                ItmUtils.buildStateTunnelListId(new StateTunnelListKey(interfaceName));
+
+        ITMBatchingUtils.delete(stateTnlId, ITMBatchingUtils.EntityType.DEFAULT_OPERATIONAL);
+    }
+
+    public void removeLportTagInterfaceMap(String infName)
+            throws ExecutionException, InterruptedException, OperationFailedException {
+        // workaround to get the id to remove from lport tag interface map
+        Integer ifIndex = allocateId(IfmConstants.IFM_IDPOOL_NAME, infName);
+        releaseId(IfmConstants.IFM_IDPOOL_NAME, infName);
+        LOG.debug("removing lport tag to interface map for {}", infName);
+        InstanceIdentifier<IfIndexTunnel> id = InstanceIdentifier.builder(IfIndexesTunnelMap.class)
+                .child(IfIndexTunnel.class, new IfIndexTunnelKey(ifIndex)).build();
+        ITMBatchingUtils.delete(id, ITMBatchingUtils.EntityType.DEFAULT_OPERATIONAL);
+    }
+
+    private void releaseId(String poolName, String idKey) throws InterruptedException, ExecutionException,
+            OperationFailedException {
+        ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+        Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+        RpcResult<Void> rpcResult = result.get();
+        if (!rpcResult.isSuccessful()) {
+            LOG.error("RPC Call to release Id with Key {} returned with Errors {}", idKey, rpcResult.getErrors());
+            Optional<RpcError> rpcError = rpcResult.getErrors().stream().findFirst();
+            String msg = String.format("RPC Call to release Id returned with Errors for the key %s", idKey);
+            if (rpcError.isPresent()) {
+                throw new OperationFailedException(msg, rpcError.get());
+            }
+            else {
+                throw new OperationFailedException(msg);
+            }
+        }
+    }
 }
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
new file mode 100644 (file)
index 0000000..f1b8f75
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2018 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.itm.itmdirecttunnels.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.itm.cache.DPNTEPsInfoCache;
+import org.opendaylight.genius.itm.cache.DpnTepStateCache;
+import org.opendaylight.genius.itm.cache.TunnelStateCache;
+import org.opendaylight.genius.itm.cache.UnprocessedNodeConnectorCache;
+import org.opendaylight.genius.itm.globals.ITMConstants;
+import org.opendaylight.genius.itm.impl.ItmUtils;
+import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
+import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
+import org.opendaylight.genius.itm.utils.NodeConnectorInfo;
+import org.opendaylight.genius.itm.utils.NodeConnectorInfoBuilder;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+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.idmanager.rev160406.IdManagerService;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
+ * This creates an entry in the tunnels-state OperDS for every node-connector used.
+ */
+public class TunnelInventoryStateListener extends AbstractTunnelListenerBase<FlowCapableNodeConnector> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TunnelInventoryStateListener.class);
+
+    private final JobCoordinator coordinator;
+    private final ManagedNewTransactionRunner txRunner;
+    private final TunnelStateCache tunnelStateCache;
+
+    public TunnelInventoryStateListener(final DataBroker dataBroker,
+                                        final JobCoordinator coordinator,
+                                        final EntityOwnershipUtils entityOwnershipUtils,
+                                        final IdManagerService idManager,
+                                        final IMdsalApiManager mdsalApiManager,
+                                        final TunnelStateCache tunnelStateCache,
+                                        final DpnTepStateCache dpnTepStateCache,
+                                        final DPNTEPsInfoCache dpntePsInfoCache,
+                                        final UnprocessedNodeConnectorCache unprocessedNCCache) {
+        super(dataBroker, LogicalDatastoreType.OPERATIONAL,InstanceIdentifier.create(Nodes.class).child(Node.class)
+                .child(NodeConnector.class).augmentation(FlowCapableNodeConnector.class), idManager, mdsalApiManager,
+                dpnTepStateCache, dpntePsInfoCache, unprocessedNCCache, entityOwnershipUtils);
+        this.coordinator = coordinator;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+        this.tunnelStateCache = tunnelStateCache;
+        super.register();
+    }
+
+    @Override
+    public void remove(@Nonnull InstanceIdentifier<FlowCapableNodeConnector> key,
+                       @Nonnull FlowCapableNodeConnector flowCapableNodeConnectorOld) {
+        String portName = flowCapableNodeConnectorOld.getName();
+        LOG.debug("InterfaceInventoryState Remove for {}", portName);
+        // ITM Direct Tunnels Return if its not tunnel port and if its not Internal
+        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 (!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);
+                return;
+            }
+        }
+        if (!entityOwner()) {
+            return;
+        }
+        LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
+        NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+        remove(nodeConnectorId, null, flowCapableNodeConnectorOld, portName);
+    }
+
+    private void remove(NodeConnectorId nodeConnectorIdNew, NodeConnectorId nodeConnectorIdOld,
+                        FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
+        LOG.debug("InterfaceInventoryState REMOVE for {}", portName);
+        InterfaceStateRemoveWorker portStateRemoveWorker = new InterfaceStateRemoveWorker(nodeConnectorIdNew,
+                nodeConnectorIdOld, fcNodeConnectorNew, portName, portName);
+        coordinator.enqueueJob(portName, portStateRemoveWorker, ITMConstants.JOB_MAX_RETRIES);
+    }
+
+    @Override
+    public void update(@Nonnull InstanceIdentifier<FlowCapableNodeConnector> key,
+                       @Nonnull FlowCapableNodeConnector fcNodeConnectorOld,
+                       @Nonnull FlowCapableNodeConnector fcNodeConnectorNew) {
+        String portName = fcNodeConnectorNew.getName();
+        if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName)) {
+            LOG.debug("Node Connector Update - {} Interface is not a tunnel I/f, so no-op", portName);
+            return;
+        } else if (!dpnTepStateCache.isInternal(portName)) {
+            LOG.debug("Node Connector Update {} Interface is not a internal tunnel I/f, so no-op", portName);
+            return;
+        }
+        if (fcNodeConnectorNew.getReason() == PortReason.Delete || !entityOwner()) {
+            return;
+        }
+        LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
+
+        InterfaceStateUpdateWorker portStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
+                fcNodeConnectorNew, portName);
+        coordinator.enqueueJob(portName, portStateUpdateWorker, ITMConstants.JOB_MAX_RETRIES);
+    }
+
+    @Override
+    public void add(@Nonnull InstanceIdentifier<FlowCapableNodeConnector> key,
+                    @Nonnull FlowCapableNodeConnector fcNodeConnectorNew) {
+        String portName = fcNodeConnectorNew.getName();
+        LOG.debug("InterfaceInventoryState ADD for {}", portName);
+        // Return if its not tunnel port and if its not Internal
+        if (!DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName)) {
+            LOG.debug("Node Connector Add {} Interface is not a tunnel I/f, so no-op", portName);
+            return;
+        }
+        if (!entityOwner()) {
+            return;
+        }
+        if (!dpnTepStateCache.isConfigAvailable(portName)) {
+            // Park the notification
+            LOG.debug("Unable to process the NodeConnector ADD event for {} as Config not available."
+                    + "Hence parking it", portName);
+            NodeConnectorInfo nodeConnectorInfo = new NodeConnectorInfoBuilder().setNodeConnectorId(key)
+                    .setNodeConnector(fcNodeConnectorNew).build();
+            unprocessedNCCache.add(portName, nodeConnectorInfo);
+            return;
+        } else if (!dpnTepStateCache.isInternal(portName)) {
+            LOG.debug("{} Interface is not a internal tunnel I/f, so no-op", portName);
+            return;
+        }
+
+        LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
+        if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(portName) && dpnTepStateCache.isInternal(portName)) {
+            //NodeConnectorId nodeConnectorId =
+            // InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+            InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(key,
+                    fcNodeConnectorNew, portName);
+            coordinator.enqueueJob(portName, ifStateAddWorker, ITMConstants.JOB_MAX_RETRIES);
+        }
+    }
+
+    private List<ListenableFuture<Void>> updateState(InstanceIdentifier<FlowCapableNodeConnector> key,
+                                                     String interfaceName,
+                                                     FlowCapableNodeConnector flowCapableNodeConnectorNew,
+                                                     FlowCapableNodeConnector flowCapableNodeConnectorOld) {
+        LOG.debug("Updating interface state for port: {}", interfaceName);
+
+        // Hardware updates can be ignored
+        Interface.OperStatus operStatusNew = getOpState(flowCapableNodeConnectorNew);
+        MacAddress macAddressNew = flowCapableNodeConnectorNew.getHardwareAddress();
+
+        Interface.OperStatus operStatusOld = getOpState(flowCapableNodeConnectorOld);
+        MacAddress macAddressOld = flowCapableNodeConnectorOld.getHardwareAddress();
+
+        boolean opstateModified = false;
+        boolean hardwareAddressModified = false;
+        if (!operStatusNew.equals(operStatusOld)) {
+            opstateModified = true;
+        }
+        if (!macAddressNew.equals(macAddressOld)) {
+            hardwareAddressModified = true;
+        }
+
+        if (!opstateModified && !hardwareAddressModified) {
+            LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
+            return Collections.emptyList();
+        }
+
+        DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
+
+        // For monitoring enabled tunnels, skip opstate updation
+        if (!modifyTunnelOpState(dpnTepInfo, opstateModified)) {
+            LOG.debug("skipping Tunnel-state update for monitoring enabled tunnel interface {}", interfaceName);
+            opstateModified = false;
+        }
+
+        if (!opstateModified && !hardwareAddressModified) {
+            LOG.debug("If State entry for port: {} Not Modified.", interfaceName);
+            return Collections.emptyList();
+        }
+        if (opstateModified) {
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                // modify the attributes in interface operational DS
+                handleInterfaceStateUpdates(dpnTepInfo, tx, true, interfaceName, flowCapableNodeConnectorNew.getName(),
+                        operStatusNew);
+
+            }));
+        } else {
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                // modify the attributes in interface operational DS
+                handleInterfaceStateUpdates(dpnTepInfo, tx, false, interfaceName,
+                        flowCapableNodeConnectorNew.getName(), operStatusNew);
+
+            }));
+        }
+    }
+
+    private void updateInterfaceStateOnNodeRemove(String interfaceName,
+                                                  FlowCapableNodeConnector flowCapableNodeConnector,
+                                                  WriteTransaction transaction) {
+        LOG.debug("Updating interface oper-status to UNKNOWN for : {}", interfaceName);
+        DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
+
+        handleInterfaceStateUpdates(dpnTepInfo, transaction, true, interfaceName, flowCapableNodeConnector.getName(),
+                Interface.OperStatus.Unknown);
+    }
+
+    private Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector) {
+        return flowCapableNodeConnector.getState().isLive()
+                && !flowCapableNodeConnector.getConfiguration().isPORTDOWN()
+                ? Interface.OperStatus.Up : Interface.OperStatus.Down;
+    }
+
+    private void handleInterfaceStateUpdates(DpnTepInterfaceInfo dpnTepInfo, WriteTransaction transaction,
+                                             boolean opStateModified, String interfaceName, String portName,
+                                             Interface.OperStatus opState) {
+        if (dpnTepInfo == null && !interfaceName.equals(portName)) {
+            return;
+        }
+        LOG.debug("updating interface state entry for {}", interfaceName);
+        InstanceIdentifier<StateTunnelList> tnlStateId = ItmUtils.buildStateTunnelListId(
+                new StateTunnelListKey(interfaceName));
+        StateTunnelListBuilder stateTnlBuilder = new StateTunnelListBuilder();
+        stateTnlBuilder.setKey(new StateTunnelListKey(interfaceName));
+        if (modifyOpState(dpnTepInfo, opStateModified)) {
+            LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
+            boolean tunnelState = opState.equals(Interface.OperStatus.Up);
+            stateTnlBuilder.setTunnelState(tunnelState);
+            stateTnlBuilder.setOperState(DirectTunnelUtils.convertInterfaceToTunnelOperState(opState));
+        }
+        transaction.merge(LogicalDatastoreType.OPERATIONAL, tnlStateId, stateTnlBuilder.build(), false);
+    }
+
+    private boolean modifyOpState(DpnTepInterfaceInfo dpnTepInterfaceInfo, boolean opStateModified) {
+        return opStateModified && (dpnTepInterfaceInfo == null || dpnTepInterfaceInfo.isMonitoringEnabled());
+    }
+
+    private boolean modifyTunnelOpState(DpnTepInterfaceInfo dpnTepInterfaceInfo, boolean opStateModified) {
+        return !dpnTepInterfaceInfo.isMonitoringEnabled() && modifyOpState(dpnTepInterfaceInfo, opStateModified);
+    }
+
+    private List<ListenableFuture<Void>> removeInterfaceStateConfiguration(NodeConnectorId nodeConnectorIdNew,
+                                                                           NodeConnectorId nodeConnectorIdOld,
+                                                                           String interfaceName,
+                                                                           FlowCapableNodeConnector
+                                                                           fcNodeConnectorOld,
+                                                                           String parentInterface) {
+        List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+        NodeConnectorId nodeConnectorId = (nodeConnectorIdOld != null && !nodeConnectorIdNew.equals(nodeConnectorIdOld))
+                ? nodeConnectorIdOld : nodeConnectorIdNew;
+
+        BigInteger dpId = DirectTunnelUtils.getDpnFromNodeConnectorId(nodeConnectorId);
+        futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+        // 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 && nodeConnectorIdNew.equals(nodeConnectorIdOld)) {
+                //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"
+                updateInterfaceStateOnNodeRemove(interfaceName, fcNodeConnectorOld, tx);
+            } else {
+                LOG.debug("removing interface state for interface: {}", interfaceName);
+                deleteTunnelStateEntry(interfaceName);
+                DpnTepInterfaceInfo dpnTepInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
+                if (dpnTepInfo != null) {
+                    //This will only be tunnel interface
+                    removeLportTagInterfaceMap(interfaceName);
+                    long portNo = DirectTunnelUtils.getPortNumberFromNodeConnectorId(nodeConnectorId);
+                    makeTunnelIngressFlow(dpnTepInfo, dpId, portNo, interfaceName, -1,
+                            NwConstants.DEL_FLOW);
+                } else {
+                    LOG.error("DPNTEPInfo is null for Tunnel Interface {}", interfaceName);
+                }
+            }
+        }));
+        return futures;
+    }
+
+    private class InterfaceStateAddWorker implements Callable {
+        private final InstanceIdentifier<FlowCapableNodeConnector> key;
+        private final FlowCapableNodeConnector fcNodeConnectorNew;
+        private final String interfaceName;
+
+        InterfaceStateAddWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
+                                FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
+            this.key = key;
+            this.fcNodeConnectorNew = fcNodeConnectorNew;
+            this.interfaceName = portName;
+        }
+
+        @Override
+        public Object call() throws Exception {
+            // If another renderer(for eg : OVS) needs to be supported, check can be performed here
+            // to call the respective helpers.
+            return addState(key, interfaceName, fcNodeConnectorNew);
+        }
+
+        @Override
+        public String toString() {
+            return "InterfaceStateAddWorker{fcNodeConnectorIdentifier=" + key + ", fcNodeConnectorNew="
+                    + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
+        }
+    }
+
+    private class InterfaceStateUpdateWorker implements Callable {
+        private final InstanceIdentifier<FlowCapableNodeConnector> key;
+        private final FlowCapableNodeConnector fcNodeConnectorOld;
+        private final FlowCapableNodeConnector fcNodeConnectorNew;
+        private final String interfaceName;
+
+        InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
+                                   FlowCapableNodeConnector fcNodeConnectorOld,
+                                   FlowCapableNodeConnector fcNodeConnectorNew, String portName) {
+            this.key = key;
+            this.fcNodeConnectorOld = fcNodeConnectorOld;
+            this.fcNodeConnectorNew = fcNodeConnectorNew;
+            this.interfaceName = portName;
+        }
+
+        @Override
+        public Object call() throws Exception {
+            // If another renderer(for eg : OVS) needs to be supported, check can be performed here
+            // to call the respective helpers.
+            return updateState(key, interfaceName, fcNodeConnectorNew, fcNodeConnectorOld);
+        }
+
+        @Override
+        public String toString() {
+            return "InterfaceStateUpdateWorker{key=" + key + ", fcNodeConnectorOld=" + fcNodeConnectorOld
+                    + ", fcNodeConnectorNew=" + fcNodeConnectorNew + ", interfaceName='" + interfaceName + '\'' + '}';
+        }
+    }
+
+    private class InterfaceStateRemoveWorker implements Callable {
+        private final NodeConnectorId nodeConnectorIdNew;
+        private final NodeConnectorId nodeConnectorIdOld;
+        private final FlowCapableNodeConnector fcNodeConnectorOld;
+        private final String interfaceName;
+        private final String parentInterface;
+
+        InterfaceStateRemoveWorker(NodeConnectorId nodeConnectorIdNew,
+                                   NodeConnectorId nodeConnectorIdOld, FlowCapableNodeConnector fcNodeConnectorOld,
+                                   String interfaceName, String parentInterface) {
+            this.nodeConnectorIdNew = nodeConnectorIdNew;
+            this.nodeConnectorIdOld = nodeConnectorIdOld;
+            this.fcNodeConnectorOld = fcNodeConnectorOld;
+            this.interfaceName = interfaceName;
+            this.parentInterface = parentInterface;
+        }
+
+        @Override
+        public Object call() throws Exception {
+            // If another renderer(for eg : OVS) needs to be supported, check can be performed here
+            // to call the respective helpers.
+            return removeInterfaceStateConfiguration(nodeConnectorIdNew, nodeConnectorIdOld, interfaceName,
+                    fcNodeConnectorOld, parentInterface);
+        }
+
+        @Override
+        public String toString() {
+            return "InterfaceStateRemoveWorker{nodeConnectorIdNew=" + nodeConnectorIdNew + ", nodeConnectorIdOld="
+                    + nodeConnectorIdOld + ", fcNodeConnectorOld=" + fcNodeConnectorOld + ", interfaceName='"
+                    + interfaceName + '\'' + '}';
+        }
+    }
+}
index 964fe354398410cf210a897bc7b4b8f5cc2e769d..6a383122bf60818cfd1c30b845cf621633a72bb2 100644 (file)
@@ -14,6 +14,7 @@ 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.OvsBridgeEntryCache;
+import org.opendaylight.genius.itm.cache.TunnelStateCache;
 import org.opendaylight.genius.itm.cache.UnprocessedNodeConnectorCache;
 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
@@ -30,6 +31,7 @@ public class TunnelListenerCreator implements AutoCloseable {
 
     private final DpnTepStateListener dpnTepStateListener;
     private final TunnelTopologyStateListener tunnelTopologyStateListener;
+    private final TunnelInventoryStateListener tunnelInventoryStateListener;
 
     @Inject
     public TunnelListenerCreator(final DataBroker dataBroker,
@@ -42,8 +44,8 @@ public class TunnelListenerCreator implements AutoCloseable {
                                  final DpnTepStateCache dpnTepStateCache,
                                  final DPNTEPsInfoCache dpntePsInfoCache,
                                  final OvsBridgeEntryCache ovsBridgeEntryCache,
+                                 final TunnelStateCache tunnelStateCache,
                                  final UnprocessedNodeConnectorCache unprocessedNodeConnectorCache) {
-
         if (interfaceManager.isItmDirectTunnelsEnabled()) {
             LOG.trace("ITM Direct Tunnels is enabled. Initializing the listeners");
             this.dpnTepStateListener = new DpnTepStateListener(dataBroker, coordinator, entityOwnershipUtils,
@@ -51,10 +53,14 @@ public class TunnelListenerCreator implements AutoCloseable {
             this.tunnelTopologyStateListener = new TunnelTopologyStateListener(dataBroker, coordinator,
                     entityOwnershipUtils, idManager, mdsalApiManager, directTunnelUtils, dpnTepStateCache,
                     dpntePsInfoCache, ovsBridgeEntryCache, unprocessedNodeConnectorCache);
+            this.tunnelInventoryStateListener = new TunnelInventoryStateListener(dataBroker, coordinator,
+                    entityOwnershipUtils, idManager, mdsalApiManager, tunnelStateCache, dpnTepStateCache,
+                    dpntePsInfoCache, unprocessedNodeConnectorCache);
         } else {
             LOG.trace("ITM Direct Tunnels is disabled. Listeners are not registered");
             this.dpnTepStateListener = null;
             this.tunnelTopologyStateListener = null;
+            this.tunnelInventoryStateListener = null;
         }
     }
 
@@ -66,5 +72,8 @@ public class TunnelListenerCreator implements AutoCloseable {
         if (tunnelTopologyStateListener != null) {
             this.tunnelTopologyStateListener.close();
         }
+        if (tunnelInventoryStateListener != null) {
+            this.tunnelInventoryStateListener.close();
+        }
     }
 }
index 19245661896bda33bfb768508ae107c49187e287..7bbdc07f4b87ed7aaf64cfd9a0f8f60d6ee40213 100644 (file)
@@ -127,80 +127,6 @@ public class TunnelTopologyStateListener extends AbstractTunnelListenerBase<Ovsd
         }
     }
 
-    private class RendererStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
-        private final InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid;
-        private final OvsdbBridgeAugmentation bridgeNew;
-
-        RendererStateAddWorker(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
-                               OvsdbBridgeAugmentation bridgeNew) {
-            this.bridgeIid = bridgeIid;
-            this.bridgeNew = bridgeNew;
-        }
-
-        @Override
-        public List<ListenableFuture<Void>> call() throws Exception {
-            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
-            // to call the respective helpers.
-            if (bridgeNew.getDatapathId() == null) {
-                LOG.info("DataPathId found as null for Bridge Augmentation: {}... returning...", bridgeNew);
-                return Collections.emptyList();
-            }
-
-            BigInteger dpnId = directTunnelUtils.getDpnId(bridgeNew.getDatapathId());
-            LOG.debug("adding bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
-
-            // create bridge reference entry in interface meta operational DS
-            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
-                createOvsBridgeRefEntry(dpnId, bridgeIid, tx);
-                // handle pre-provisioning of tunnels for the newly connected dpn
-                Optional<OvsBridgeEntry> bridgeEntry = ovsBridgeEntryCache.get(dpnId);
-                if (!bridgeEntry.isPresent()) {
-                    LOG.debug("Bridge entry not found in config DS for dpn: {}", dpnId);
-                } else {
-                    addAllPortsToBridge(bridgeEntry.get(), bridgeIid, bridgeNew);
-                }
-            }));
-        }
-    }
-
-    private class RendererStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
-        private final InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
-        private final OvsdbBridgeAugmentation bridgeNew;
-
-        RendererStateRemoveWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
-                                  OvsdbBridgeAugmentation bridgeNew) {
-            this.instanceIdentifier = instanceIdentifier;
-            this.bridgeNew = bridgeNew;
-        }
-
-        @Override
-        public List<ListenableFuture<Void>> call() throws Exception {
-            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
-            // to call the respective helpers.
-            return removePortFromBridge(instanceIdentifier, bridgeNew);
-        }
-    }
-
-    private class RendererStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
-        private final InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
-        private final OvsdbBridgeAugmentation bridgeNew;
-        private final OvsdbBridgeAugmentation bridgeOld;
-
-        RendererStateUpdateWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
-                                  OvsdbBridgeAugmentation bridgeNew, OvsdbBridgeAugmentation bridgeOld) {
-            this.instanceIdentifier = instanceIdentifier;
-            this.bridgeNew = bridgeNew;
-            this.bridgeOld = bridgeOld;
-        }
-
-        @Override
-        public List<ListenableFuture<Void>> call() throws Exception {
-            // If another renderer(for eg : CSS) needs to be supported, check can be performed here
-            // to call the respective helpers.
-            return updateOvsBridgeRefEntry(instanceIdentifier, bridgeNew, bridgeOld);
-        }
-    }
-
     /*
      *  This code is used to handle only a dpnId change scenario for a particular change,
      * which is not expected to happen in usual cases.
@@ -313,4 +239,77 @@ public class TunnelTopologyStateListener extends AbstractTunnelListenerBase<Ovsd
         }
     }
 
+    private class RendererStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
+        private final InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid;
+        private final OvsdbBridgeAugmentation bridgeNew;
+
+        RendererStateAddWorker(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+                               OvsdbBridgeAugmentation bridgeNew) {
+            this.bridgeIid = bridgeIid;
+            this.bridgeNew = bridgeNew;
+        }
+
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+            // If another renderer(for eg : OVS) needs to be supported, check can be performed here
+            // to call the respective helpers.
+            if (bridgeNew.getDatapathId() == null) {
+                LOG.info("DataPathId found as null for Bridge Augmentation: {}... returning...", bridgeNew);
+                return Collections.emptyList();
+            }
+
+            BigInteger dpnId = directTunnelUtils.getDpnId(bridgeNew.getDatapathId());
+            LOG.debug("adding bridge references for bridge: {}, dpn: {}", bridgeNew, dpnId);
+
+            // create bridge reference entry in interface meta operational DS
+            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+                createOvsBridgeRefEntry(dpnId, bridgeIid, tx);
+                // handle pre-provisioning of tunnels for the newly connected dpn
+                Optional<OvsBridgeEntry> bridgeEntry = ovsBridgeEntryCache.get(dpnId);
+                if (!bridgeEntry.isPresent()) {
+                    LOG.debug("Bridge entry not found in config DS for dpn: {}", dpnId);
+                } else {
+                    addAllPortsToBridge(bridgeEntry.get(), bridgeIid, bridgeNew);
+                }
+            }));
+        }
+    }
+
+    private class RendererStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+        private final InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
+        private final OvsdbBridgeAugmentation bridgeNew;
+
+        RendererStateRemoveWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+                                  OvsdbBridgeAugmentation bridgeNew) {
+            this.instanceIdentifier = instanceIdentifier;
+            this.bridgeNew = bridgeNew;
+        }
+
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+            // If another renderer needs to be supported, check can be performed here
+            // to call the respective helpers.
+            return removePortFromBridge(instanceIdentifier, bridgeNew);
+        }
+    }
+
+    private class RendererStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+        private final InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
+        private final OvsdbBridgeAugmentation bridgeNew;
+        private final OvsdbBridgeAugmentation bridgeOld;
+
+        RendererStateUpdateWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+                                  OvsdbBridgeAugmentation bridgeNew, OvsdbBridgeAugmentation bridgeOld) {
+            this.instanceIdentifier = instanceIdentifier;
+            this.bridgeNew = bridgeNew;
+            this.bridgeOld = bridgeOld;
+        }
+
+        @Override
+        public List<ListenableFuture<Void>> call() throws Exception {
+            // If another renderer(for eg : OVS) needs to be supported, check can be performed here
+            // to call the respective helpers.
+            return updateOvsBridgeRefEntry(instanceIdentifier, bridgeNew, bridgeOld);
+        }
+    }
 }
\ No newline at end of file