X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=elanmanager%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Felan%2Futils%2FElanUtils.java;h=a25c8a25eed3c7b10a2475eca48ccbe96fbee4e6;hb=be1b0517d62d3aa1a21062363b21f6d9f4da4fba;hp=6076f036c66448a11ac14b9ddbb07445649adcbf;hpb=8fdc9ce06cb607037902c9b7ac293fcbd3727962;p=netvirt.git diff --git a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java index 6076f036c6..a25c8a25ee 100755 --- a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java +++ b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java @@ -7,6 +7,10 @@ */ package org.opendaylight.netvirt.elan.utils; +import static java.util.Collections.emptyList; +import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS; +import static org.opendaylight.genius.infra.Datastore.CONFIGURATION; + import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -17,30 +21,37 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Singleton; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.ReadTransaction; 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.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.genius.infra.Datastore; +import org.opendaylight.genius.infra.Datastore.Configuration; +import org.opendaylight.genius.infra.Datastore.Operational; import org.opendaylight.genius.infra.ManagedNewTransactionRunner; import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; +import org.opendaylight.genius.infra.TypedReadTransaction; +import org.opendaylight.genius.infra.TypedReadWriteTransaction; +import org.opendaylight.genius.infra.TypedWriteTransaction; import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo; -import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil; import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; +import org.opendaylight.genius.itm.api.IITMProvider; import org.opendaylight.genius.itm.globals.ITMConstants; import org.opendaylight.genius.mdsalutil.ActionInfo; import org.opendaylight.genius.mdsalutil.FlowEntity; @@ -62,9 +73,9 @@ import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId; import org.opendaylight.genius.mdsalutil.packet.ARP; import org.opendaylight.genius.mdsalutil.packet.Ethernet; import org.opendaylight.genius.mdsalutil.packet.IPv4; -import org.opendaylight.infrautils.utils.concurrent.JdkFutures; -import org.opendaylight.infrautils.utils.concurrent.ListenableFutures; -import org.opendaylight.netvirt.elan.ElanException; +import org.opendaylight.infrautils.utils.concurrent.LoggingFutures; +import org.opendaylight.infrautils.utils.concurrent.NamedLocks; +import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired; import org.opendaylight.netvirt.elan.arp.responder.ArpResponderUtil; import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache; import org.opendaylight.netvirt.elanmanager.api.ElanHelper; @@ -118,6 +129,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.I import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; 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.nodes.Node; @@ -133,7 +147,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev16061 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagNameBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaceForwardingEntries; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanState; @@ -177,8 +190,38 @@ import org.slf4j.LoggerFactory; @Singleton public class ElanUtils { + private static final class ElanLockName { + private final String macAddress; + private final BigInteger dpnId; + private final long elanTag; + + ElanLockName(long elanTag, String macAddress, BigInteger dpnId) { + this.elanTag = elanTag; + this.macAddress = macAddress; + this.dpnId = dpnId; + } + + @Override + public int hashCode() { + return 31 * Long.hashCode(elanTag) + Objects.hash(macAddress, dpnId); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ElanLockName)) { + return false; + } + final ElanLockName other = (ElanLockName) obj; + return elanTag == other.elanTag && Objects.equals(macAddress, other.macAddress) + && Objects.equals(dpnId, other.dpnId); + } + } private static final Logger LOG = LoggerFactory.getLogger(ElanUtils.class); + private static final NamedLocks ELAN_LOCKS = new NamedLocks<>(); private final DataBroker broker; private final ManagedNewTransactionRunner txRunner; @@ -190,6 +233,7 @@ public class ElanUtils { private final ElanItmUtils elanItmUtils; private final ElanEtreeUtils elanEtreeUtils; private final ElanInterfaceCache elanInterfaceCache; + private final IITMProvider iitmProvider; public static final FutureCallback DEFAULT_CALLBACK = new FutureCallback() { @Override @@ -207,7 +251,7 @@ public class ElanUtils { public ElanUtils(DataBroker dataBroker, IMdsalApiManager mdsalManager, OdlInterfaceRpcService interfaceManagerRpcService, ItmRpcService itmRpcService, ElanConfig elanConfig, IInterfaceManager interfaceManager, ElanEtreeUtils elanEtreeUtils, ElanItmUtils elanItmUtils, - ElanInterfaceCache elanInterfaceCache) { + ElanInterfaceCache elanInterfaceCache, IITMProvider iitmProvider) { this.broker = dataBroker; this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); this.mdsalManager = mdsalManager; @@ -218,6 +262,7 @@ public class ElanUtils { this.elanEtreeUtils = elanEtreeUtils; this.elanItmUtils = elanItmUtils; this.elanInterfaceCache = elanInterfaceCache; + this.iitmProvider = iitmProvider; } public final Boolean isOpenstackVniSemanticsEnforced() { @@ -255,7 +300,7 @@ public class ElanUtils { public static void releaseId(IdManagerService idManager, String poolName, String idKey) { ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build(); - JdkFutures.addErrorLogging(idManager.releaseId(releaseIdInput), LOG, "Release Id"); + LoggingFutures.addErrorLogging(idManager.releaseId(releaseIdInput), LOG, "Release Id"); } /** @@ -271,7 +316,7 @@ public class ElanUtils { */ @Deprecated @SuppressWarnings("checkstyle:IllegalCatch") - public static Optional read(@Nonnull DataBroker broker, + public static Optional read(@NonNull DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path) { try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) { return tx.read(datastoreType, path).get(); @@ -288,7 +333,7 @@ public class ElanUtils { } } - @SuppressWarnings("checkstyle:ForbiddenMethod") + @SuppressWarnings("checkstyle:ForbidCertainMethod") public static void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path) { WriteTransaction tx = broker.newWriteOnlyTransaction(); @@ -296,33 +341,22 @@ public class ElanUtils { Futures.addCallback(tx.submit(), DEFAULT_CALLBACK, MoreExecutors.directExecutor()); } - @SuppressWarnings("checkstyle:ForbiddenMethod") - public static void delete(DataBroker broker, LogicalDatastoreType datastoreType, - InstanceIdentifier path, FutureCallback callback) { - WriteTransaction tx = broker.newWriteOnlyTransaction(); - tx.delete(datastoreType, path); - Futures.addCallback(tx.submit(), callback, MoreExecutors.directExecutor()); - } - - public static InstanceIdentifier getElanInstanceIdentifier() { - return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class).build(); - } - public static InstanceIdentifier getElanInterfaceConfigurationDataPathId(String interfaceName) { return InstanceIdentifier.builder(ElanInterfaces.class) .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build(); } // elan-state Operational container + @Nullable public static Elan getElanByName(DataBroker broker, String elanInstanceName) { InstanceIdentifier elanIdentifier = getElanInstanceOperationalDataPath(elanInstanceName); return MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanIdentifier).orNull(); } @Nullable - public static Elan getElanByName(ReadTransaction tx, String elanInstanceName) throws ReadFailedException { - return tx.read(LogicalDatastoreType.OPERATIONAL, - getElanInstanceOperationalDataPath(elanInstanceName)).checkedGet().orNull(); + public static Elan getElanByName(TypedReadTransaction tx, String elanInstanceName) + throws ExecutionException, InterruptedException { + return tx.read(getElanInstanceOperationalDataPath(elanInstanceName)).get().orNull(); } public static InstanceIdentifier getElanInstanceOperationalDataPath(String elanInstanceName) { @@ -330,16 +364,17 @@ public class ElanUtils { } // grouping of forwarding-entries + @Nullable public MacEntry getInterfaceMacEntriesOperationalDataPath(String interfaceName, PhysAddress physAddress) { InstanceIdentifier existingMacEntryId = getInterfaceMacEntriesIdentifierOperationalDataPath( interfaceName, physAddress); return read(broker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId).orNull(); } - public MacEntry getInterfaceMacEntriesOperationalDataPathFromId(InstanceIdentifier identifier) { - Optional existingInterfaceMacEntry = read(broker, - LogicalDatastoreType.OPERATIONAL, identifier); - return existingInterfaceMacEntry.orNull(); + @Nullable + public MacEntry getInterfaceMacEntriesOperationalDataPathFromId(TypedReadTransaction tx, + InstanceIdentifier identifier) throws ExecutionException, InterruptedException { + return tx.read(identifier).get().orNull(); } public static InstanceIdentifier getInterfaceMacEntriesIdentifierOperationalDataPath(String interfaceName, @@ -356,16 +391,16 @@ public class ElanUtils { return read(broker, LogicalDatastoreType.OPERATIONAL, macId); } - public Optional getMacEntryForElanInstance(ReadTransaction tx, String elanName, PhysAddress physAddress) - throws ReadFailedException { + public Optional getMacEntryForElanInstance(TypedReadTransaction tx, String elanName, + PhysAddress physAddress) throws ExecutionException, InterruptedException { InstanceIdentifier macId = getMacEntryOperationalDataPath(elanName, physAddress); - return tx.read(LogicalDatastoreType.OPERATIONAL, macId).checkedGet(); + return tx.read(macId).get(); } - public MacEntry getMacEntryFromElanMacId(InstanceIdentifier identifier) { - Optional existingInterfaceMacEntry = read(broker, - LogicalDatastoreType.OPERATIONAL, identifier); - return existingInterfaceMacEntry.orNull(); + @Nullable + public MacEntry getMacEntryFromElanMacId(TypedReadTransaction tx, + InstanceIdentifier identifier) throws ExecutionException, InterruptedException { + return tx.read(identifier).get().orNull(); } public static InstanceIdentifier getMacEntryOperationalDataPath(String elanName, @@ -391,25 +426,6 @@ public class ElanUtils { return read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId).orNull(); } - /** - * Gets the elan interface mac addresses. - * - * @param interfaceName - * the interface name - * @return the elan interface mac addresses - */ - public List getElanInterfaceMacAddresses(String interfaceName) { - List macAddresses = new ArrayList<>(); - ElanInterfaceMac elanInterfaceMac = getElanInterfaceMacByInterfaceName(interfaceName); - if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) { - List macEntries = elanInterfaceMac.getMacEntry(); - for (MacEntry macEntry : macEntries) { - macAddresses.add(macEntry.getMacAddress()); - } - } - return macAddresses; - } - public static InstanceIdentifier getElanInterfaceMacEntriesOperationalDataPath( String interfaceName) { return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class) @@ -418,7 +434,7 @@ public class ElanUtils { /** * Returns the list of Interfaces that belong to an Elan on an specific DPN. - * Data retrieved from Elan's operational DS: elan-dpn-interfaces container + * Data retrieved from Elan's operational DS: elan-dpn-interfaces container. * * @param elanInstanceName * name of the Elan to which the interfaces must belong to @@ -426,6 +442,7 @@ public class ElanUtils { * Id of the DPN where the interfaces are located * @return the elan interface Info */ + @Nullable public DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) { InstanceIdentifier elanDpnInterfacesId = getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId); @@ -451,6 +468,7 @@ public class ElanUtils { } // elan-tag-name-map Operational Container + @Nullable public ElanTagName getElanInfoByElanTag(long elanTag) { InstanceIdentifier elanId = getElanInfoEntriesOperationalDataPath(elanTag); Optional existingElanInfo = read(broker, @@ -479,11 +497,13 @@ public class ElanUtils { .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build(); } + @Nullable public ElanDpnInterfacesList getElanDpnInterfacesList(String elanName) { InstanceIdentifier elanDpnInterfaceId = getElanDpnOperationDataPath(elanName); return read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId).orNull(); } + @Nullable public ElanDpnInterfaces getElanDpnInterfacesList() { InstanceIdentifier elanDpnInterfaceId = InstanceIdentifier.builder(ElanDpnInterfaces.class) .build(); @@ -499,7 +519,7 @@ public class ElanUtils { * the elan instance name * @return list of dpIds */ - @Nonnull + @NonNull public List getParticipatingDpnsInElanInstance(String elanInstanceName) { List dpIds = new ArrayList<>(); InstanceIdentifier elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName); @@ -508,46 +528,13 @@ public class ElanUtils { if (!existingElanDpnInterfaces.isPresent()) { return dpIds; } - List dpnInterfaces = existingElanDpnInterfaces.get().getDpnInterfaces(); + List dpnInterfaces = existingElanDpnInterfaces.get().nonnullDpnInterfaces(); for (DpnInterfaces dpnInterface : dpnInterfaces) { dpIds.add(dpnInterface.getDpId()); } return dpIds; } - /** - * To check given dpId is already present in Elan instance. This can be used - * to program flow entry in external tunnel table when a new access port - * added for first time into the ELAN instance - * - * @param dpId - * the dp id - * @param elanInstanceName - * the elan instance name - * @return true if dpId is already present, otherwise return false - */ - public boolean isDpnAlreadyPresentInElanInstance(BigInteger dpId, String elanInstanceName) { - InstanceIdentifier elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName); - Optional existingElanDpnInterfaces = read(broker, - LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId); - if (!existingElanDpnInterfaces.isPresent()) { - return false; - } - List dpnInterfaces = existingElanDpnInterfaces.get().getDpnInterfaces(); - for (DpnInterfaces dpnInterface : dpnInterfaces) { - if (dpnInterface.getDpId().equals(dpId)) { - return true; - } - } - return false; - } - - public ElanForwardingTables getElanForwardingList() { - InstanceIdentifier elanForwardingTableId = InstanceIdentifier - .builder(ElanForwardingTables.class).build(); - return read(broker, LogicalDatastoreType.OPERATIONAL, elanForwardingTableId).orNull(); - } - public static long getElanRemoteBroadCastGroupID(long elanTag) { return ElanConstants.ELAN_GID_MIN + elanTag % ElanConstants.ELAN_GID_MIN * 2; } @@ -559,6 +546,7 @@ public class ElanUtils { * the elan name * @return the elan mac table */ + @Nullable public MacTable getElanMacTable(String elanName) { return getElanMacTable(broker, elanName); } @@ -605,12 +593,11 @@ public class ElanUtils { * true if remote dmac flows should be configured as well * @param writeFlowGroupTx * the flow group tx - * @throws ElanException in case of issues creating the flow objects */ public void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout, String macAddress, boolean configureRemoteFlows, - WriteTransaction writeFlowGroupTx) throws ElanException { - synchronized (getElanMacDPNKey(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) { + TypedWriteTransaction writeFlowGroupTx) { + try (Acquired lock = lockElanMacDPN(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) { setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, mdsalManager, writeFlowGroupTx); setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, configureRemoteFlows, mdsalManager, @@ -619,7 +606,7 @@ public class ElanUtils { } public void setupDMacFlowOnRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId, - String macAddress, WriteTransaction writeFlowTx) throws ElanException { + String macAddress, TypedWriteTransaction writeFlowTx) { String elanInstanceName = elanInfo.getElanInstanceName(); setupRemoteDmacFlow(dstDpId, interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag(), elanInfo.getElanTag(), macAddress, elanInstanceName, writeFlowTx, interfaceInfo.getInterfaceName(), elanInfo); @@ -633,9 +620,10 @@ public class ElanUtils { * learnt. */ private void setupKnownSmacFlow(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout, - String macAddress, IMdsalApiManager mdsalApiManager, WriteTransaction writeFlowGroupTx) { + String macAddress, IMdsalApiManager mdsalApiManager, + TypedWriteTransaction writeFlowGroupTx) { FlowEntity flowEntity = buildKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress); - mdsalApiManager.addFlowToTx(flowEntity, writeFlowGroupTx); + mdsalApiManager.addFlow(writeFlowGroupTx, flowEntity); LOG.debug("Known Smac flow entry created for elan Name:{}, logical Interface port:{} and mac address:{}", elanInfo.getElanInstanceName(), elanInfo.getDescription(), macAddress); } @@ -674,7 +662,7 @@ public class ElanUtils { if (etreeInterface == null || etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) { return elanInfo.getElanTag(); } else { // Leaf - EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class); + EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class); if (etreeInstance == null) { LOG.warn("EtreeInterface {} is connected to a non-Etree network: {}", interfaceInfo.getInterfaceName(), elanInfo.getElanInstanceName()); @@ -698,7 +686,7 @@ public class ElanUtils { * the writeFLowGroup tx */ public void setupTermDmacFlows(InterfaceInfo interfaceInfo, IMdsalApiManager mdsalApiManager, - WriteTransaction writeFlowGroupTx) { + TypedWriteTransaction writeFlowGroupTx) { BigInteger dpId = interfaceInfo.getDpId(); int lportTag = interfaceInfo.getInterfaceTag(); Flow flow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, @@ -707,7 +695,7 @@ public class ElanUtils { ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(lportTag)), getTunnelIdMatchForFilterEqualsLPortTag(lportTag), getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName())); - mdsalApiManager.addFlowToTx(dpId, flow, writeFlowGroupTx); + mdsalApiManager.addFlow(writeFlowGroupTx, dpId, flow); LOG.debug("Terminating service table flow entry created on dpn:{} for logical Interface port:{}", dpId, interfaceInfo.getPortName()); } @@ -723,7 +711,7 @@ public class ElanUtils { * @return the Internal tunnel */ public static String getIntTunnelTableFlowRef(short tableId, int elanTag) { - return new StringBuffer().append(tableId).append(elanTag).toString(); + return new StringBuilder().append(tableId).append(elanTag).toString(); } /** @@ -773,7 +761,8 @@ public class ElanUtils { * @return the egress actions for interface */ @SuppressWarnings("checkstyle:IllegalCatch") - public List getEgressActionsForInterface(String ifName, Long tunnelKey) { + @NonNull + public List getEgressActionsForInterface(String ifName, @Nullable Long tunnelKey) { List listAction = new ArrayList<>(); try { GetEgressActionsForInterfaceInput getEgressActionInput = new GetEgressActionsForInterfaceInputBuilder() @@ -785,8 +774,7 @@ public class ElanUtils { LOG.debug("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors()); } else { - List actions = rpcResult.getResult().getAction(); - listAction = actions; + listAction = rpcResult.getResult().nonnullAction(); } } catch (Exception e) { LOG.warn("Exception when egress actions for interface {}", ifName, e); @@ -796,8 +784,7 @@ public class ElanUtils { private void setupOrigDmacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, boolean configureRemoteFlows, IMdsalApiManager mdsalApiManager, - WriteTransaction writeFlowGroupTx) - throws ElanException { + TypedWriteTransaction writeFlowGroupTx) { BigInteger dpId = interfaceInfo.getDpId(); String ifName = interfaceInfo.getInterfaceName(); long ifTag = interfaceInfo.getInterfaceTag(); @@ -817,7 +804,7 @@ public class ElanUtils { List elanDpns = getInvolvedDpnsInElan(elanInstanceName); for (DpnInterfaces elanDpn : elanDpns) { - if (elanDpn.getDpId().equals(dpId)) { + if (Objects.equals(elanDpn.getDpId(), dpId)) { continue; } @@ -842,28 +829,28 @@ public class ElanUtils { // TODO: Make sure that the same is performed against the ElanDevices. } - @Nonnull + @NonNull public List getInvolvedDpnsInElan(String elanName) { return getElanDPNByName(elanName); } - @Nonnull + @NonNull public List getElanDPNByName(String elanInstanceName) { InstanceIdentifier elanIdentifier = getElanDpnOperationDataPath(elanInstanceName); return MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanIdentifier).toJavaUtil().map( - ElanDpnInterfacesList::getDpnInterfaces).orElse(Collections.emptyList()); + ElanDpnInterfacesList::getDpnInterfaces).orElse(emptyList()); } private void setupLocalDmacFlow(long elanTag, BigInteger dpId, String ifName, String macAddress, - ElanInstance elanInfo, IMdsalApiManager mdsalApiManager, long ifTag, WriteTransaction writeFlowGroupTx) { + ElanInstance elanInfo, IMdsalApiManager mdsalApiManager, long ifTag, + TypedWriteTransaction writeFlowGroupTx) { Flow flowEntity = buildLocalDmacFlowEntry(elanTag, dpId, ifName, macAddress, elanInfo, ifTag); - mdsalApiManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx); - installEtreeLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInfo, - ifTag, writeFlowGroupTx); + mdsalApiManager.addFlow(writeFlowGroupTx, dpId, flowEntity); + installEtreeLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInfo, ifTag, writeFlowGroupTx); } private void installEtreeLocalDmacFlow(long elanTag, BigInteger dpId, String ifName, String macAddress, - ElanInstance elanInfo, long ifTag, WriteTransaction writeFlowGroupTx) { + ElanInstance elanInfo, long ifTag, TypedWriteTransaction writeFlowGroupTx) { EtreeInterface etreeInterface = elanInterfaceCache.getEtreeInterface(ifName).orNull(); if (etreeInterface != null && etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) { EtreeLeafTagName etreeTagName = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag); @@ -873,7 +860,7 @@ public class ElanUtils { } else { Flow flowEntity = buildLocalDmacFlowEntry(etreeTagName.getEtreeLeafTag().getValue(), dpId, ifName, macAddress, elanInfo, ifTag); - mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx); + mdsalManager.addFlow(writeFlowGroupTx, dpId, flowEntity); } } } @@ -937,9 +924,9 @@ public class ElanUtils { return flow; } - public void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag, String - macAddress, String displayName, WriteTransaction writeFlowGroupTx, String interfaceName, ElanInstance - elanInstance) throws ElanException { + public void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag, + String macAddress, String displayName, TypedWriteTransaction writeFlowGroupTx, + String interfaceName, ElanInstance elanInstance) { if (interfaceManager.isExternalInterface(interfaceName)) { LOG.debug("Ignoring install remote DMAC {} flow on provider interface {} elan {}", macAddress, interfaceName, elanInstance.getElanInstanceName()); @@ -952,14 +939,15 @@ public class ElanUtils { ? getVxlanSegmentationId(elanInstance) : 0; flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTagOrVni, elanTag, macAddress, displayName, elanInstance); - mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx); + mdsalManager.addFlow(writeFlowGroupTx, srcDpId, flowEntity); setupEtreeRemoteDmacFlow(srcDpId, destDpId, lportTagOrVni, elanTag, macAddress, displayName, interfaceName, writeFlowGroupTx, elanInstance); } private void setupEtreeRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, long lportTagOrVni, long elanTag, String macAddress, String displayName, String interfaceName, - WriteTransaction writeFlowGroupTx, ElanInstance elanInstance) { + TypedWriteTransaction writeFlowGroupTx, + ElanInstance elanInstance) { Flow flowEntity; EtreeInterface etreeInterface = elanInterfaceCache.getEtreeInterface(interfaceName).orNull(); if (etreeInterface != null && etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) { @@ -970,7 +958,7 @@ public class ElanUtils { } else { flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTagOrVni, etreeTagName.getEtreeLeafTag().getValue(), macAddress, displayName, elanInstance); - mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx); + mdsalManager.addFlow(writeFlowGroupTx, srcDpId, flowEntity); } } } @@ -1009,15 +997,15 @@ public class ElanUtils { // List of Action for the provided Source and Destination DPIDs try { List actions = null; - if (isVlan(elanInstance) || isFlat(elanInstance)) { + if (isVxlanNetworkOrVxlanSegment(elanInstance)) { + actions = elanItmUtils.getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTagOrVni); + } else if (isVlan(elanInstance) || isFlat(elanInstance)) { String interfaceName = getExternalElanInterface(elanInstance.getElanInstanceName(), srcDpId); if (null == interfaceName) { LOG.info("buildRemoteDmacFlowEntry: Could not find interfaceName for {} {}", srcDpId, - elanInstance); + elanInstance); } actions = getEgressActionsForInterface(interfaceName, null); - } else if (isVxlanNetworkOrVxlanSegment(elanInstance)) { - actions = elanItmUtils.getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTagOrVni); } mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions)); } catch (Exception e) { @@ -1037,18 +1025,20 @@ public class ElanUtils { } public void deleteMacFlows(@Nullable ElanInstance elanInfo, @Nullable InterfaceInfo interfaceInfo, - MacEntry macEntry, WriteTransaction deleteFlowGroupTx) { + MacEntry macEntry, TypedReadWriteTransaction flowTx) + throws ExecutionException, InterruptedException { if (elanInfo == null || interfaceInfo == null) { return; } String macAddress = macEntry.getMacAddress().getValue(); - synchronized (getElanMacDPNKey(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) { - deleteMacFlows(elanInfo, interfaceInfo, macAddress, /* alsoDeleteSMAC */ true, deleteFlowGroupTx); + try (Acquired lock = lockElanMacDPN(elanInfo.getElanTag(), macAddress, interfaceInfo.getDpId())) { + deleteMacFlows(elanInfo, interfaceInfo, macAddress, /* alsoDeleteSMAC */ true, flowTx); } } public void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, - boolean deleteSmac, WriteTransaction deleteFlowGroupTx) { + boolean deleteSmac, TypedReadWriteTransaction flowTx) + throws ExecutionException, InterruptedException { String elanInstanceName = elanInfo.getElanInstanceName(); List remoteFEs = getInvolvedDpnsInElan(elanInstanceName); BigInteger srcdpId = interfaceInfo.getDpId(); @@ -1057,40 +1047,39 @@ public class ElanUtils { Long elanTag = elanInfo.getElanTag(); BigInteger dstDpId = dpnInterface.getDpId(); if (executeDeleteMacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, elanInstanceName, srcdpId, - elanTag, dstDpId, deleteFlowGroupTx)) { + elanTag, dstDpId, flowTx)) { isFlowsRemovedInSrcDpn = true; } executeEtreeDeleteMacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, elanInstanceName, srcdpId, - elanTag, dstDpId, deleteFlowGroupTx); + elanTag, dstDpId, flowTx); } if (!isFlowsRemovedInSrcDpn) { - deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, deleteFlowGroupTx); + deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, flowTx); } } private void executeEtreeDeleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, boolean deleteSmac, String elanInstanceName, BigInteger srcdpId, Long elanTag, BigInteger dstDpId, - WriteTransaction deleteFlowGroupTx) { + TypedReadWriteTransaction flowTx) throws ExecutionException, InterruptedException { EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag); if (etreeLeafTag != null) { executeDeleteMacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, elanInstanceName, srcdpId, - etreeLeafTag.getEtreeLeafTag().getValue(), dstDpId, deleteFlowGroupTx); + etreeLeafTag.getEtreeLeafTag().getValue(), dstDpId, flowTx); } } private boolean executeDeleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, boolean deleteSmac, String elanInstanceName, BigInteger srcdpId, Long elanTag, BigInteger dstDpId, - WriteTransaction deleteFlowGroupTx) { + TypedReadWriteTransaction flowTx) throws ExecutionException, InterruptedException { boolean isFlowsRemovedInSrcDpn = false; if (dstDpId.equals(srcdpId)) { isFlowsRemovedInSrcDpn = true; - deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, deleteFlowGroupTx); + deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, flowTx); } else if (isDpnPresent(dstDpId)) { mdsalManager - .removeFlowToTx(dstDpId, - MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, getKnownDynamicmacFlowRef( - NwConstants.ELAN_DMAC_TABLE, dstDpId, srcdpId, macAddress, elanTag)), - deleteFlowGroupTx); + .removeFlow(flowTx, dstDpId, + MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, getKnownDynamicmacFlowRef( + NwConstants.ELAN_DMAC_TABLE, dstDpId, srcdpId, macAddress, elanTag))); LOG.debug("Dmac flow entry deleted for elan:{}, logical interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dstDpId); } @@ -1098,22 +1087,21 @@ public class ElanUtils { } private void deleteSmacAndDmacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, - boolean deleteSmac, WriteTransaction deleteFlowGroupTx) { + boolean deleteSmac, TypedReadWriteTransaction flowTx) + throws ExecutionException, InterruptedException { String elanInstanceName = elanInfo.getElanInstanceName(); long ifTag = interfaceInfo.getInterfaceTag(); BigInteger srcdpId = interfaceInfo.getDpId(); Long elanTag = elanInfo.getElanTag(); if (deleteSmac) { mdsalManager - .removeFlowToTx(srcdpId, + .removeFlow(flowTx, srcdpId, MDSALUtil.buildFlow(NwConstants.ELAN_SMAC_TABLE, getKnownDynamicmacFlowRef( - NwConstants.ELAN_SMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)), - deleteFlowGroupTx); + NwConstants.ELAN_SMAC_TABLE, srcdpId, ifTag, macAddress, elanTag))); } - mdsalManager.removeFlowToTx(srcdpId, - MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, - getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)), - deleteFlowGroupTx); + mdsalManager.removeFlow(flowTx, srcdpId, + MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, + getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, srcdpId, ifTag, macAddress, elanTag))); LOG.debug("All the required flows deleted for elan:{}, logical Interface port:{} and MAC address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, srcdpId); } @@ -1128,32 +1116,31 @@ public class ElanUtils { * the elan instance added * @param elanInterfaces * the elan interfaces - * @param tx + * @param operTx * transaction * * @return the updated ELAN instance. */ public static ElanInstance updateOperationalDataStore(IdManagerService idManager, - ElanInstance elanInstanceAdded, List elanInterfaces, WriteTransaction tx) { + ElanInstance elanInstanceAdded, List elanInterfaces, TypedWriteTransaction confTx, + TypedWriteTransaction operTx) { String elanInstanceName = elanInstanceAdded.getElanInstanceName(); Long elanTag = elanInstanceAdded.getElanTag(); if (elanTag == null || elanTag == 0L) { elanTag = retrieveNewElanTag(idManager, elanInstanceName); } Elan elanInfo = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(elanInterfaces) - .setKey(new ElanKey(elanInstanceName)).build(); + .withKey(new ElanKey(elanInstanceName)).build(); // Add the ElanState in the elan-state operational data-store - tx.put(LogicalDatastoreType.OPERATIONAL, getElanInstanceOperationalDataPath(elanInstanceName), - elanInfo, WriteTransaction.CREATE_MISSING_PARENTS); + operTx.put(getElanInstanceOperationalDataPath(elanInstanceName), elanInfo, CREATE_MISSING_PARENTS); // Add the ElanMacTable in the elan-mac-table operational data-store - MacTable elanMacTable = new MacTableBuilder().setKey(new MacTableKey(elanInstanceName)).build(); - tx.put(LogicalDatastoreType.OPERATIONAL, getElanMacTableOperationalDataPath(elanInstanceName), - elanMacTable, WriteTransaction.CREATE_MISSING_PARENTS); + MacTable elanMacTable = new MacTableBuilder().withKey(new MacTableKey(elanInstanceName)).build(); + operTx.put(getElanMacTableOperationalDataPath(elanInstanceName), elanMacTable, CREATE_MISSING_PARENTS); ElanTagNameBuilder elanTagNameBuilder = new ElanTagNameBuilder().setElanTag(elanTag) - .setKey(new ElanTagNameKey(elanTag)).setName(elanInstanceName); + .withKey(new ElanTagNameKey(elanTag)).setName(elanInstanceName); long etreeLeafTag = -1; if (isEtreeInstance(elanInstanceAdded)) { etreeLeafTag = retrieveNewElanTag(idManager,elanInstanceName + ElanConstants @@ -1161,14 +1148,13 @@ public class ElanUtils { EtreeLeafTagName etreeLeafTagName = new EtreeLeafTagNameBuilder() .setEtreeLeafTag(new EtreeLeafTag(etreeLeafTag)).build(); elanTagNameBuilder.addAugmentation(EtreeLeafTagName.class, etreeLeafTagName); - addTheLeafTagAsElanTag(elanInstanceName, etreeLeafTag, tx); + addTheLeafTagAsElanTag(elanInstanceName, etreeLeafTag, operTx); } ElanTagName elanTagName = elanTagNameBuilder.build(); // Add the ElanTag to ElanName in the elan-tag-name Operational // data-store - tx.put(LogicalDatastoreType.OPERATIONAL, - getElanInfoEntriesOperationalDataPath(elanTag), elanTagName); + operTx.put(getElanInfoEntriesOperationalDataPath(elanTag), elanTagName); // Updates the ElanInstance Config DS by setting the just acquired // elanTag @@ -1176,27 +1162,27 @@ public class ElanUtils { .setDescription(elanInstanceAdded.getDescription()) .setMacTimeout(elanInstanceAdded.getMacTimeout() == null ? Long.valueOf(ElanConstants.DEFAULT_MAC_TIME_OUT) : elanInstanceAdded.getMacTimeout()) - .setKey(elanInstanceAdded.getKey()).setElanTag(elanTag); + .withKey(elanInstanceAdded.key()).setElanTag(elanTag); if (isEtreeInstance(elanInstanceAdded)) { EtreeInstance etreeInstance = new EtreeInstanceBuilder().setEtreeLeafTagVal(new EtreeLeafTag(etreeLeafTag)) .build(); elanInstanceBuilder.addAugmentation(EtreeInstance.class, etreeInstance); } ElanInstance elanInstanceWithTag = elanInstanceBuilder.build(); - tx.merge(LogicalDatastoreType.CONFIGURATION, ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName), - elanInstanceWithTag, WriteTransaction.CREATE_MISSING_PARENTS); + confTx.merge(ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstanceWithTag, + CREATE_MISSING_PARENTS); return elanInstanceWithTag; } - private static void addTheLeafTagAsElanTag(String elanInstanceName, long etreeLeafTag, WriteTransaction tx) { + private static void addTheLeafTagAsElanTag(String elanInstanceName, long etreeLeafTag, + TypedWriteTransaction tx) { ElanTagName etreeTagAsElanTag = new ElanTagNameBuilder().setElanTag(etreeLeafTag) - .setKey(new ElanTagNameKey(etreeLeafTag)).setName(elanInstanceName).build(); - tx.put(LogicalDatastoreType.OPERATIONAL, - getElanInfoEntriesOperationalDataPath(etreeLeafTag), etreeTagAsElanTag); + .withKey(new ElanTagNameKey(etreeLeafTag)).setName(elanInstanceName).build(); + tx.put(getElanInfoEntriesOperationalDataPath(etreeLeafTag), etreeTagAsElanTag); } private static boolean isEtreeInstance(ElanInstance elanInstanceAdded) { - return elanInstanceAdded.getAugmentation(EtreeInstance.class) != null; + return elanInstanceAdded.augmentation(EtreeInstance.class) != null; } public boolean isDpnPresent(BigInteger dpnId) { @@ -1208,11 +1194,6 @@ public class ElanUtils { return read(broker, LogicalDatastoreType.CONFIGURATION, node).isPresent(); } - public static ServicesInfo getServiceInfo(String elanInstanceName, String interfaceName) { - return InterfaceServiceUtil.buildServiceInfo(elanInstanceName + "." + interfaceName, - ElanConstants.ELAN_SERVICE_PRIORITY); - } - public static String getElanServiceName(String elanName, String interfaceName) { return "elan." + elanName + interfaceName; } @@ -1221,7 +1202,7 @@ public class ElanUtils { BigInteger cookie, List instructions) { StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority) .setInstruction(instructions); - return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName) + return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName) .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class) .addAugmentation(StypeOpenflow.class, augBuilder.build()).build(); } @@ -1271,6 +1252,7 @@ public class ElanUtils { * the datastore type * @return the external tunnel */ + @Nullable public ExternalTunnel getExternalTunnel(String sourceDevice, String destinationDevice, LogicalDatastoreType datastoreType) { Class tunType = TunnelTypeVxlan.class; @@ -1288,6 +1270,7 @@ public class ElanUtils { * the datastore type * @return the external tunnel */ + @Nullable public ExternalTunnel getExternalTunnel(String interfaceName, LogicalDatastoreType datastoreType) { ExternalTunnel externalTunnel = null; List externalTunnels = getAllExternalTunnels(datastoreType); @@ -1310,7 +1293,7 @@ public class ElanUtils { public List getAllExternalTunnels(LogicalDatastoreType datastoreType) { InstanceIdentifier iid = InstanceIdentifier.builder(ExternalTunnelList.class).build(); return read(broker, datastoreType, iid).toJavaUtil().map(ExternalTunnelList::getExternalTunnel).orElse( - Collections.emptyList()); + emptyList()); } public static List buildMatchesForElanTagShFlagAndDstMac(long elanTag, boolean shFlag, String macAddr) { @@ -1350,13 +1333,10 @@ public class ElanUtils { * the data broker * @return the interface state from oper ds */ - public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang - .ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS( - String interfaceName, DataBroker dataBroker) { - InstanceIdentifier ifStateId = createInterfaceStateInstanceIdentifier( - interfaceName); - return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId).orNull(); + public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state + .@Nullable Interface getInterfaceStateFromOperDS(String interfaceName, DataBroker dataBroker) { + return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, + createInterfaceStateInstanceIdentifier(interfaceName)).orNull(); } /** @@ -1380,16 +1360,15 @@ public class ElanUtils { return idBuilder.build(); } - public static CheckedFuture waitForTransactionToComplete( - WriteTransaction tx) { - CheckedFuture futures = tx.submit(); + @CheckReturnValue + public static ListenableFuture waitForTransactionToComplete(ListenableFuture future) { try { - futures.get(); + future.get(); } catch (InterruptedException | ExecutionException e) { - // NETVIRT-1215: Do not log.error() here, only debug() + // NETVIRT-1215: Do not log.error() here, only debug(); but callers *MUST* @CheckReturnValue LOG.debug("Error writing to datastore", e); } - return futures; + return future; } public static boolean isVxlan(@Nullable ElanInstance elanInstance) { @@ -1398,7 +1377,7 @@ public class ElanUtils { && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId() != 0; } - private static boolean isVxlanSegment(ElanInstance elanInstance) { + private static boolean isVxlanSegment(@Nullable ElanInstance elanInstance) { if (elanInstance != null) { List elanSegments = elanInstance.getElanSegments(); if (elanSegments != null) { @@ -1414,7 +1393,7 @@ public class ElanUtils { return false; } - public static boolean isVxlanNetworkOrVxlanSegment(ElanInstance elanInstance) { + public static boolean isVxlanNetworkOrVxlanSegment(@Nullable ElanInstance elanInstance) { return isVxlan(elanInstance) || isVxlanSegment(elanInstance); } @@ -1454,18 +1433,21 @@ public class ElanUtils { public void addDmacRedirectToDispatcherFlows(Long elanTag, String displayName, String macAddress, List dpnIds) { for (BigInteger dpId : dpnIds) { - ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit( - tx -> mdsalManager.addFlowToTx( - buildDmacRedirectToDispatcherFlow(dpId, macAddress, displayName, elanTag), tx)), LOG, + LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + tx -> mdsalManager.addFlow(tx, buildDmacRedirectToDispatcherFlow(dpId, macAddress, displayName, + elanTag))), LOG, "Error adding DMAC redirect to dispatcher flows"); } } public void removeDmacRedirectToDispatcherFlows(Long elanTag, String macAddress, List dpnIds) { - for (BigInteger dpId : dpnIds) { - String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, macAddress, elanTag); - mdsalManager.removeFlow(dpId, MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, flowId)); - } + LoggingFutures.addErrorLogging( + txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, tx -> { + for (BigInteger dpId : dpnIds) { + String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, macAddress, elanTag); + mdsalManager.removeFlow(tx, dpId, MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, flowId)); + } + }), LOG, "Error removing DMAC redirect to dispatcher flows"); } public static FlowEntity buildDmacRedirectToDispatcherFlow(BigInteger dpId, String dstMacAddress, @@ -1484,6 +1466,7 @@ public class ElanUtils { matches, instructions); } + @Nullable public String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) { DpnInterfaces dpnInterfaces = getElanInterfaceInfoByElanDpn(elanInstanceName, dpnId); if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null) { @@ -1501,14 +1484,8 @@ public class ElanUtils { return null; } - public static String getElanMacDPNKey(long elanTag, String macAddress, BigInteger dpnId) { - String elanMacDmacDpnKey = "MAC-" + macAddress + " ELAN_TAG-" + elanTag + "DPN_ID-" + dpnId; - return elanMacDmacDpnKey.intern(); - } - - public static String getElanMacKey(long elanTag, String macAddress) { - String elanMacKey = "MAC-" + macAddress + " ELAN_TAG-" + elanTag; - return elanMacKey.intern(); + public static Acquired lockElanMacDPN(long elanTag, String macAddress, BigInteger dpnId) { + return ELAN_LOCKS.acquire(new ElanLockName(elanTag, macAddress, dpnId)); } public static List> @@ -1551,18 +1528,6 @@ public class ElanUtils { new StaticMacEntriesKey(new PhysAddress(macAddress))).build(); } - public static List getDeletedEntries(List originalStaticMacEntries, - List updatedStaticMacEntries) { - if (isEmpty(originalStaticMacEntries)) { - return Collections.EMPTY_LIST; - } - List deleted = Lists.newArrayList(originalStaticMacEntries); - if (isNotEmpty(updatedStaticMacEntries)) { - deleted.removeAll(updatedStaticMacEntries); - } - return deleted; - } - public static List diffOf(List orig, List updated) { if (isEmpty(orig)) { return Collections.EMPTY_LIST; @@ -1574,18 +1539,6 @@ public class ElanUtils { return diff; } - public static void segregateToBeDeletedAndAddEntries(List originalStaticMacEntries, - List updatedStaticMacEntries) { - if (isNotEmpty(updatedStaticMacEntries)) { - List existingClonedStaticMacEntries = new ArrayList<>(); - if (isNotEmpty(originalStaticMacEntries)) { - existingClonedStaticMacEntries.addAll(0, originalStaticMacEntries); - originalStaticMacEntries.removeAll(updatedStaticMacEntries); - updatedStaticMacEntries.removeAll(existingClonedStaticMacEntries); - } - } - } - public static boolean isEmpty(Collection collection) { return collection == null || collection.isEmpty(); } @@ -1616,7 +1569,7 @@ public class ElanUtils { public List getElanMacEntries(String elanName) { MacTable macTable = getElanMacTable(elanName); if (macTable == null) { - return Collections.emptyList(); + return emptyList(); } return macTable.getMacEntry(); } @@ -1625,12 +1578,16 @@ public class ElanUtils { org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang .ietf.interfaces.rev140508.interfaces.Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName); - IfTunnel ifTunnel = configIface.getAugmentation(IfTunnel.class); + if (configIface == null) { + configIface = iitmProvider.getInterface(interfaceName); + } + if (configIface == null) { + return false; + } + IfTunnel ifTunnel = configIface.augmentation(IfTunnel.class); if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) { - ParentRefs refs = configIface.getAugmentation(ParentRefs.class); - if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) { - return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated - } + ParentRefs refs = configIface.augmentation(ParentRefs.class); + return refs != null && !Strings.isNullOrEmpty(refs.getParentInterface()); } return false; } @@ -1640,10 +1597,10 @@ public class ElanUtils { org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nodeId = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId("openflow:" + dpnId); org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node nodeDpn = - new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build(); + new NodeBuilder().setId(nodeId).withKey(new NodeKey(nodeId)).build(); return InstanceIdentifier.builder(Nodes.class) .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, - nodeDpn.getKey()).augmentation(FlowCapableNode.class) + nodeDpn.key()).augmentation(FlowCapableNode.class) .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build(); } @@ -1655,9 +1612,12 @@ public class ElanUtils { int lportTag) { LOG.info("Removing the ARP responder flow on DPN {} of Interface {} with IP {}", dpnId, ingressInterfaceName, ipAddress); - ArpResponderUtil.removeFlow(mdsalManager, dpnId, ArpResponderUtil.getFlowId(lportTag, ipAddress)); + LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION, + tx -> mdsalManager.removeFlow(tx, dpnId, ArpResponderUtil.getFlowId(lportTag, ipAddress), + NwConstants.ARP_RESPONDER_TABLE)), LOG, "Error removing ARP responder flow"); } + @Nullable public static String getRouterPordIdFromElanInstance(DataBroker dataBroker, String elanInstanceName) { Optional subnetMapsData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath()); @@ -1679,6 +1639,9 @@ public class ElanUtils { static InstanceIdentifier buildSubnetMapsWildCardPath() { return InstanceIdentifier.create(Subnetmaps.class); } -} - + public static InstanceIdentifier getGroupInstanceid(BigInteger dpnId, long groupId) { + return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))) + .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build(); + } +}