Utils for itm performance enhancements 09/69109/20
authorEdw7n <n.edwin.anthony@ericsson.com>
Tue, 6 Mar 2018 06:11:17 +0000 (11:41 +0530)
committerFaseela K <faseela.k@ericsson.com>
Thu, 22 Mar 2018 16:21:53 +0000 (16:21 +0000)
Change-Id: Id0400bd56473550ebc49d2968024632fcdf5b265
Signed-off-by: Edw7n <n.edwin.anthony@ericsson.com>
itm/itm-api/src/main/java/org/opendaylight/genius/itm/globals/ITMConstants.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/BfdStateCache.java [new file with mode: 0644]
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/DPNTEPsInfoCache.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/DpnTepStateCache.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/TunnelStateCache.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/UnprocessedNodeConnectorCache.java [new file with mode: 0644]
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/UnprocessedNodeConnectorEndPointCache.java [new file with mode: 0644]
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/renderer/ovs/utilities/DirectTunnelUtils.java [new file with mode: 0644]

index e0ca20ab64592cb0c2d33b7f2ec9ad7c43c9d07d..6bc14709474a68f3253e9779be8c316a1613ffff 100644 (file)
@@ -65,6 +65,14 @@ public interface ITMConstants {
     String EXT_ID_TEP_PARAM_KEY_TZNAME = "tzname";
     String EXT_ID_TEP_PARAM_KEY_BR_NAME = "br-name";
     String EXT_ID_TEP_PARAM_KEY_OF_TUNNEL = "of-tunnel";
+
     // ITM DIRECT TUNNELS RELATED CONSTANTS
     String ITM_CONFIG_ENTITY = "itm_config";
+    int INVALID_PORT_NO = -1;
+    int DEFAULT_FLOW_PRIORITY = 5;
+    int MAC_STRING_LENGTH = 17;
+    String OF_URI_SEPARATOR = ":";
+    String DEAD_BEEF_MAC_PREFIX = "DEADBEEF";
+    String INVALID_MAC = "00:00:00:00:00:00";
+    String MAC_SEPARATOR = ":";
 }
diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/BfdStateCache.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/BfdStateCache.java
new file mode 100644 (file)
index 0000000..6367079
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.cache;
+
+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 BfdStateCache {
+
+    private final ConcurrentMap<String, Interface.OperStatus> bfdStateMap = new ConcurrentHashMap<>();
+
+    public void add(String interfaceName, Interface.OperStatus operStatus) {
+        bfdStateMap.put(interfaceName, operStatus);
+    }
+
+    public Interface.OperStatus remove(String interfaceName) {
+        return bfdStateMap.remove(interfaceName);
+    }
+
+    public Interface.OperStatus get(String interfaceName) {
+        return bfdStateMap.get(interfaceName);
+    }
+}
index 599229b48dd597c9b69cf75edcff48d0a093659a..77c3a602460755dfddffe370b68f8bc890b622b7 100644 (file)
@@ -7,6 +7,11 @@
  */
 package org.opendaylight.genius.itm.cache;
 
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -31,4 +36,22 @@ public class DPNTEPsInfoCache extends InstanceIdDataObjectCache<DPNTEPsInfo> {
         super(DPNTEPsInfo.class, dataBroker, LogicalDatastoreType.CONFIGURATION,
                 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class).build(), cacheProvider);
     }
+
+    public List<DPNTEPsInfo> getDPNTepListFromDPNId(List<BigInteger> dpnIds) {
+        Collection<DPNTEPsInfo> meshedDpnList = this.getAllPresent() ;
+        List<DPNTEPsInfo> cfgDpnList = new ArrayList<>();
+        for (BigInteger dpnId : dpnIds) {
+            for (DPNTEPsInfo teps : meshedDpnList) {
+                if (dpnId.equals(teps.getDPNID())) {
+                    cfgDpnList.add(teps);
+                }
+            }
+        }
+        return cfgDpnList;
+    }
+
+    public Optional<DPNTEPsInfo> getDPNTepFromDPNId(BigInteger dpnId) {
+        Collection<DPNTEPsInfo> meshedDpnList = this.getAllPresent() ;
+        return meshedDpnList.stream().filter(info -> dpnId.equals(info.getDPNID())).findFirst();
+    }
 }
