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 = ":";
}
--- /dev/null
+/*
+ * 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);
+ }
+}
*/
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;
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();
+ }
}
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;
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;
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
.setIsMonitoringEnabled(remoteDpns.isInternal())
.setTunnelType(dpnsTeps.getTunnelType()).build();
dpnTepInterfaceMap.put(dpn, value);
+ addTunnelEndPointInfoToCache(remoteDpns.getTunnelName(),
+ dpnsTeps.getSourceDpnId().toString(), remoteDpns.getDestinationDpnId().toString());
}
}
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) {
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);
+ }
}
*/
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;
/**
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();
+ }
}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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