X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=elanmanager%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Felan%2Finternal%2FElanInterfaceManager.java;h=d0ec7557a63934b3b1b8e348c7dc4292c03d9fd6;hb=be1b0517d62d3aa1a21062363b21f6d9f4da4fba;hp=b2f6e311ccc6e8e1a5f5e0d7d7233e2e01824f3c;hpb=2bb99fe69d823fa98d49f9ed900030079231cfe5;p=netvirt.git diff --git a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java index b2f6e311cc..d0ec7557a6 100644 --- a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java +++ b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java @@ -7,15 +7,17 @@ */ package org.opendaylight.netvirt.elan.internal; +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 static org.opendaylight.genius.infra.Datastore.OPERATIONAL; +import static org.opendaylight.infrautils.utils.concurrent.LoggingFutures.addErrorLogging; import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.util.concurrent.ListenableFuture; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; @@ -27,22 +29,23 @@ import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; - +import java.util.concurrent.ExecutionException; +import java.util.concurrent.locks.ReentrantLock; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Singleton; - import org.apache.commons.lang3.StringUtils; import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase; 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.TransactionAdapter; import org.opendaylight.genius.infra.TypedReadWriteTransaction; +import org.opendaylight.genius.infra.TypedWriteTransaction; import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo; import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; import org.opendaylight.genius.itm.globals.ITMConstants; @@ -65,10 +68,11 @@ import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata; import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.genius.mdsalutil.matches.MatchMetadata; import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId; +import org.opendaylight.genius.utils.JvmGlobalLocks; import org.opendaylight.genius.utils.ServiceIndex; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; -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.NamedSimpleReentrantLock.Acquired; import org.opendaylight.netvirt.elan.cache.ElanInstanceCache; import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache; import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils; @@ -217,7 +221,15 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase identifier, ElanInterface del) { String interfaceName = del.getName(); - ElanInstance elanInfo = elanInstanceCache.get(del.getElanInstanceName()).orNull(); + String elanInstanceName = del.getElanInstanceName(); + Queue elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName); + if (elanInterfaces != null && elanInterfaces.contains(del)) { + elanInterfaces.remove(del); + if (elanInterfaces.isEmpty()) { + unProcessedElanInterfaces.remove(elanInstanceName); + } + } + ElanInstance elanInfo = elanInstanceCache.get(elanInstanceName).orNull(); /* * Handling in case the elan instance is deleted.If the Elan instance is * deleted, there is no need to explicitly delete the elan interfaces @@ -232,74 +244,79 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase> removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo) { String elanName = elanInfo.getElanInstanceName(); - boolean isLastElanInterface = false; - boolean isLastInterfaceOnDpn = false; - BigInteger dpId = null; long elanTag = elanInfo.getElanTag(); // We use two transaction so we don't suffer on multiple shards (interfaces and flows) - WriteTransaction interfaceTx = broker.newWriteOnlyTransaction(); - Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, interfaceTx); - if (elanState == null) { - interfaceTx.cancel(); - return Collections.emptyList(); - } - WriteTransaction flowTx = broker.newWriteOnlyTransaction(); - List elanInterfaces = elanState.getElanInterfaces(); - if (elanInterfaces.isEmpty()) { - isLastElanInterface = true; - } - if (interfaceInfo != null) { - dpId = interfaceInfo.getDpId(); - DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, - interfaceName, elanTag, interfaceTx); - /* - * If there are not elan ports, remove the unknown dmac, terminating - * service table flows, remote/local bc group - */ - if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null - || dpnInterfaces.getInterfaces().isEmpty()) { - // No more Elan Interfaces in this DPN - LOG.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId); - if (!elanUtils.isOpenstackVniSemanticsEnforced()) { - removeDefaultTermFlow(dpId, elanInfo.getElanTag()); + List> futures = new ArrayList<>(); + RemoveElanInterfaceHolder holder = new RemoveElanInterfaceHolder(); + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, interfaceTx -> { + Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, interfaceTx); + if (elanState == null) { + return; + } + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, flowTx -> { + List elanInterfaces = elanState.getElanInterfaces(); + if (elanInterfaces == null || elanInterfaces.isEmpty()) { + holder.isLastElanInterface = true; } - removeUnknownDmacFlow(dpId, elanInfo, flowTx, elanInfo.getElanTag()); - removeEtreeUnknownDmacFlow(dpId, elanInfo, flowTx); - removeElanBroadcastGroup(elanInfo, interfaceInfo, flowTx); - removeLocalBroadcastGroup(elanInfo, interfaceInfo, flowTx); - removeEtreeBroadcastGrups(elanInfo, interfaceInfo, flowTx); - if (isVxlanNetworkOrVxlanSegment(elanInfo)) { - if (elanUtils.isOpenstackVniSemanticsEnforced()) { - elanUtils.removeTerminatingServiceAction(dpId, - elanUtils.getVxlanSegmentationId(elanInfo).intValue()); + if (interfaceInfo != null) { + holder.dpId = interfaceInfo.getDpId(); + DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, holder.dpId, + interfaceName, elanTag, interfaceTx); + /* + * If there are not elan ports, remove the unknown dmac, terminating + * service table flows, remote/local bc group + */ + if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null + || dpnInterfaces.getInterfaces().isEmpty()) { + // No more Elan Interfaces in this DPN + LOG.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), + holder.dpId); + if (!elanUtils.isOpenstackVniSemanticsEnforced()) { + removeDefaultTermFlow(holder.dpId, elanInfo.getElanTag()); + } + removeUnknownDmacFlow(holder.dpId, elanInfo, flowTx, elanInfo.getElanTag()); + removeEtreeUnknownDmacFlow(holder.dpId, elanInfo, flowTx); + removeElanBroadcastGroup(elanInfo, interfaceInfo, flowTx); + removeLocalBroadcastGroup(elanInfo, interfaceInfo, flowTx); + removeEtreeBroadcastGrups(elanInfo, interfaceInfo, flowTx); + if (isVxlanNetworkOrVxlanSegment(elanInfo)) { + if (elanUtils.isOpenstackVniSemanticsEnforced()) { + elanUtils.removeTerminatingServiceAction(holder.dpId, + ElanUtils.getVxlanSegmentationId(elanInfo).intValue()); + } + unsetExternalTunnelTable(holder.dpId, elanInfo, flowTx); + } + holder.isLastInterfaceOnDpn = true; + } else { + setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo, flowTx); } - unsetExternalTunnelTable(dpId, elanInfo); } - isLastInterfaceOnDpn = true; - } else { - setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo); - } - } - - List> futures = new ArrayList<>(); - futures.add(ElanUtils.waitForTransactionToComplete(interfaceTx)); - futures.add(ElanUtils.waitForTransactionToComplete(flowTx)); + })); + })); + futures.forEach(ElanUtils::waitForTransactionToComplete); - if (isLastInterfaceOnDpn && dpId != null && isVxlanNetworkOrVxlanSegment(elanInfo)) { - setElanAndEtreeBCGrouponOtherDpns(elanInfo, dpId); + if (holder.isLastInterfaceOnDpn && holder.dpId != null && isVxlanNetworkOrVxlanSegment(elanInfo)) { + futures.add( + ElanUtils.waitForTransactionToComplete(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + confTx -> setElanAndEtreeBCGrouponOtherDpns(elanInfo, holder.dpId, confTx)))); } InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface( - interfaceName, elanInfo, interfaceInfo, this, isLastElanInterface); + interfaceName, elanInfo, interfaceInfo, this, holder.isLastElanInterface); jobCoordinator.enqueueJob(ElanUtils.getElanInterfaceJobKey(interfaceName), removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES); @@ -307,7 +324,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase deleteFlowGroupTx) + throws ExecutionException, InterruptedException { EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanInfo.getElanTag()); if (etreeLeafTag != null) { long leafTag = etreeLeafTag.getEtreeLeafTag().getValue(); @@ -316,83 +334,71 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase deleteFlowGroupTx) + throws ExecutionException, InterruptedException { removeLeavesEtreeBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx); removeLeavesLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx); } private void removeLeavesLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, - WriteTransaction deleteFlowGroupTx) { + TypedReadWriteTransaction deleteFlowGroupTx) + throws ExecutionException, InterruptedException { EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class); if (etreeInstance != null) { BigInteger dpnId = interfaceInfo.getDpId(); long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeInstance.getEtreeLeafTagVal().getValue()); - List listBuckets = new ArrayList<>(); - int bucketId = 0; - listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId)); - Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, - MDSALUtil.buildBucketLists(listBuckets)); - LOG.trace("deleted the localBroadCast Group:{}", group); - mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx); + LOG.trace("deleted the localBroadCast Group:{}", groupId); + mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId); } } private void removeLeavesEtreeBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, - WriteTransaction deleteFlowGroupTx) { + TypedReadWriteTransaction deleteFlowGroupTx) + throws ExecutionException, InterruptedException { EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class); if (etreeInstance != null) { long etreeTag = etreeInstance.getEtreeLeafTagVal().getValue(); - int bucketId = 0; - int actionKey = 0; - List listBuckets = new ArrayList<>(); - List listAction = new ArrayList<>(); - listAction.add(new ActionGroup(ElanUtils.getEtreeLeafLocalBCGId(etreeTag)).buildAction(++actionKey)); - listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, - MDSALUtil.WATCH_GROUP)); - bucketId++; - listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, etreeTag)); BigInteger dpnId = interfaceInfo.getDpId(); long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeTag); - Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, - MDSALUtil.buildBucketLists(listBuckets)); - LOG.trace("deleting the remoteBroadCast group:{}", group); - mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx); + LOG.trace("deleting the remoteBroadCast group:{}", groupId); + mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId); } } - private Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) { + private static Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, + TypedReadWriteTransaction tx) throws ExecutionException, InterruptedException { String elanName = elanInfo.getElanInstanceName(); - Elan elanState = ElanUtils.getElanByName(broker, elanName); + Elan elanState = ElanUtils.getElanByName(tx, elanName); if (elanState == null) { return elanState; } List elanInterfaces = elanState.getElanInterfaces(); - boolean isRemoved = elanInterfaces.remove(interfaceName); + boolean isRemoved = elanInterfaces != null && elanInterfaces.remove(interfaceName); if (!isRemoved) { return elanState; } if (elanInterfaces.isEmpty()) { - tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName)); - tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName)); - tx.delete(LogicalDatastoreType.OPERATIONAL, - ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag())); + tx.delete(ElanUtils.getElanInstanceOperationalDataPath(elanName)); + tx.delete(ElanUtils.getElanMacTableOperationalDataPath(elanName)); + tx.delete(ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag())); + tx.delete(ElanUtils.getElanDpnOperationDataPath(elanName)); } else { Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName) .withKey(new ElanKey(elanName)).build(); - tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), - updateElanState); + tx.put(ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState); } return elanState; } - private void deleteElanInterfaceFromConfigDS(String interfaceName, WriteTransaction tx) { + private void deleteElanInterfaceFromConfigDS(String interfaceName, TypedReadWriteTransaction tx) + throws ReadFailedException { // removing the ElanInterface from the config data_store if interface is // not present in Interface config DS - if (interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName) == null + if (interfaceManager.getInterfaceInfoFromConfigDataStore(TransactionAdapter.toReadWriteTransaction(tx), + interfaceName) == null && elanInterfaceCache.get(interfaceName).isPresent()) { - tx.delete(LogicalDatastoreType.CONFIGURATION, - ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName)); + tx.delete(ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName)); } } @@ -401,11 +407,10 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase> futures = new ArrayList<>(); futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, flowTx -> { - futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(interfaceTx -> { + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, interfaceTx -> { InstanceIdentifier elanInterfaceId = ElanUtils .getElanInterfaceMacEntriesOperationalDataPath(interfaceName); - Optional existingElanInterfaceMac = - interfaceTx.read(LogicalDatastoreType.OPERATIONAL, elanInterfaceId).checkedGet(); + Optional existingElanInterfaceMac = interfaceTx.read(elanInterfaceId).get(); LOG.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName); if (interfaceInfo != null) { if (existingElanInterfaceMac.isPresent()) { @@ -419,8 +424,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase macEntryOptional = elanUtils.getMacEntryForElanInstance(interfaceTx, elanName, macAddress); if (!isLastElanInterface && macEntryOptional.isPresent()) { - interfaceTx.delete(LogicalDatastoreType.OPERATIONAL, - ElanUtils.getMacEntryOperationalDataPath(elanName, macAddress)); + interfaceTx.delete(ElanUtils.getMacEntryOperationalDataPath(elanName, macAddress)); } elanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, flowTx); macAddresses.add(macAddress); @@ -443,17 +447,16 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase tx) + throws ExecutionException, InterruptedException { + // FIXME: pass in and use ElanInstanceKey instead? + final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanName); + lock.lock(); + try { DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId); if (dpnInterfaces != null) { List interfaceLists = dpnInterfaces.getInterfaces(); @@ -479,38 +485,44 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase dpnInterfaces = elanUtils.getInvolvedDpnsInElan(elanName); - for (DpnInterfaces dpnInterface : dpnInterfaces) { - BigInteger currentDpId = dpnInterface.getDpId(); - if (!currentDpId.equals(dpId)) { - for (String elanInterface : dpnInterface.getInterfaces()) { - ElanInterfaceMac macs = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface); - if (macs == null || macs.getMacEntry() == null) { - continue; - } - for (MacEntry mac : macs.getMacEntry()) { - removeTheMacFlowInTheDPN(dpId, elanTag, currentDpId, mac); - removeEtreeMacFlowInTheDPN(dpId, elanTag, currentDpId, mac); + addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> { + for (DpnInterfaces dpnInterface : dpnInterfaces) { + BigInteger currentDpId = dpnInterface.getDpId(); + if (!currentDpId.equals(dpId) && dpnInterface.getInterfaces() != null) { + for (String elanInterface : dpnInterface.getInterfaces()) { + ElanInterfaceMac macs = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface); + if (macs == null || macs.getMacEntry() == null) { + continue; + } + for (MacEntry mac : macs.getMacEntry()) { + removeTheMacFlowInTheDPN(dpId, elanTag, currentDpId, mac, confTx); + removeEtreeMacFlowInTheDPN(dpId, elanTag, currentDpId, mac, confTx); + } } } } - } + }), LOG, "Error deleting remote MACs in DPN {}", dpId); } - private void removeEtreeMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) { + private void removeEtreeMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac, + TypedReadWriteTransaction confTx) throws ExecutionException, InterruptedException { EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag); if (etreeLeafTag != null) { - removeTheMacFlowInTheDPN(dpId, etreeLeafTag.getEtreeLeafTag().getValue(), currentDpId, mac); + removeTheMacFlowInTheDPN(dpId, etreeLeafTag.getEtreeLeafTag().getValue(), currentDpId, mac, confTx); } } - private void removeTheMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) { + private void removeTheMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac, + TypedReadWriteTransaction confTx) throws ExecutionException, InterruptedException { mdsalManager - .removeFlow(dpId, + .removeFlow(confTx, dpId, MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, currentDpId, mac.getMacAddress().getValue(), elanTag))); @@ -553,25 +565,24 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase macEntryIdentifier = getMacEntryOperationalDataPath(elanName, staticMacEntry.getMacAddress()); - Optional existingMacEntry = ElanUtils.read(broker, - LogicalDatastoreType.OPERATIONAL, macEntryIdentifier); - WriteTransaction tx = broker.newWriteOnlyTransaction(); - if (existingMacEntry.isPresent()) { - elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList( - elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(), - tx); - } else { - elanForwardingEntriesHandler.addElanInterfaceForwardingTableList( - elanName, interfaceName, staticMacEntry, tx); - } - ListenableFutures.addErrorLogging(ElanUtils.waitForTransactionToComplete(tx), LOG, - "Error in update: identifier={}, original={}, update={}", identifier, original, update); + addErrorLogging(ElanUtils.waitForTransactionToComplete( + txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, tx -> { + Optional existingMacEntry = tx.read(macEntryIdentifier).get(); + if (existingMacEntry.isPresent()) { + elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList( + elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(), + tx); + } else { + elanForwardingEntriesHandler.addElanInterfaceForwardingTableList( + elanName, interfaceName, staticMacEntry, tx); + } + })), LOG, "Error in update: identifier={}, original={}, update={}", identifier, original, update); } } @Override protected void add(InstanceIdentifier identifier, ElanInterface elanInterfaceAdded) { - ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { + addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> { String elanInstanceName = elanInterfaceAdded.getElanInstanceName(); String interfaceName = elanInterfaceAdded.getName(); InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); @@ -582,34 +593,37 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase elanInterfaces = new ArrayList<>(); elanInterfaces.add(interfaceName); - elanInstance = ElanUtils.updateOperationalDataStore(idManager, elanInstance, elanInterfaces, tx); + elanInstance = txRunner.applyWithNewReadWriteTransactionAndSubmit(CONFIGURATION, + confTx -> ElanUtils.updateOperationalDataStore(idManager, + new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription( + elanInterfaceAdded.getDescription()).build(), elanInterfaces, confTx, operTx)).get(); } Long elanTag = elanInstance.getElanTag(); // If elan tag is not updated, then put the elan interface into // unprocessed entry map and entry. Let entries // in this map get processed during ELAN update DCN. - if (elanTag == null) { + if (elanTag == null || elanTag == 0L) { ConcurrentLinkedQueue elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName); if (elanInterfaces == null) { elanInterfaces = new ConcurrentLinkedQueue<>(); } - elanInterfaces.add(elanInterfaceAdded); + if (!elanInterfaces.contains(elanInterfaceAdded)) { + elanInterfaces.add(elanInterfaceAdded); + } unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces); return; } InterfaceAddWorkerOnElan addWorker = new InterfaceAddWorkerOnElan(elanInstanceName, elanInterfaceAdded, interfaceInfo, elanInstance, this); jobCoordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES); - }), LOG, "Error procedding added ELAN interface"); + }), LOG, "Error processing added ELAN interface"); } - List> handleunprocessedElanInterfaces(ElanInstance elanInstance) throws ElanException { + List> handleunprocessedElanInterfaces(ElanInstance elanInstance) { List> futures = new ArrayList<>(); Queue elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName()); if (elanInterfaces == null || elanInterfaces.isEmpty()) { @@ -620,11 +634,12 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase writeFlowGroupTx) { ElanDpnInterfacesList elanDpnInterfacesList = elanUtils .getElanDpnInterfacesList(elanInstance.getElanInstanceName()); List dpnInterfaceLists = null; @@ -636,7 +651,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase remoteElanInterfaces = dpnInterfaces.getInterfaces(); @@ -661,9 +676,15 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase> addElanInterface(ElanInterface elanInterface, - InterfaceInfo interfaceInfo, ElanInstance elanInstance) throws ElanException { + InterfaceInfo interfaceInfo, ElanInstance elanInstance) { Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null"); Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null"); Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null"); @@ -671,148 +692,171 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase elanInterfaces = new ArrayList<>(); - elanInterfaces.add(interfaceName); - ElanUtils.updateOperationalDataStore(idManager, elanInstance, elanInterfaces, tx); - } else { - createElanStateList(elanInstanceName, interfaceName, tx); - } - boolean isFirstInterfaceInDpn = false; - // Specific actions to the DPN where the ElanInterface has been added, - // for example, programming the - // External tunnel table if needed or adding the ElanInterface to the - // DpnInterfaces in the operational DS. - BigInteger dpId = interfaceInfo.getDpId(); - DpnInterfaces dpnInterfaces = null; - if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) { - synchronized (elanInstanceName.intern()) { - InstanceIdentifier elanDpnInterfaces = ElanUtils - .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId); - Optional existingElanDpnInterfaces = ElanUtils.read(broker, - LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces); - if (ElanUtils.isVlan(elanInstance)) { - isFirstInterfaceInDpn = checkIfFirstInterface(interfaceName, + List> futures = new ArrayList<>(); + AddElanInterfaceHolder holder = new AddElanInterfaceHolder(); + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> { + Elan elanInfo = ElanUtils.getElanByName(broker, elanInstanceName); + if (elanInfo == null) { + List elanInterfaces = new ArrayList<>(); + elanInterfaces.add(interfaceName); + futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + confTx -> ElanUtils.updateOperationalDataStore(idManager, elanInstance, elanInterfaces, confTx, + operTx))); + } else { + createElanStateList(elanInstanceName, interfaceName, operTx); + } + // Specific actions to the DPN where the ElanInterface has been added, + // for example, programming the + // External tunnel table if needed or adding the ElanInterface to the + // DpnInterfaces in the operational DS. + holder.dpId = interfaceInfo.getDpId(); + if (holder.dpId != null && !holder.dpId.equals(ElanConstants.INVALID_DPN)) { + // FIXME: use elanInstaince.key() instead? + final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanInstanceName); + lock.lock(); + try { + InstanceIdentifier elanDpnInterfaces = ElanUtils + .getElanDpnInterfaceOperationalDataPath(elanInstanceName, holder.dpId); + Optional existingElanDpnInterfaces = operTx.read(elanDpnInterfaces).get(); + if (ElanUtils.isVlan(elanInstance)) { + holder.isFirstInterfaceInDpn = checkIfFirstInterface(interfaceName, elanInstanceName, existingElanDpnInterfaces); - } else { - isFirstInterfaceInDpn = !existingElanDpnInterfaces.isPresent(); - } - if (isFirstInterfaceInDpn) { - // ELAN's 1st ElanInterface added to this DPN - if (!existingElanDpnInterfaces.isPresent()) { - dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx); } else { - List elanInterfaces = existingElanDpnInterfaces.get().getInterfaces(); - elanInterfaces.add(interfaceName); - dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, - elanInterfaces, tx); + holder.isFirstInterfaceInDpn = !existingElanDpnInterfaces.isPresent(); } - // The 1st ElanInterface in a DPN must program the Ext Tunnel - // table, but only if Elan has VNI - if (isVxlanNetworkOrVxlanSegment(elanInstance)) { - setExternalTunnelTable(dpId, elanInstance); - } - elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName); - } else { - List elanInterfaces = existingElanDpnInterfaces.get().getInterfaces(); - elanInterfaces.add(interfaceName); - if (elanInterfaces.size() == 1) { // 1st dpn interface - elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName); + if (holder.isFirstInterfaceInDpn) { + // ELAN's 1st ElanInterface added to this DPN + if (!existingElanDpnInterfaces.isPresent()) { + holder.dpnInterfaces = + createElanInterfacesList(elanInstanceName, interfaceName, holder.dpId, operTx); + } else { + List existingInterfaces = existingElanDpnInterfaces.get().getInterfaces(); + List elanInterfaces = + existingInterfaces != null ? new ArrayList<>(existingInterfaces) : new ArrayList<>(); + elanInterfaces.add(interfaceName); + holder.dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, holder.dpId, + elanInterfaces, operTx); + } + // The 1st ElanInterface in a DPN must program the Ext Tunnel + // table, but only if Elan has VNI + if (isVxlanNetworkOrVxlanSegment(elanInstance)) { + futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + confTx -> setExternalTunnelTable(holder.dpId, elanInstance, confTx))); + } + elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(holder.dpId, elanInstance, + interfaceName); + } else { + List existingInterfaces = existingElanDpnInterfaces.get().getInterfaces(); + List elanInterfaces = + existingInterfaces != null ? new ArrayList<>(existingInterfaces) : new ArrayList<>(); + elanInterfaces.add(interfaceName); + if (elanInterfaces.size() == 1) { // 1st dpn interface + elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(holder.dpId, elanInstance, + interfaceName); + } + holder.dpnInterfaces = + updateElanDpnInterfacesList(elanInstanceName, holder.dpId, elanInterfaces, operTx); } - dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx); + } finally { + lock.unlock(); } } - } - // add code to install Local/Remote BC group, unknow DMAC entry, - // terminating service table flow entry - // call bindservice of interfacemanager to create ingress table flow - // enty. - // Add interface to the ElanInterfaceForwardingEntires Container - createElanInterfaceTablesList(interfaceName, tx); - List> futures = new ArrayList<>(); - futures.add(ElanUtils.waitForTransactionToComplete(tx)); - installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn); + // add code to install Local/Remote BC group, unknow DMAC entry, + // terminating service table flow entry + // call bindservice of interfacemanager to create ingress table flow + // enty. + // Add interface to the ElanInterfaceForwardingEntires Container + createElanInterfaceTablesList(interfaceName, operTx); + })); + futures.forEach(ElanUtils::waitForTransactionToComplete); + futures.add( + ElanUtils.waitForTransactionToComplete(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + confTx -> installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, holder.dpnInterfaces, + holder.isFirstInterfaceInDpn, confTx)))); // add the vlan provider interface to remote BC group for the elan // for internal vlan networks if (ElanUtils.isVlan(elanInstance) && !elanInstance.isExternal()) { if (interfaceManager.isExternalInterface(interfaceName)) { LOG.debug("adding vlan prv intf {} to elan {} BC group", interfaceName, elanInstanceName); - handleExternalInterfaceEvent(elanInstance, dpnInterfaces, dpId); + handleExternalInterfaceEvent(elanInstance, holder.dpnInterfaces, holder.dpId); } } - if (isFirstInterfaceInDpn && isVxlanNetworkOrVxlanSegment(elanInstance)) { + if (holder.isFirstInterfaceInDpn && isVxlanNetworkOrVxlanSegment(elanInstance)) { //update the remote-DPNs remoteBC group entry with Tunnels - LOG.trace("update remote bc group for elan {} on other DPNs for newly added dpn {}", elanInstance, dpId); - setElanAndEtreeBCGrouponOtherDpns(elanInstance, dpId); + LOG.trace("update remote bc group for elan {} on other DPNs for newly added dpn {}", elanInstance, + holder.dpId); + futures.add( + ElanUtils.waitForTransactionToComplete(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + confTx -> setElanAndEtreeBCGrouponOtherDpns(elanInstance, holder.dpId, confTx)))); } String jobKey = ElanUtils.getElanInterfaceJobKey(interfaceName); InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(jobKey, - elanInterface, interfaceInfo, elanInstance, isFirstInterfaceInDpn, this); + elanInterface, interfaceInfo, elanInstance, holder.isFirstInterfaceInDpn, this); jobCoordinator.enqueueJob(jobKey, addWorker, ElanConstants.JOB_MAX_RETRIES); return futures; } @SuppressWarnings("checkstyle:ForbidCertainMethod") List> setupEntriesForElanInterface(ElanInstance elanInstance, - ElanInterface elanInterface, InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) - throws ElanException { + ElanInterface elanInterface, InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) { String elanInstanceName = elanInstance.getElanInstanceName(); String interfaceName = elanInterface.getName(); - WriteTransaction tx = broker.newWriteOnlyTransaction(); + List> futures = new ArrayList<>(); BigInteger dpId = interfaceInfo.getDpId(); - WriteTransaction writeFlowGroupTx = broker.newWriteOnlyTransaction(); - installEntriesForElanInterface(elanInstance, elanInterface, interfaceInfo, - isFirstInterfaceInDpn, tx, writeFlowGroupTx); - - List staticMacEntriesList = elanInterface.getStaticMacEntries(); - List staticMacAddresses = Lists.newArrayList(); - boolean isInterfaceOperational = isOperational(interfaceInfo); - if (ElanUtils.isNotEmpty(staticMacEntriesList)) { - for (StaticMacEntries staticMacEntry : staticMacEntriesList) { - InstanceIdentifier macId = getMacEntryOperationalDataPath(elanInstanceName, - staticMacEntry.getMacAddress()); - Optional existingMacEntry = ElanUtils.read(broker, - LogicalDatastoreType.OPERATIONAL, macId); - if (existingMacEntry.isPresent()) { - elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList( - elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), - existingMacEntry.get(), tx); - } else { - elanForwardingEntriesHandler - .addElanInterfaceForwardingTableList(elanInstanceName, interfaceName, staticMacEntry, tx); - } + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> { + futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL, operTx -> { + installEntriesForElanInterface(elanInstance, elanInterface, interfaceInfo, + isFirstInterfaceInDpn, confTx); + + List staticMacEntriesList = elanInterface.getStaticMacEntries(); + List staticMacAddresses = Lists.newArrayList(); + + if (ElanUtils.isNotEmpty(staticMacEntriesList)) { + for (StaticMacEntries staticMacEntry : staticMacEntriesList) { + InstanceIdentifier macId = getMacEntryOperationalDataPath(elanInstanceName, + staticMacEntry.getMacAddress()); + Optional existingMacEntry = ElanUtils.read(broker, + LogicalDatastoreType.OPERATIONAL, macId); + if (existingMacEntry.isPresent()) { + elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList( + elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), + existingMacEntry.get(), operTx); + } else { + elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanInstanceName, + interfaceName, staticMacEntry, operTx); + } - if (isInterfaceOperational) { - // Setting SMAC, DMAC, UDMAC in this DPN and also in other - // DPNs - String macAddress = staticMacEntry.getMacAddress().getValue(); - LOG.info("programming smac and dmacs for {} on source and other DPNs for elan {} and interface {}", - macAddress, elanInstanceName, interfaceName); - elanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, - staticMacEntry.getMacAddress().getValue(), true, writeFlowGroupTx); - } - } + if (isInterfaceOperational) { + // Setting SMAC, DMAC, UDMAC in this DPN and also in other + // DPNs + String macAddress = staticMacEntry.getMacAddress().getValue(); + LOG.info( + "programming smac and dmacs for {} on source and other DPNs for elan {} and interface" + + " {}", + macAddress, elanInstanceName, interfaceName); + elanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, + staticMacEntry.getMacAddress().getValue(), true, confTx); + } + } - if (isInterfaceOperational) { - // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop - // on purpose. - for (StaticMacEntries staticMacEntry : staticMacEntriesList) { - staticMacAddresses.add(staticMacEntry.getMacAddress()); + if (isInterfaceOperational) { + // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop + // on purpose. + for (StaticMacEntries staticMacEntry : staticMacEntriesList) { + staticMacAddresses.add(staticMacEntry.getMacAddress()); + } + elanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, + staticMacAddresses); + } } - elanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, - staticMacAddresses); - } - } - List> futures = new ArrayList<>(); - futures.add(ElanUtils.waitForTransactionToComplete(tx)); - futures.add(ElanUtils.waitForTransactionToComplete(writeFlowGroupTx)); + })); + })); + futures.forEach(ElanUtils::waitForTransactionToComplete); if (isInterfaceOperational && !interfaceManager.isExternalInterface(interfaceName)) { //At this point, the interface is operational and D/SMAC flows have been configured, mark the port active try { @@ -855,42 +899,43 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase interfaces = dpnInterfaces.getInterfaces(); + if (interfaces == null) { + return true; } - if (dpnInterfaces.getInterfaces().contains(elanInstanceName)) { + if (interfaces.contains(routerPortUuid)) { dummyInterfaceCount++; } - if (dpnInterfaces.getInterfaces().size() - dummyInterfaceCount == 0) { - return true; + if (interfaces.contains(elanInstanceName)) { + dummyInterfaceCount++; } - return false; + return interfaces.size() == dummyInterfaceCount; } - private InstanceIdentifier getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) { + private static InstanceIdentifier getMacEntryOperationalDataPath(String elanName, + PhysAddress physAddress) { return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName)) .child(MacEntry.class, new MacEntryKey(physAddress)).build(); } private void installEntriesForElanInterface(ElanInstance elanInstance, ElanInterface elanInterface, - InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn, WriteTransaction tx, - WriteTransaction writeFlowGroupTx) throws ElanException { + InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn, TypedWriteTransaction confTx) { if (!isOperational(interfaceInfo)) { return; } BigInteger dpId = interfaceInfo.getDpId(); if (!elanUtils.isOpenstackVniSemanticsEnforced()) { - elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, writeFlowGroupTx); + elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, confTx); } - setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx); + setupFilterEqualsTable(elanInstance, interfaceInfo, confTx); if (isFirstInterfaceInDpn) { // Terminating Service , UnknownDMAC Table. // The 1st ELAN Interface in a DPN must program the INTERNAL_TUNNEL_TABLE, but only if the network type // for ELAN Instance is VxLAN if (isVxlanNetworkOrVxlanSegment(elanInstance)) { - setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx); + setupTerminateServiceTable(elanInstance, dpId, confTx); } - setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx); + setupUnknownDMacTable(elanInstance, dpId, confTx); /* * Install remote DMAC flow. This is required since this DPN is * added later to the elan instance and remote DMACs of other @@ -900,20 +945,20 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase confTx) { if (!isOperational(interfaceInfo)) { return; } // LocalBroadcast Group creation with elan-Interfaces - setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo); + setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo, confTx); if (isFirstInterfaceInDpn) { LOG.trace("waitTimeForSyncInstall is {}", WAIT_TIME_FOR_SYNC_INSTALL); BigInteger dpId = interfaceInfo.getDpId(); @@ -923,7 +968,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase writeFlowGroupTx) { int ifTag = interfaceInfo.getInterfaceTag(); Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "group"), 9, elanInfo.getElanInstanceName(), 0, @@ -941,64 +986,52 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase flowTx) { - try { - int ifTag = interfaceInfo.getInterfaceTag(); - Flow flow = MDSALUtil.buildFlow(NwConstants.ELAN_FILTER_EQUALS_TABLE, - getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "group")); + TypedReadWriteTransaction flowTx) throws ExecutionException, InterruptedException { + int ifTag = interfaceInfo.getInterfaceTag(); + Flow flow = MDSALUtil.buildFlow(NwConstants.ELAN_FILTER_EQUALS_TABLE, + getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "group")); - mdsalManager.removeFlow(flowTx, interfaceInfo.getDpId(), flow); + mdsalManager.removeFlow(flowTx, interfaceInfo.getDpId(), flow); - Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE, - getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "drop"), 10, elanInfo.getElanInstanceName(), 0, - 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), - getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop()); + Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE, + getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "drop"), 10, elanInfo.getElanInstanceName(), 0, + 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), + getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop()); - mdsalManager.removeFlow(flowTx, interfaceInfo.getDpId(), flowEntity); - } catch (Exception e) { - LOG.error("Error removing flow", e); - throw new RuntimeException("Error removing flow", e); - } - } - - private List getRemoteBCGroupBucketInfos(ElanInstance elanInfo, int bucketKeyStart, - InterfaceInfo interfaceInfo, long elanTag) { - return elanL2GatewayMulticastUtils.getRemoteBCGroupBuckets(elanInfo, null, interfaceInfo.getDpId(), - bucketKeyStart, elanTag); + mdsalManager.removeFlow(flowTx, interfaceInfo.getDpId(), flowEntity); } - private void setElanAndEtreeBCGrouponOtherDpns(ElanInstance elanInfo, BigInteger dpId) { + private void setElanAndEtreeBCGrouponOtherDpns(ElanInstance elanInfo, BigInteger dpId, + TypedWriteTransaction confTx) { int elanTag = elanInfo.getElanTag().intValue(); long groupId = ElanUtils.getElanRemoteBCGId(elanTag); - setBCGrouponOtherDpns(elanInfo, dpId, elanTag, groupId); + setBCGrouponOtherDpns(elanInfo, dpId, elanTag, groupId, confTx); EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class); if (etreeInstance != null) { int etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue().intValue(); long etreeLeafGroupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag); - setBCGrouponOtherDpns(elanInfo, dpId, etreeLeafTag, etreeLeafGroupId); + setBCGrouponOtherDpns(elanInfo, dpId, etreeLeafTag, etreeLeafGroupId, confTx); } } @SuppressWarnings("checkstyle:IllegalCatch") - private void setBCGrouponOtherDpns(ElanInstance elanInfo, BigInteger dpId, int elanTag, long groupId) { + private void setBCGrouponOtherDpns(ElanInstance elanInfo, BigInteger dpId, int elanTag, long groupId, + TypedWriteTransaction confTx) { int bucketId = 0; ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); if (elanDpns != null) { - List dpnInterfaces = elanDpns.getDpnInterfaces(); + List dpnInterfaces = elanDpns.nonnullDpnInterfaces(); for (DpnInterfaces dpnInterface : dpnInterfaces) { List remoteListBucketInfo = new ArrayList<>(); if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !Objects.equals(dpnInterface.getDpId(), dpId) @@ -1017,7 +1050,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase remoteListActionInfo = elanItmUtils.getInternalTunnelItmEgressAction( dpnInterface.getDpId(), otherFes.getDpId(), elanUtils.isOpenstackVniSemanticsEnforced() - ? elanUtils.getVxlanSegmentationId(elanInfo) : elanTag); + ? ElanUtils.getVxlanSegmentationId(elanInfo) : elanTag); if (!remoteListActionInfo.isEmpty()) { remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil .GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); @@ -1042,7 +1075,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase buildMatchesForVni(Long vni) { + private static List buildMatchesForVni(Long vni) { List mkMatches = new ArrayList<>(); MatchInfo match = new MatchTunnelId(BigInteger.valueOf(vni)); mkMatches.add(match); return mkMatches; } - private List getInstructionsForOutGroup(long groupId) { + private static List getInstructionsForOutGroup(long groupId) { List mkInstructions = new ArrayList<>(); mkInstructions.add(new InstructionWriteActions(Collections.singletonList(new ActionGroup(groupId)))); return mkInstructions; } - private List getMatchesForElanTag(long elanTag, boolean isSHFlagSet) { + private static List getMatchesForElanTag(long elanTag, boolean isSHFlagSet) { List mkMatches = new ArrayList<>(); // Matching metadata mkMatches.add(new MatchMetadata( @@ -1090,7 +1115,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase getInstructionsIntOrExtTunnelTable(Long elanTag) { + private static List getInstructionsIntOrExtTunnelTable(Long elanTag) { List mkInstructions = new ArrayList<>(); mkInstructions.add(new InstructionWriteMetadata(ElanHelper.getElanMetadataLabel(elanTag), ElanHelper .getElanMetadataMask())); @@ -1102,30 +1127,31 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase> installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, - BigInteger dstDpId) throws ElanException { + BigInteger dstDpId) { String interfaceName = interfaceInfo.getInterfaceName(); ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName); if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) { List macEntries = elanInterfaceMac.getMacEntry(); - WriteTransaction writeFlowTx = broker.newWriteOnlyTransaction(); - for (MacEntry macEntry : macEntries) { - String macAddress = macEntry.getMacAddress().getValue(); - LOG.info("Installing remote dmac for mac address {} and interface {}", macAddress, interfaceName); - synchronized (ElanUtils.getElanMacDPNKey(elanInfo.getElanTag(), macAddress, - interfaceInfo.getDpId())) { - LOG.info("Acquired lock for mac : {}, proceeding with remote dmac install operation", macAddress); - elanUtils.setupDMacFlowOnRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress, - writeFlowTx); - } - } - return Collections.singletonList(ElanUtils.waitForTransactionToComplete(writeFlowTx)); + return Collections.singletonList(ElanUtils.waitForTransactionToComplete( + txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> { + for (MacEntry macEntry : macEntries) { + String macAddress = macEntry.getMacAddress().getValue(); + LOG.info("Installing remote dmac for mac address {} and interface {}", macAddress, + interfaceName); + try (Acquired lock = ElanUtils.lockElanMacDPN(elanInfo.getElanTag(), macAddress, + interfaceInfo.getDpId())) { + LOG.info("Acquired lock for mac : {}, proceeding with remote dmac install operation", + macAddress); + elanUtils.setupDMacFlowOnRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress, tx); + } + } + }))); } - return Collections.emptyList(); + return emptyList(); } - private void createDropBucket(List listBucket) { + private static void createDropBucket(List listBucket) { List actionsInfos = new ArrayList<>(); actionsInfos.add(new ActionDrop().buildAction()); Bucket dropBucket = MDSALUtil.buildBucket(actionsInfos, MDSALUtil.GROUP_WEIGHT, 0, MDSALUtil.WATCH_PORT, @@ -1133,20 +1159,20 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase confTx) { + setupStandardLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo, confTx); + setupLeavesLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo, confTx); } - public void setupStandardLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface, - InterfaceInfo interfaceInfo) { + private void setupStandardLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface, + InterfaceInfo interfaceInfo, TypedWriteTransaction confTx) { List listBucket = new ArrayList<>(); int bucketId = 0; long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag()); List interfaces = new ArrayList<>(); - if (newDpnInterface != null) { + if (newDpnInterface != null && newDpnInterface.getInterfaces() != null) { interfaces = newDpnInterface.getInterfaces(); } for (String ifName : interfaces) { @@ -1168,18 +1194,18 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase confTx) { EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class); if (etreeInstance != null) { List listBucket = new ArrayList<>(); int bucketId = 0; List interfaces = new ArrayList<>(); - if (newDpnInterface != null) { + if (newDpnInterface != null && newDpnInterface.getInterfaces() != null) { interfaces = newDpnInterface.getInterfaces(); } for (String ifName : interfaces) { @@ -1207,7 +1233,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase deleteFlowGroupTx) + throws ExecutionException, InterruptedException { BigInteger dpnId = interfaceInfo.getDpId(); long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag()); - List listBuckets = new ArrayList<>(); - int bucketId = 0; - listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId)); - // listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, - // interfaceInfo)); - Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, - MDSALUtil.buildBucketLists(listBuckets)); - LOG.trace("deleted the localBroadCast Group:{}", group); - mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx); + LOG.trace("deleted the localBroadCast Group:{}", groupId); + mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId); } public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, - WriteTransaction deleteFlowGroupTx) { - int bucketId = 0; - int actionKey = 0; - Long elanTag = elanInfo.getElanTag(); - List listBuckets = new ArrayList<>(); - List listAction = new ArrayList<>(); - listAction.add(new ActionGroup(++actionKey, ElanUtils.getElanLocalBCGId(elanTag)).buildAction()); - listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, - MDSALUtil.WATCH_GROUP)); - bucketId++; - listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, elanTag)); + TypedReadWriteTransaction deleteFlowGroupTx) + throws ExecutionException, InterruptedException { BigInteger dpnId = interfaceInfo.getDpId(); long groupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag()); - Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, - MDSALUtil.buildBucketLists(listBuckets)); - LOG.trace("deleting the remoteBroadCast group:{}", group); - mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx); + LOG.trace("deleting the remoteBroadCast group:{}", groupId); + mdsalManager.removeGroup(deleteFlowGroupTx, dpnId, groupId); } /** * Installs a flow in the External Tunnel table consisting in translating * the VNI retrieved from the packet that came over a tunnel with a TOR into * elanTag that will be used later in the ELANs pipeline. - * - * @param dpnId - * the dpn id - * @param elanInfo - * the elan info + * @param dpnId the dpn id */ - public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) { + private void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo, + TypedWriteTransaction confTx) { long elanTag = elanInfo.getElanTag(); FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.EXTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag), 5, // prio @@ -1278,7 +1284,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase confTx) throws ExecutionException, InterruptedException { // TODO: Use DataStoreJobCoordinator in order to avoid that removing the // last ElanInstance plus // adding a new one does (almost at the same time) are executed in that @@ -1303,16 +1307,17 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase writeFlowGroupTx) { setupTerminateServiceTable(elanInfo, dpId, elanInfo.getElanTag(), writeFlowGroupTx); setupEtreeTerminateServiceTable(elanInfo, dpId, writeFlowGroupTx); } public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, long elanTag, - WriteTransaction writeFlowGroupTx) { + TypedWriteTransaction writeFlowGroupTx) { List listMatchInfoBase; List instructionInfos; long serviceId; @@ -1321,7 +1326,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase writeFlowGroupTx) { EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class); if (etreeInstance != null) { setupTerminateServiceTable(elanInfo, dpId, etreeInstance.getEtreeLeafTagVal().getValue(), writeFlowGroupTx); } } - public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) { + public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, + TypedWriteTransaction writeFlowGroupTx) { long elanTag = elanInfo.getElanTag(); installLocalUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx); installRemoteUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx); @@ -1348,7 +1354,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase writeFlowGroupTx) { EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag); if (etreeLeafTag != null) { long leafTag = etreeLeafTag.getEtreeLeafTag().getValue(); @@ -1358,7 +1364,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase writeFlowGroupTx) { FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,/* SH flag */false), 5, elanInfo.getElanInstanceName(), 0, 0, @@ -1366,11 +1372,11 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase writeFlowGroupTx) { // only if ELAN can connect to external network, perform the following if (isVxlanNetworkOrVxlanSegment(elanInfo) || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) { @@ -1380,22 +1386,23 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase deleteFlowGroupTx, long elanTag) + throws ExecutionException, InterruptedException { Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, SH_FLAG_UNSET))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE).build(); - mdsalManager.removeFlowToTx(dpId, flow, deleteFlowGroupTx); + mdsalManager.removeFlow(deleteFlowGroupTx, dpId, flow); if (isVxlanNetworkOrVxlanSegment(elanInfo)) { Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, SH_FLAG_SET))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE) .build(); - mdsalManager.removeFlowToTx(dpId, flow2, deleteFlowGroupTx); + mdsalManager.removeFlow(deleteFlowGroupTx, dpId, flow2); } } @@ -1403,7 +1410,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase tx) { if (isStandardElanService(elanInterface)) { bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), lportTag, tx); @@ -1413,7 +1421,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase tx) { int instructionKey = 0; List instructions = new ArrayList<>(); instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanHelper.getElanMetadataLabel(elanTag), @@ -1437,13 +1445,12 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase existingElanService = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, bindServiceId); if (!existingElanService.isPresent()) { - tx.put(LogicalDatastoreType.CONFIGURATION, bindServiceId, serviceInfo, - WriteTransaction.CREATE_MISSING_PARENTS); + tx.put(bindServiceId, serviceInfo, CREATE_MISSING_PARENTS); } } private void bindEtreeService(ElanInstance elanInfo, ElanInterface elanInterface, int lportTag, - WriteTransaction tx) { + TypedWriteTransaction tx) { if (elanInterface.augmentation(EtreeInterface.class).getEtreeInterfaceType() == EtreeInterfaceType.Root) { bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), lportTag, tx); @@ -1459,32 +1466,33 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase tx) + throws ExecutionException, InterruptedException { short elanServiceIndex = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX); InstanceIdentifier bindServiceId = ElanUtils.buildServiceId(interfaceName, elanServiceIndex); - if (tx.read(LogicalDatastoreType.CONFIGURATION, bindServiceId).checkedGet().isPresent()) { - tx.delete(LogicalDatastoreType.CONFIGURATION, bindServiceId); + if (tx.read(bindServiceId).get().isPresent()) { + tx.delete(bindServiceId); } } - private String getFlowRef(long tableId, long elanTag) { + private static String getFlowRef(long tableId, long elanTag) { return String.valueOf(tableId) + elanTag; } - private String getFlowRef(long tableId, long elanTag, String flowName) { - return new StringBuffer().append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(elanTag) + private static String getFlowRef(long tableId, long elanTag, String flowName) { + return new StringBuilder().append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(elanTag) .append(NwConstants.FLOWID_SEPARATOR).append(flowName).toString(); } - private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) { + private static String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) { return String.valueOf(tableId) + elanTag + shFlag; } - private List getInterfacePortActions(InterfaceInfo interfaceInfo) { + private static List getInterfacePortActions(InterfaceInfo interfaceInfo) { List listAction = new ArrayList<>(); int actionKey = 0; listAction.add( @@ -1494,13 +1502,12 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase interfaceNames, WriteTransaction tx) { + private static DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, + List interfaceNames, TypedWriteTransaction tx) { DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames) .withKey(new DpnInterfacesKey(dpId)).build(); - tx.put(LogicalDatastoreType.OPERATIONAL, - ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, - WriteTransaction.CREATE_MISSING_PARENTS); + tx.put(ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, + CREATE_MISSING_PARENTS); return dpnInterface; } @@ -1512,48 +1519,46 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase tx) throws ExecutionException, InterruptedException { InstanceIdentifier dpnInterfacesId = ElanUtils .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId); - Optional dpnInterfaces = ElanUtils.read(broker, - LogicalDatastoreType.OPERATIONAL, dpnInterfacesId); + Optional dpnInterfaces = tx.read(dpnInterfacesId).get(); if (dpnInterfaces.isPresent()) { - tx.delete(LogicalDatastoreType.OPERATIONAL, dpnInterfacesId); + tx.delete(dpnInterfacesId); } } - private DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId, - WriteTransaction tx) { + private static DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, + BigInteger dpId, TypedWriteTransaction tx) { List interfaceNames = new ArrayList<>(); interfaceNames.add(interfaceName); DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames) .withKey(new DpnInterfacesKey(dpId)).build(); - tx.put(LogicalDatastoreType.OPERATIONAL, - ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, - WriteTransaction.CREATE_MISSING_PARENTS); + tx.put(ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, + CREATE_MISSING_PARENTS); return dpnInterface; } - private void createElanInterfaceTablesList(String interfaceName, WriteTransaction tx) { + private static void createElanInterfaceTablesList(String interfaceName, TypedReadWriteTransaction tx) + throws ExecutionException, InterruptedException { InstanceIdentifier elanInterfaceMacTables = ElanUtils .getElanInterfaceMacEntriesOperationalDataPath(interfaceName); - Optional interfaceMacTables = ElanUtils.read(broker, - LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables); + Optional interfaceMacTables = tx.read(elanInterfaceMacTables).get(); // Adding new Elan Interface Port to the operational DataStore without // Static-Mac Entries.. if (!interfaceMacTables.isPresent()) { ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName) .withKey(new ElanInterfaceMacKey(interfaceName)).build(); - tx.put(LogicalDatastoreType.OPERATIONAL, - ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), elanInterfaceMacTable, - WriteTransaction.CREATE_MISSING_PARENTS); + tx.put(ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), elanInterfaceMacTable, + CREATE_MISSING_PARENTS); } } - private void createElanStateList(String elanInstanceName, String interfaceName, WriteTransaction tx) { + private static void createElanStateList(String elanInstanceName, String interfaceName, + TypedReadWriteTransaction tx) throws ExecutionException, InterruptedException { InstanceIdentifier elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName); - Optional elanInterfaceLists = ElanUtils.read(broker, - LogicalDatastoreType.OPERATIONAL, elanInstance); + Optional elanInterfaceLists = tx.read(elanInstance).get(); // Adding new Elan Interface Port to the operational DataStore without // Static-Mac Entries.. if (elanInterfaceLists.isPresent()) { @@ -1564,16 +1569,12 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList(); + List elanDpnIf = dpnInterfaceLists.nonnullElanDpnInterfacesList(); for (ElanDpnInterfacesList elanDpns : elanDpnIf) { int cnt = 0; String elanName = elanDpns.getElanInstanceName(); @@ -1605,9 +1606,9 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase elanL2GatewayMulticastUtils.setupElanBroadcastGroups(elanInfo, srcDpId, + confTx)).get(); } catch (RuntimeException e) { LOG.error("Error while adding remote bc group for {} on dpId {} ", elanName, srcDpId); } @@ -1632,10 +1635,10 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList(); + List elanDpnIf = dpnInterfaceLists.nonnullElanDpnInterfacesList(); for (ElanDpnInterfacesList elanDpns : elanDpnIf) { String elanName = elanDpns.getElanInstanceName(); ElanInstance elanInfo = elanInstanceCache.get(elanName).orNull(); @@ -1687,7 +1689,10 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase elanL2GatewayMulticastUtils.setupElanBroadcastGroups(elanInfo, finalDpId, confTx)), LOG, + "Error setting up ELAN BGs"); // install L2gwDevices local macs in dpn. elanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo, intrf.getName()); // Install dpn macs on external device @@ -1735,7 +1740,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase staticMacs = elanL2GatewayUtils.getElanDpnMacsFromInterfaces(lstElanInterfaceNames); if (phyLocAlreadyExists) { @@ -1777,7 +1782,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase getMatchesForFilterEqualsLPortTag(int lportTag) { + private static List getMatchesForFilterEqualsLPortTag(int lportTag) { List mkMatches = new ArrayList<>(); // Matching metadata mkMatches.add( @@ -1794,7 +1799,9 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase elanL2GatewayMulticastUtils.setupStandardElanBroadcastGroups(elanInstance, dpnInterfaces, dpId, + confTx)), LOG, "Error setting up remote BC group for ELAN {}", elanInstance.getPhysicalNetworkName()); try { Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL); } catch (InterruptedException e) {