index da7c052c938f24d09da8066d7a70f249da43647d..0f6975ccfc087c3f876d5ff89a9ab4c6acfa1b80 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.genius.itm.cache;
 
 import com.google.common.base.Optional;
 import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import javax.inject.Inject;
@@ -16,14 +19,23 @@ import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.itm.impl.ItmUtils;
 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfoBuilder;
+import org.opendaylight.genius.itm.utils.TunnelEndPointInfo;
+import org.opendaylight.genius.itm.utils.TunnelEndPointInfoBuilder;
 import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
 import org.opendaylight.infrautils.caches.CacheProvider;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBfd;
 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.dpn.endpoints.DPNTEPsInfo;
 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.dpn.teps.state.dpns.teps.RemoteDpnsKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,15 +45,20 @@ public class DpnTepStateCache extends DataObjectCache<BigInteger, DpnsTeps> {
 
     private static final Logger LOG = LoggerFactory.getLogger(DpnTepStateCache.class);
 
+    private final DataBroker dataBroker;
+    private final DPNTEPsInfoCache dpnTepsInfoCache;
     private final ConcurrentMap<String, DpnTepInterfaceInfo> dpnTepInterfaceMap = new ConcurrentHashMap<>();
+    private final ConcurrentMap<String, TunnelEndPointInfo> tunnelEndpointMap = new ConcurrentHashMap();
 
     @Inject
-    public DpnTepStateCache(DataBroker dataBroker, CacheProvider cacheProvider) {
+    public DpnTepStateCache(DataBroker dataBroker, CacheProvider cacheProvider, DPNTEPsInfoCache dpnTepsInfoCache) {
         super(DpnsTeps.class, dataBroker, LogicalDatastoreType.OPERATIONAL,
             InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class).build(), cacheProvider,
             (iid, dpnsTeps) -> dpnsTeps.getSourceDpnId(),
             sourceDpnId -> InstanceIdentifier.builder(DpnTepsState.class)
                     .child(DpnsTeps.class, new DpnsTepsKey(sourceDpnId)).build());
+        this.dataBroker = dataBroker;
+        this.dpnTepsInfoCache = dpnTepsInfoCache;
     }
 
     @Override
@@ -55,6 +72,8 @@ public class DpnTepStateCache extends DataObjectCache<BigInteger, DpnsTeps> {
                     .setIsMonitoringEnabled(remoteDpns.isInternal())
                     .setTunnelType(dpnsTeps.getTunnelType()).build();
             dpnTepInterfaceMap.put(dpn, value);
+            addTunnelEndPointInfoToCache(remoteDpns.getTunnelName(),
+                    dpnsTeps.getSourceDpnId().toString(), remoteDpns.getDestinationDpnId().toString());
         }
     }
 
@@ -62,9 +81,14 @@ public class DpnTepStateCache extends DataObjectCache<BigInteger, DpnsTeps> {
     protected void removed(InstanceIdentifier<DpnsTeps> path, DpnsTeps dpnsTeps) {
         for (RemoteDpns remoteDpns : dpnsTeps.getRemoteDpns()) {
             dpnTepInterfaceMap.remove(getDpnId(dpnsTeps.getSourceDpnId(), remoteDpns.getDestinationDpnId()));
+            tunnelEndpointMap.remove(remoteDpns.getTunnelName());
         }
     }
 
+    private DpnTepInterfaceInfo getDpnTepInterface(String srcDpnId, String dstDpnId) {
+        return getDpnTepInterface(new BigInteger(srcDpnId), new BigInteger(dstDpnId));
+    }
+
     public DpnTepInterfaceInfo getDpnTepInterface(BigInteger srcDpnId, BigInteger dstDpnId) {
         DpnTepInterfaceInfo  dpnTepInterfaceInfo = dpnTepInterfaceMap.get(getDpnId(srcDpnId, dstDpnId));
         if (dpnTepInterfaceInfo == null) {
@@ -72,24 +96,126 @@ public class DpnTepStateCache extends DataObjectCache<BigInteger, DpnsTeps> {
                 Optional<DpnsTeps> dpnsTeps = super.get(srcDpnId);
                 if (dpnsTeps.isPresent()) {
                     DpnsTeps teps = dpnsTeps.get();
-                    teps.getRemoteDpns().forEach(remoteDpns
-                        -> dpnTepInterfaceMap.putIfAbsent(getDpnId(srcDpnId, remoteDpns.getDestinationDpnId()),
-                        new DpnTepInterfaceInfoBuilder()
-                            .setTunnelName(remoteDpns.getTunnelName())
-                            .setGroupId(teps.getGroupId())
-                            .setIsMonitoringEnabled(remoteDpns.isMonitoringEnabled())
-                            .setIsMonitoringEnabled(remoteDpns.isInternal())
-                            .setTunnelType(teps.getTunnelType()).build()
-                        ));
+                    teps.getRemoteDpns().forEach(remoteDpns -> {
+                        DpnTepInterfaceInfo value = new DpnTepInterfaceInfoBuilder()
+                                .setTunnelName(remoteDpns.getTunnelName())
+                                .setGroupId(teps.getGroupId())
+                                .setIsMonitoringEnabled(remoteDpns.isMonitoringEnabled())
+                                .setIsMonitoringEnabled(remoteDpns.isInternal())
+                                .setTunnelType(teps.getTunnelType()).build();
+                        dpnTepInterfaceMap.putIfAbsent(getDpnId(srcDpnId, remoteDpns.getDestinationDpnId()), value);
+                        addTunnelEndPointInfoToCache(remoteDpns.getTunnelName(),
+                                teps.getSourceDpnId().toString(), remoteDpns.getDestinationDpnId().toString());
+                        }
+                    );
                 }
             } catch (ReadFailedException e) {
-                LOG.debug("cache read for dpnID {} in DpnTepStateCache failed", srcDpnId);
+                LOG.error("cache read for dpnID {} in DpnTepStateCache failed ", srcDpnId, e);
             }
         }
         return dpnTepInterfaceMap.get(getDpnId(srcDpnId, dstDpnId));
     }
 
-    private static String getDpnId(BigInteger src, BigInteger dst) {
+    public void removeTepFromDpnTepInterfaceConfigDS(BigInteger srcDpnId) throws TransactionCommitFailedException {
+        Collection<DpnsTeps> dpnsTeps = this.getAllPresent();
+        for (DpnsTeps dpnTep : dpnsTeps) {
+            if (!dpnTep.getSourceDpnId().equals(srcDpnId)) {
+                List<RemoteDpns> remoteDpns = dpnTep.getRemoteDpns();
+                for (RemoteDpns remoteDpn : remoteDpns) {
+                    if (remoteDpn.getDestinationDpnId().equals(srcDpnId)) {
+                        // Remote the SrcDpnId from the remote List. Remove it from COnfig DS. 4
+                        // This will be reflected in cache by the ClusteredDTCN. Not removing it here !
+                        //Caution :- Batching Delete !!
+                        InstanceIdentifier<RemoteDpns> remoteDpnII =
+                                buildRemoteDpnsInstanceIdentifier(dpnTep.getSourceDpnId(),
+                                        remoteDpn.getDestinationDpnId());
+                        SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                                remoteDpnII);
+                        break;
+                    }
+                }
+            } else {
+                // The source DPn id is the one to be removed
+                InstanceIdentifier<DpnsTeps> dpnsTepsII = buildDpnsTepsInstanceIdentifier(dpnTep.getSourceDpnId());
+                SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, dpnsTepsII);
+            }
+        }
+    }
+
+    private InstanceIdentifier<DpnsTeps> buildDpnsTepsInstanceIdentifier(BigInteger srcDpnId) {
+        return InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class, new DpnsTepsKey(srcDpnId)).build();
+    }
+
+    private InstanceIdentifier<RemoteDpns> buildRemoteDpnsInstanceIdentifier(BigInteger srcDpnId, BigInteger dstDpnId) {
+        DpnsTepsKey dpnsTepsKey = new DpnsTepsKey(srcDpnId);
+        RemoteDpnsKey remoteDpnsKey = new RemoteDpnsKey(dstDpnId);
+        return InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class, dpnsTepsKey)
+                .child(RemoteDpns.class, remoteDpnsKey).build();
+    }
+
+    // Given the tunnel name find out if its internal or external
+    public boolean isInternal(String tunnelName) {
+        TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
+        if (endPointInfo != null) {
+            DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(endPointInfo.getSrcEndPointInfo(),
+                    endPointInfo.getDstEndPointInfo());
+            return dpnTepInfo != null && dpnTepInfo.isInternal();
+        }
+        return false;
+    }
+
+    public boolean isConfigAvailable(String tunnelName) {
+        TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
+        if (endPointInfo != null) {
+            DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(endPointInfo.getDstEndPointInfo(),
+                    endPointInfo.getDstEndPointInfo());
+            return dpnTepInfo != null;
+        }
+        return false;
+    }
+
+    public DpnTepInterfaceInfo getTunnelFromCache(String tunnelName) {
+        TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
+        return getDpnTepInterface(endPointInfo.getDstEndPointInfo(), endPointInfo.getDstEndPointInfo());
+    }
+
+    private String getDpnId(BigInteger src, BigInteger dst) {
         return src + ":" + dst;
     }
+
+    public Interface getInterfaceFromCache(String tunnelName) {
+        TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
+        BigInteger srcDpnId = new BigInteger(endPointInfo.getSrcEndPointInfo());
+        BigInteger dstDpnId = new BigInteger(endPointInfo.getDstEndPointInfo());
+        Interface iface = null ;
+        int monitoringInt = 1000;
+        DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(srcDpnId, dstDpnId);
+        if (dpnTepInfo != null) {
+            List<DPNTEPsInfo> srcDpnTEPsInfo = dpnTepsInfoCache
+                    .getDPNTepListFromDPNId(Collections.singletonList(srcDpnId));
+            List<DPNTEPsInfo> dstDpnTEPsInfo = dpnTepsInfoCache
+                    .getDPNTepListFromDPNId(Collections.singletonList(dstDpnId));
+            iface = ItmUtils.buildTunnelInterface(srcDpnId, tunnelName,
+                    String.format("%s %s", ItmUtils.convertTunnelTypetoString(dpnTepInfo.getTunnelType()),
+                            "Trunk Interface"), true, dpnTepInfo.getTunnelType(),
+                    srcDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getIpAddress(),
+                    dstDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getIpAddress(),
+                    srcDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getGwIpAddress(),
+                    srcDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getVLANID(), true,
+                    dpnTepInfo.isMonitoringEnabled(), TunnelMonitoringTypeBfd.class,
+                    monitoringInt, true, null);
+        }
+        return iface;
+    }
+
+    //Start: TunnelEndPoint Cache accessors
+    private void addTunnelEndPointInfoToCache(String tunnelName, String srcEndPtInfo, String dstEndPtInfo) {
+        TunnelEndPointInfo tunnelEndPointInfo = new TunnelEndPointInfoBuilder().setSrcEndPointInfo(srcEndPtInfo)
+                .setDstEndPointInfo(dstEndPtInfo).build();
+        tunnelEndpointMap.put(tunnelName, tunnelEndPointInfo);
+    }
+
+    public TunnelEndPointInfo getTunnelEndPointInfoFromCache(String tunnelName) {
+        return tunnelEndpointMap.get(tunnelName);
+    }
 }
index 7c57e38a587d647c38c90a84950252a8ef3915b8..bbd0af9b992640076daddcab86dc9de4185efd93 100644 (file)
@@ -7,14 +7,19 @@
  */
 package org.opendaylight.genius.itm.cache;
 
+import com.google.common.base.Optional;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.genius.itm.globals.ITMConstants;
 import org.opendaylight.genius.mdsalutil.cache.InstanceIdDataObjectCache;
 import org.opendaylight.infrautils.caches.CacheProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
 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.yangtools.yang.binding.InstanceIdentifier;
 
 /**
@@ -30,4 +35,23 @@ public class TunnelStateCache extends InstanceIdDataObjectCache<StateTunnelList>
         super(StateTunnelList.class, dataBroker, LogicalDatastoreType.OPERATIONAL,
                 InstanceIdentifier.builder(TunnelsState.class).child(StateTunnelList.class).build(), cacheProvider);
     }
+
+    public boolean isInternalBasedOnState(String tunnelName) throws ReadFailedException {
+        Optional<StateTunnelList> stateTunnelList = get(getStateTunnelListIdentifier(tunnelName));
+        return stateTunnelList.isPresent() && TepTypeInternal.class
+                .equals(stateTunnelList.get().getDstInfo().getTepDeviceType());
+    }
+
+    public long getNodeConnectorIdFromInterface(String interfaceName) throws ReadFailedException {
+        Optional<StateTunnelList> stateTnl = get(getStateTunnelListIdentifier(interfaceName));
+        if (stateTnl.isPresent()) {
+            return Long.parseLong(stateTnl.get().getPortNumber());
+        }
+        return ITMConstants.INVALID_PORT_NO;
+    }
+
+    public InstanceIdentifier<StateTunnelList> getStateTunnelListIdentifier(String key) {
+        return InstanceIdentifier.builder(TunnelsState.class).child(StateTunnelList.class, new StateTunnelListKey(key))
+                .build();
+    }
 }
diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/UnprocessedNodeConnectorCache.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/UnprocessedNodeConnectorCache.java
new file mode 100644 (file)
index 0000000..5cb1410
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.cache;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import javax.inject.Singleton;
+import org.opendaylight.genius.itm.utils.NodeConnectorInfo;
+
+@Singleton
+public class UnprocessedNodeConnectorCache {
+
+    private final ConcurrentMap<String, NodeConnectorInfo> unprocessedNodeConnectorMap = new ConcurrentHashMap();
+
+    public void add(String tunnelName, NodeConnectorInfo ncInfo) {
+        unprocessedNodeConnectorMap.put(tunnelName, ncInfo);
+    }
+
+    public NodeConnectorInfo get(String tunnelName) {
+        return unprocessedNodeConnectorMap.get(tunnelName);
+    }
+
+    public void remove(String tunnelName) {
+        unprocessedNodeConnectorMap.remove(tunnelName);
+    }
+}
diff --git a/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/UnprocessedNodeConnectorEndPointCache.java b/itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/UnprocessedNodeConnectorEndPointCache.java
new file mode 100644 (file)
index 0000000..e09d1d3
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.cache;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import javax.inject.Singleton;
+import org.opendaylight.genius.itm.utils.NodeConnectorInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class UnprocessedNodeConnectorEndPointCache {
+
+    private static final Logger LOG = LoggerFactory.getLogger(UnprocessedNodeConnectorEndPointCache.class);
+
+    private final ConcurrentMap<String, Set<NodeConnectorInfo>> unProcessedNodeConnectorEndPtMap =
+            new ConcurrentHashMap();
+
+    public void add(String dpnId, Collection<NodeConnectorInfo> ncList) {
+        unProcessedNodeConnectorEndPtMap.computeIfAbsent(dpnId, key -> ConcurrentHashMap.newKeySet()).addAll(ncList);
+    }
+
+    public void add(String dpnId, NodeConnectorInfo ncInfo) {
+        unProcessedNodeConnectorEndPtMap.computeIfAbsent(dpnId, key -> ConcurrentHashMap.newKeySet()).add(ncInfo);
+    }
+
+    public void remove(String dpnId) {
+        unProcessedNodeConnectorEndPtMap.remove(dpnId);
+    }
+
+    public void remove(String dpnId, NodeConnectorInfo ncInfo) {
+        Collection<NodeConnectorInfo> ncList = get(dpnId);
+        if (ncList != null) {
+            ncList.remove(ncInfo);
+        } else {
+            LOG.debug("NodeConnectorInfo List for DPN Id {} is null", dpnId);
+        }
+    }
+
+    public Collection<NodeConnectorInfo> get(String dpnId) {
+        return unProcessedNodeConnectorEndPtMap.get(dpnId);
+    }
+}
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
new file mode 100644 (file)
index 0000000..41ed016
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * 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.renderer.ovs.utilities;
+
+import com.google.common.base.Optional;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.itm.cache.DpnTepStateCache;
+import org.opendaylight.genius.itm.cache.TunnelStateCache;
+import org.opendaylight.genius.itm.globals.ITMConstants;
+import org.opendaylight.genius.itm.impl.ItmUtils;
+import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
+import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
+import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+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.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.OvsBridgeRefInfo;
+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.OvsBridgeRefEntryBuilder;
+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.TunnelOperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public final class DirectTunnelUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DirectTunnelUtils.class);
+    private static final String ENTITY = "ovsBridgeRefEntryOperation";
+
+    private final DataBroker dataBroker;
+    private final JobCoordinator jobCoordinator;
+    private final ManagedNewTransactionRunner txRunner;
+    private final DpnTepStateCache dpnTepStateCache;
+    private final TunnelStateCache tunnelStateCache;
+
+    @Inject
+    public DirectTunnelUtils(DataBroker dataBroker, JobCoordinator jobCoordinator, DpnTepStateCache dpnTepStateCache,
+                             TunnelStateCache tunnelStateCache) {
+        this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+        this.jobCoordinator = jobCoordinator;
+        this.dpnTepStateCache = dpnTepStateCache;
+        this.tunnelStateCache = tunnelStateCache;
+    }
+
+    public BigInteger getDpnId(DatapathId datapathId) {
+        if (datapathId != null) {
+            String dpIdStr = datapathId.getValue().replace(":", "");
+            return new BigInteger(dpIdStr, 16);
+        }
+        return null;
+    }
+
+    public static BigInteger getDpnFromNodeConnectorId(NodeConnectorId portId) {
+        /*
+         * NodeConnectorId is of form 'openflow:dpnid:portnum'
+         */
+        return new BigInteger(portId.getValue().split(ITMConstants.OF_URI_SEPARATOR)[1]);
+    }
+
+    public static long getPortNumberFromNodeConnectorId(NodeConnectorId portId) {
+        String portNo = getPortNoFromNodeConnectorId(portId);
+        try {
+            return Long.parseLong(portNo);
+        } catch (NumberFormatException ex) {
+            LOG.error("Unable to retrieve port number from nodeconnector id for {} ", portId, ex);
+            return ITMConstants.INVALID_PORT_NO;
+        }
+    }
+
+    private static String getPortNoFromNodeConnectorId(NodeConnectorId portId) {
+        /*
+         * NodeConnectorId is of form 'openflow:dpnid:portnum'
+         */
+        return portId.getValue().split(ITMConstants.OF_URI_SEPARATOR)[2];
+    }
+
+    public static NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) {
+        return new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":")));
+    }
+
+    public static String generateMacAddress(long portNo) {
+        String unformattedMAC = getDeadBeefBytesForMac().or(fillPortNumberToMac(portNo)).toString(16);
+        return unformattedMAC.replaceAll("(.{2})", "$1" + ITMConstants.MAC_SEPARATOR)
+                .substring(0, ITMConstants.MAC_STRING_LENGTH);
+    }
+
+    private static BigInteger getDeadBeefBytesForMac() {
+        return new BigInteger("FFFFFFFF", 16).and(new BigInteger(ITMConstants.DEAD_BEEF_MAC_PREFIX, 16)).shiftLeft(16);
+    }
+
+    private static BigInteger fillPortNumberToMac(long portNumber) {
+        return new BigInteger("FFFF", 16).and(BigInteger.valueOf(portNumber));
+    }
+
+    // Convert Interface Oper State to Tunnel Oper state
+    public static TunnelOperStatus convertInterfaceToTunnelOperState(Interface.OperStatus opState) {
+
+        java.util.Optional<TunnelOperStatus> tunnelOperStatus = TunnelOperStatus.forName(opState.getName());
+        if (tunnelOperStatus.isPresent()) {
+            return tunnelOperStatus.get();
+        }
+        return TunnelOperStatus.Ignore;
+    }
+
+    public void createOvsBridgeRefEntry(BigInteger dpnId, InstanceIdentifier<?> bridgeIid) {
+        LOG.debug("Creating bridge ref entry for dpn: {} bridge: {}", dpnId, bridgeIid);
+        OvsBridgeRefEntryKey bridgeRefEntryKey = new OvsBridgeRefEntryKey(dpnId);
+        InstanceIdentifier<OvsBridgeRefEntry> bridgeEntryId = getOvsBridgeRefEntryIdentifier(bridgeRefEntryKey);
+        OvsBridgeRefEntryBuilder tunnelDpnBridgeEntryBuilder = new OvsBridgeRefEntryBuilder().setKey(bridgeRefEntryKey)
+                .setDpid(dpnId).setOvsBridgeReference(new OvsdbBridgeRef(bridgeIid));
+        jobCoordinator.enqueueJob(ENTITY,
+            () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx
+                -> tx.put(LogicalDatastoreType.OPERATIONAL, bridgeEntryId, tunnelDpnBridgeEntryBuilder.build(),
+                    true))));
+
+    }
+
+    public void deleteOvsBridgeRefEntry(BigInteger dpnId) {
+        LOG.debug("Deleting bridge ref entry for dpn: {}", dpnId);
+        OvsBridgeRefEntryKey bridgeRefEntryKey = new OvsBridgeRefEntryKey(dpnId);
+        InstanceIdentifier<OvsBridgeRefEntry> bridgeEntryId = getOvsBridgeRefEntryIdentifier(bridgeRefEntryKey);
+        jobCoordinator.enqueueJob(ENTITY,
+            () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx
+                -> tx.delete(LogicalDatastoreType.OPERATIONAL, bridgeEntryId))));
+    }
+
+    private static InstanceIdentifier<OvsBridgeRefEntry>
+        getOvsBridgeRefEntryIdentifier(OvsBridgeRefEntryKey bridgeRefEntryKey) {
+        return InstanceIdentifier.builder(OvsBridgeRefInfo.class)
+                .child(OvsBridgeRefEntry.class, bridgeRefEntryKey).build();
+    }
+
+    public boolean isNodeConnectorPresent(NodeConnectorId nodeConnectorId) throws ReadFailedException {
+        NodeId nodeId = getNodeIdFromNodeConnectorId(nodeConnectorId);
+        InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                        new NodeKey(nodeId))
+                .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)).build();
+        return SingleTransactionDataBroker
+                .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, ncIdentifier).isPresent();
+    }
+
+    public boolean isNodePresent(NodeConnectorId nodeConnectorId) throws ReadFailedException {
+        NodeId nodeID = getNodeIdFromNodeConnectorId(nodeConnectorId);
+        InstanceIdentifier<Node> nodeInstanceIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class,
+                new NodeKey(nodeID)).build();
+        return SingleTransactionDataBroker
+                .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, nodeInstanceIdentifier).isPresent();
+    }
+
+    public List<Action> getEgressActionsForInterface(String interfaceName, long tunnelKey, Integer actionKey) {
+        List<ActionInfo> listActionInfo = getEgressActionInfosForInterface(interfaceName, tunnelKey,
+                actionKey == null ? 0 : actionKey);
+        return listActionInfo.stream().map(ActionInfo::buildAction).collect(Collectors.toList());
+    }
+
+    private List<ActionInfo> getEgressActionInfosForInterface(String interfaceName, long tunnelKey,
+                                                              int actionKeyStart) {
+        DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
+        if (interfaceInfo == null) {
+            LOG.error("Interface information not present in config DS for {}", interfaceName);
+            return Collections.singletonList(new ActionDrop());
+        }
+        Optional<StateTunnelList> ifState;
+        try {
+            ifState = tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
+        } catch (ReadFailedException e) {
+            LOG.error("Interface information not present in oper DS for {} ", interfaceName, e);
+            return Collections.singletonList(new ActionDrop());
+        }
+        if (ifState.isPresent()) {
+            String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
+            return getEgressActionInfosForInterface(tunnelType, ifState.get().getPortNumber(), tunnelKey,
+                    actionKeyStart);
+        }
+        LOG.error("Interface information not present in oper DS for {}", interfaceName);
+        return Collections.singletonList(new ActionDrop());
+    }
+
+
+    private static List<ActionInfo> getEgressActionInfosForInterface(String tunnelType, String portNo, Long tunnelKey,
+                                                                    int actionKeyStart) {
+        List<ActionInfo> result = new ArrayList<>();
+        switch (tunnelType) {
+            case ITMConstants.TUNNEL_TYPE_GRE:
+            case ITMConstants.TUNNEL_TYPE_MPLSoGRE:
+                // Invoke IFM RPC and pass it on to the caller.
+                LOG.warn("Interface Type {} not handled by ITM", tunnelType);
+                break;
+            case ITMConstants.TUNNEL_TYPE_VXLAN:
+                //TODO tunnel_id to encode GRE key, once it is supported
+                // Until then, tunnel_id should be "cleaned", otherwise it stores the value coming from a VXLAN tunnel
+                result.add(new ActionSetFieldTunnelId(actionKeyStart++,
+                        BigInteger.valueOf(tunnelKey != null ? tunnelKey : 0L)));
+                result.add(new ActionOutput(actionKeyStart, new Uri(portNo)));
+                break;
+
+            default:
+                LOG.warn("Interface Type {} not handled yet", tunnelType);
+                break;
+        }
+        return result;
+    }
+}
\ No newline at end of file