X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=elanmanager%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Felan%2Fl2gw%2Futils%2FElanL2GatewayMulticastUtils.java;h=dd289aa192acd3fa2003840afbe0b467153df20f;hb=refs%2Fchanges%2F60%2F89660%2F34;hp=244d423d9f9be8a03570b1dcadb4ec0cf5e2d9bd;hpb=e3fee34afc75b60b6677f4b90a9b769f1edf6929;p=netvirt.git diff --git a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanL2GatewayMulticastUtils.java b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanL2GatewayMulticastUtils.java index 244d423d9f..dd289aa192 100644 --- a/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanL2GatewayMulticastUtils.java +++ b/elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/l2gw/utils/ElanL2GatewayMulticastUtils.java @@ -8,25 +8,31 @@ package org.opendaylight.netvirt.elan.l2gw.utils; import static java.util.Collections.emptyList; +import static org.opendaylight.genius.infra.Datastore.CONFIGURATION; import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment; +import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.SettableFuture; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; -import java.util.concurrent.ConcurrentMap; -import javax.annotation.Nonnull; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutionException; import javax.inject.Inject; import javax.inject.Singleton; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; +import org.opendaylight.genius.infra.Datastore; import org.opendaylight.genius.infra.ManagedNewTransactionRunner; import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; +import org.opendaylight.genius.infra.TypedWriteTransaction; import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.genius.mdsalutil.actions.ActionGroup; @@ -35,11 +41,18 @@ import org.opendaylight.genius.utils.batching.ResourceBatchingManager; import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils; import org.opendaylight.genius.utils.hwvtep.HwvtepUtils; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; -import org.opendaylight.infrautils.utils.concurrent.JdkFutures; +import org.opendaylight.infrautils.utils.concurrent.LoggingFutures; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.common.api.CommitInfo; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.ReadFailedException; import org.opendaylight.netvirt.elan.l2gw.jobs.HwvtepDeviceMcastMacUpdateJob; +import org.opendaylight.netvirt.elan.l2gw.jobs.McastUpdateJob; +import org.opendaylight.netvirt.elan.utils.ElanClusterUtils; import org.opendaylight.netvirt.elan.utils.ElanConstants; import org.opendaylight.netvirt.elan.utils.ElanItmUtils; import org.opendaylight.netvirt.elan.utils.ElanUtils; +import org.opendaylight.netvirt.elan.utils.Scheduler; import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils; import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; @@ -74,6 +87,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.Uint64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,31 +109,37 @@ public class ElanL2GatewayMulticastUtils { private final ElanUtils elanUtils; private final IMdsalApiManager mdsalManager; private final IInterfaceManager interfaceManager; + private final ElanRefUtil elanRefUtil; + private final ElanClusterUtils elanClusterUtils; + private final Scheduler scheduler; + @Inject - public ElanL2GatewayMulticastUtils(DataBroker broker, ElanItmUtils elanItmUtils, JobCoordinator jobCoordinator, - ElanUtils elanUtils, IMdsalApiManager mdsalManager, IInterfaceManager interfaceManager) { - this.broker = broker; - this.txRunner = new ManagedNewTransactionRunnerImpl(broker); + public ElanL2GatewayMulticastUtils(ElanItmUtils elanItmUtils, ElanUtils elanUtils, IMdsalApiManager mdsalManager, + IInterfaceManager interfaceManager, ElanRefUtil elanRefUtil) { + this.elanRefUtil = elanRefUtil; + this.broker = elanRefUtil.getDataBroker(); + this.txRunner = new ManagedNewTransactionRunnerImpl(elanRefUtil.getDataBroker()); this.elanItmUtils = elanItmUtils; - this.jobCoordinator = jobCoordinator; + this.jobCoordinator = elanRefUtil.getJobCoordinator(); this.elanUtils = elanUtils; this.mdsalManager = mdsalManager; this.interfaceManager = interfaceManager; + this.elanClusterUtils = elanRefUtil.getElanClusterUtils(); + this.scheduler = elanRefUtil.getScheduler(); } /** * Handle mcast for elan l2 gw device add. * @param elanName the elan name * @param device the device - * @return the listenable future */ - public ListenableFuture handleMcastForElanL2GwDeviceAdd(String elanName, L2GatewayDevice device) { + public void handleMcastForElanL2GwDeviceAdd(String elanName, L2GatewayDevice device) { InstanceIdentifier tepPath = buildExternalTepPath(elanName, device.getTunnelIp()); - JdkFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { - tx.put(LogicalDatastoreType.CONFIGURATION, tepPath, buildExternalTeps(device)); - }), LOG, "Failed to write to config external tep {}", tepPath); - return updateMcastMacsForAllElanDevices(elanName, device, true/* updateThisDevice */); + LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + tx -> tx.put(tepPath, buildExternalTeps(device))), LOG, "Failed to write to config external tep {}", + tepPath); + updateMcastMacsForAllElanDevices(elanName, device, true/* updateThisDevice */); } public static InstanceIdentifier buildExternalTepPath(String elan, IpAddress tepIp) { @@ -138,15 +158,11 @@ public class ElanL2GatewayMulticastUtils { * * @param elanName * the elan to be updated - * @return the listenable future */ - @SuppressWarnings("checkstyle:IllegalCatch") - public ListenableFuture updateRemoteMcastMacOnElanL2GwDevices(String elanName) { - return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { - for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).values()) { - prepareRemoteMcastMacUpdateOnDevice(elanName, device); - } - }); + public void updateRemoteMcastMacOnElanL2GwDevices(String elanName) { + for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName)) { + prepareRemoteMcastMacUpdateOnDevice(elanName, device, false, null); + } } public void scheduleMcastMacUpdateJob(String elanName, L2GatewayDevice device) { @@ -161,21 +177,64 @@ public class ElanL2GatewayMulticastUtils { * the elan name * @param device * the device - * @return the listenable future */ - public ListenableFuture updateRemoteMcastMacOnElanL2GwDevice(String elanName, L2GatewayDevice device) { - return txRunner.callWithNewWriteOnlyTransactionAndSubmit( - tx -> prepareRemoteMcastMacUpdateOnDevice(elanName, device)); + public void updateRemoteMcastMacOnElanL2GwDevice(String elanName, L2GatewayDevice device) { + prepareRemoteMcastMacUpdateOnDevice(elanName, device, false, null); } - public void prepareRemoteMcastMacUpdateOnDevice(String elanName, - L2GatewayDevice device) { - ConcurrentMap elanL2gwDevices = ElanL2GwCacheUtils - .getInvolvedL2GwDevices(elanName); - List dpns = elanUtils.getElanDPNByName(elanName); + public ListenableFuture prepareRemoteMcastMacUpdateOnDevice(String elanName, L2GatewayDevice device, + boolean addCase, IpAddress removedDstTep) { + NodeId dstNodeId = new NodeId(device.getHwvtepNodeId()); + RemoteMcastMacs existingMac = null; + try { + Optional mac = elanRefUtil.getConfigMcastCache().get(getRemoteMcastIid(dstNodeId, + elanName)); + if (mac.isPresent()) { + existingMac = mac.get(); + } + } catch (ReadFailedException e) { + LOG.error("Failed to read iid for elan {}", elanName, e); + } + + if (!addCase && removedDstTep != null) { + LOG.debug(" RemoteMcast update delete tep {} of elan {} ", removedDstTep.getIpv4Address().getValue(), + elanName); + //incase of dpn flap immediately after cluster reboot just remove its tep alone + if (existingMac != null) { + return deleteLocatorFromMcast(elanName, dstNodeId, removedDstTep, existingMac); + } + } + Collection elanL2gwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName); + Collection dpns = elanRefUtil.getElanInstanceDpnsCache().get(elanName); List dpnsTepIps = getAllTepIpsOfDpns(device, dpns); List l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(elanL2gwDevices); - preapareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps); + return prepareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps, addCase); + } + + private ListenableFuture deleteLocatorFromMcast(String elanName, NodeId dstNodeId, + IpAddress removedDstTep, + RemoteMcastMacs existingMac) { + + LocatorSet tobeDeleted = buildLocatorSet(dstNodeId, removedDstTep); + RemoteMcastMacsBuilder newMacBuilder = new RemoteMcastMacsBuilder(existingMac); + + List locatorList = new ArrayList<>(existingMac.nonnullLocatorSet()); + locatorList.remove(tobeDeleted); + newMacBuilder.setLocatorSet(locatorList); + RemoteMcastMacs mac = newMacBuilder.build(); + //configMcastCache.add(macIid, mac); + InstanceIdentifier macIid = HwvtepSouthboundUtils + .createRemoteMcastMacsInstanceIdentifier(dstNodeId, existingMac.key()); + return ResourceBatchingManager.getInstance().put( + ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY, macIid, mac); + } + + LocatorSet buildLocatorSet(NodeId nodeId, IpAddress tepIp) { + HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils + .createHwvtepPhysicalLocatorAugmentation(tepIp.stringValue()); + HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef( + HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug)); + return new LocatorSetBuilder().setLocatorRef(phyLocRef).build(); } /** @@ -189,63 +248,46 @@ public class ElanL2GatewayMulticastUtils { * the device * @param updateThisDevice * the update this device - * @return the listenable future */ - private ListenableFuture updateMcastMacsForAllElanDevices(String elanName, L2GatewayDevice device, + public void updateMcastMacsForAllElanDevices(String elanName, L2GatewayDevice device, boolean updateThisDevice) { - - SettableFuture ft = SettableFuture.create(); - ft.set(null); - - List dpns = elanUtils.getElanDPNByName(elanName); - - ConcurrentMap devices = ElanL2GwCacheUtils - .getInvolvedL2GwDevices(elanName); - - List dpnsTepIps = getAllTepIpsOfDpns(device, dpns); - List l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(devices); - // if (allTepIps.size() < 2) { - // LOG.debug("no other devices are found in the elan {}", elanName); - // return ft; - // } - - return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { - if (updateThisDevice) { - preapareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps); - } - - // TODO: Need to revisit below logic as logical switches might not be - // present to configure RemoteMcastMac entry - for (L2GatewayDevice otherDevice : devices.values()) { - if (!otherDevice.getDeviceName().equals(device.getDeviceName())) { - preapareRemoteMcastMacEntry(elanName, otherDevice, dpnsTepIps, l2GwDevicesTepIps); - } - } - }); - + if (updateThisDevice) { + McastUpdateJob.updateAllMcastsForConnectionAdd(elanName, this, elanClusterUtils); + } else { + McastUpdateJob.updateAllMcastsForConnectionDelete(elanName, this, elanClusterUtils, device); + } } - public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) { + public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo, boolean createCase, + TypedWriteTransaction confTx) { List dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName()); for (DpnInterfaces dpn : dpns) { - setupElanBroadcastGroups(elanInfo, dpn.getDpId()); + setupStandardElanBroadcastGroups(elanInfo, null, dpn.getDpId(), createCase, confTx); } } - public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) { - setupElanBroadcastGroups(elanInfo, null, dpnId); + public void setupElanBroadcastGroups(ElanInstance elanInfo, Uint64 dpnId, + TypedWriteTransaction confTx) { + setupElanBroadcastGroups(elanInfo, null, dpnId, confTx); + } + + public void setupElanBroadcastGroups(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces, Uint64 dpnId, + TypedWriteTransaction confTx) { + setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId, confTx); + setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId, confTx); } - public void setupElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) { - setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId); - setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId); + public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, Uint64 dpnId, + TypedWriteTransaction confTx) { + setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId, true, confTx); } - public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) { + public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces, + Uint64 dpnId, boolean createCase, TypedWriteTransaction confTx) { List listBucket = new ArrayList<>(); int bucketId = 0; int actionKey = 0; - Long elanTag = elanInfo.getElanTag(); + Long elanTag = elanInfo.getElanTag().toJava(); List listAction = new ArrayList<>(); listAction.add(new ActionGroup(ElanUtils.getElanLocalBCGId(elanTag)).buildAction(++actionKey)); listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, @@ -257,13 +299,18 @@ public class ElanL2GatewayMulticastUtils { Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket)); LOG.trace("Installing the remote BroadCast Group:{}", group); - mdsalManager.syncInstallGroup(dpnId, group); + if (createCase) { + elanUtils.syncUpdateGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND, confTx); + } else { + mdsalManager.addGroup(confTx, dpnId, group); + } } - public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) { - EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class); + public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces, + Uint64 dpnId, TypedWriteTransaction confTx) { + EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class); if (etreeInstance != null) { - long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue(); + long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue().toJava(); List listBucket = new ArrayList<>(); int bucketId = 0; int actionKey = 0; @@ -279,14 +326,15 @@ public class ElanL2GatewayMulticastUtils { Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket)); LOG.trace("Installing the remote BroadCast Group:{}", group); - mdsalManager.syncInstallGroup(dpnId, group); + mdsalManager.addGroup(confTx, dpnId, group); } } - private DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) { + @Nullable + private static DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, Uint64 dpnId) { if (elanDpns != null) { - for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) { - if (dpnInterface.getDpId().equals(dpnId)) { + for (DpnInterfaces dpnInterface : elanDpns.nonnullDpnInterfaces().values()) { + if (Objects.equals(dpnInterface.getDpId(), dpnId)) { return dpnInterface; } } @@ -295,7 +343,7 @@ public class ElanL2GatewayMulticastUtils { } private List getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns, - DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) { + DpnInterfaces dpnInterfaces, Uint64 dpnId, int bucketId) { DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId); if (currDpnInterfaces == null || !elanUtils.isDpnPresent(currDpnInterfaces.getDpId()) || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) { @@ -315,16 +363,18 @@ public class ElanL2GatewayMulticastUtils { return listBucketInfo; } - @Nonnull - public List getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId, - int bucketId, long elanTag) { + @NonNull + public List getRemoteBCGroupBuckets(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces, + Uint64 dpnId, int bucketId, long elanTag) { List listBucketInfo = new ArrayList<>(); ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); if (isVxlanNetworkOrVxlanSegment(elanInfo)) { + // Adding 270000 to avoid collision between LPort and elan for broadcast group actions listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId, elanUtils.isOpenstackVniSemanticsEnforced() - ? elanUtils.getVxlanSegmentationId(elanInfo) : elanTag)); + ? ElanUtils.getVxlanSegmentationId(elanInfo).longValue() : elanTag + + ElanConstants.ELAN_TAG_ADDEND)); } listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId, getNextAvailableBucketId(listBucketInfo.size()))); @@ -333,19 +383,17 @@ public class ElanL2GatewayMulticastUtils { return listBucketInfo; } - public List getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId, + public List getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, Uint64 dpnId, int bucketId) { List listBucketInfo = new ArrayList<>(); - ConcurrentMap map = ElanL2GwCacheUtils - .getInvolvedL2GwDevices(elanInfo.getElanInstanceName()); - for (L2GatewayDevice device : map.values()) { + for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanInfo.getElanInstanceName())) { String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId), device.getHwvtepNodeId()); if (interfaceName == null) { continue; } List listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName, - ElanUtils.getVxlanSegmentationId(elanInfo)); + ElanUtils.getVxlanSegmentationId(elanInfo).longValue(), true); listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); bucketId++; @@ -353,27 +401,27 @@ public class ElanL2GatewayMulticastUtils { return listBucketInfo; } - public List getRemoteBCGroupBucketsOfElanExternalTeps(ElanInstance elanInfo, BigInteger dpnId, + public List getRemoteBCGroupBucketsOfElanExternalTeps(ElanInstance elanInfo, Uint64 dpnId, int bucketId) { ElanInstance operElanInstance = null; try { operElanInstance = new SingleTransactionDataBroker(broker).syncReadOptional( LogicalDatastoreType.OPERATIONAL, - InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, elanInfo.getKey()) - .build()).orNull(); - } catch (ReadFailedException e) { + InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, elanInfo.key()) + .build()).orElse(null); + } catch (InterruptedException | ExecutionException e) { LOG.error("Failed to read elan instance operational path {}", elanInfo, e); return emptyList(); } if (operElanInstance == null) { return emptyList(); } - List teps = operElanInstance.getExternalTeps(); + Map teps = operElanInstance.getExternalTeps(); if (teps == null || teps.isEmpty()) { return emptyList(); } List listBucketInfo = new ArrayList<>(); - for (ExternalTeps tep : teps) { + for (ExternalTeps tep : teps.values()) { String externalTep = tep.getNodeid() != null ? tep.getNodeid() : tep.getTepIp().toString(); String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId), externalTep); @@ -382,7 +430,7 @@ public class ElanL2GatewayMulticastUtils { continue; } List listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName, - elanUtils.getVxlanSegmentationId(elanInfo)); + ElanUtils.getVxlanSegmentationId(elanInfo).longValue(), false); listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); bucketId++; @@ -390,21 +438,23 @@ public class ElanL2GatewayMulticastUtils { return listBucketInfo; } - private int getNextAvailableBucketId(int bucketSize) { + private static int getNextAvailableBucketId(int bucketSize) { return bucketSize + 1; } @SuppressWarnings("checkstyle:IllegalCatch") - private List getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId, + private List getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, Uint64 dpnId, int bucketId, long elanTagOrVni) { List listBucketInfo = new ArrayList<>(); if (elanDpns != null) { - for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) { - if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !Objects.equals(dpnInterface.getDpId(), dpnId) - && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { + for (DpnInterfaces dpnInterface : elanDpns.nonnullDpnInterfaces().values()) { + if (!Objects.equals(dpnInterface.getDpId(), dpnId) && dpnInterface.getInterfaces() != null + && !dpnInterface.getInterfaces().isEmpty()) { try { List listActionInfo = elanItmUtils.getInternalTunnelItmEgressAction(dpnId, dpnInterface.getDpId(), elanTagOrVni); + LOG.trace("configuring broadcast group for elan {} for source DPN {} and destination DPN {} " + + "with actions {}", elanTagOrVni, dpnId, dpnInterface.getDpId(), listActionInfo); if (listActionInfo.isEmpty()) { continue; } @@ -434,9 +484,9 @@ public class ElanL2GatewayMulticastUtils { * the l2 gw devices tep ips * @return the write transaction */ - private void preapareRemoteMcastMacEntry(String elanName, + private ListenableFuture prepareRemoteMcastMacEntry(String elanName, L2GatewayDevice device, List dpnsTepIps, - List l2GwDevicesTepIps) { + List l2GwDevicesTepIps, boolean addCase) { NodeId nodeId = new NodeId(device.getHwvtepNodeId()); ArrayList remoteTepIps = new ArrayList<>(l2GwDevicesTepIps); @@ -450,17 +500,17 @@ public class ElanL2GatewayMulticastUtils { remoteTepIps.add(dhcpDesignatedSwitchTepIp); HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils - .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dhcpDesignatedSwitchTepIp.getValue())); + .createHwvtepPhysicalLocatorAugmentation(dhcpDesignatedSwitchTepIp); InstanceIdentifier iid = HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug); TerminationPoint terminationPoint = new TerminationPointBuilder() - .setKey(HwvtepSouthboundUtils.getTerminationPointKey(phyLocatorAug)) + .withKey(HwvtepSouthboundUtils.getTerminationPointKey(phyLocatorAug)) .addAugmentation(HwvtepPhysicalLocatorAugmentation.class, phyLocatorAug).build(); ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY, iid, terminationPoint); LOG.info("Adding PhysicalLocator for node: {} with Dhcp designated switch Tep Ip {} " + "as physical locator, elan {}", device.getHwvtepNodeId(), - String.valueOf(dhcpDesignatedSwitchTepIp.getValue()), elanName); + dhcpDesignatedSwitchTepIp.stringValue(), elanName); } else { LOG.warn("Dhcp designated switch Tep Ip not found for l2 gw node {} and elan {}", device.getHwvtepNodeId(), elanName); @@ -470,9 +520,9 @@ public class ElanL2GatewayMulticastUtils { remoteTepIps.add(dhcpDesignatedSwitchTepIp); } String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName); - putRemoteMcastMac(nodeId, logicalSwitchName, remoteTepIps); LOG.info("Adding RemoteMcastMac for node: {} with physical locators: {}", device.getHwvtepNodeId(), remoteTepIps); + return putRemoteMcastMac(nodeId, logicalSwitchName, remoteTepIps, addCase); } /** @@ -485,12 +535,12 @@ public class ElanL2GatewayMulticastUtils { * @param tepIps * the tep ips */ - private static void putRemoteMcastMac(NodeId nodeId, String logicalSwitchName, - ArrayList tepIps) { + private ListenableFuture putRemoteMcastMac(NodeId nodeId, String logicalSwitchName, + ArrayList tepIps, boolean addCase) { List locators = new ArrayList<>(); for (IpAddress tepIp : tepIps) { HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils - .createHwvtepPhysicalLocatorAugmentation(String.valueOf(tepIp.getValue())); + .createHwvtepPhysicalLocatorAugmentation(tepIp); HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef( HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug)); locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build()); @@ -498,16 +548,49 @@ public class ElanL2GatewayMulticastUtils { HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName))); - RemoteMcastMacs remoteMcastMac = new RemoteMcastMacsBuilder() + RemoteMcastMacs newRemoteMcastMac = new RemoteMcastMacsBuilder() .setMacEntryKey(new MacAddress(ElanConstants.UNKNOWN_DMAC)).setLogicalSwitchRef(lsRef) .setLocatorSet(locators).build(); InstanceIdentifier iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId, - remoteMcastMac.getKey()); - ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY, - iid, remoteMcastMac); + newRemoteMcastMac.key()); + RemoteMcastMacs existingRemoteMcastMac = null; + try { + Optional mac = elanRefUtil.getConfigMcastCache().get(iid); + if (mac.isPresent()) { + existingRemoteMcastMac = mac.get(); + } + } catch (ReadFailedException e) { + LOG.error("Failed to read iid {}", iid, e); + } + + if (addCase && areLocatorsAlreadyConfigured(existingRemoteMcastMac, newRemoteMcastMac)) { + return Futures.immediateFuture(null); + } + + return ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY, + iid, newRemoteMcastMac); } + private boolean areLocatorsAlreadyConfigured(RemoteMcastMacs existingMac, RemoteMcastMacs newMac) { + if (existingMac == null) { + return false; + } + Set existingLocators = new HashSet<>(existingMac.getLocatorSet()); + List newLocators = newMac.getLocatorSet(); + return existingLocators.containsAll(newLocators); + } + + private InstanceIdentifier getRemoteMcastIid(NodeId nodeId, String logicalSwitchName) { + HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils + .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName))); + RemoteMcastMacs remoteMcastMac = new RemoteMcastMacsBuilder() + .setMacEntryKey(new MacAddress(ElanConstants.UNKNOWN_DMAC)).setLogicalSwitchRef(lsRef) + .build(); + return HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId, + remoteMcastMac.key()); + } + /** * Gets all the tep ips of dpns. * @@ -517,7 +600,7 @@ public class ElanL2GatewayMulticastUtils { * the dpns * @return the all tep ips of dpns and devices */ - private List getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, List dpns) { + private List getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, Collection dpns) { List tepIps = new ArrayList<>(); for (DpnInterfaces dpn : dpns) { IpAddress internalTunnelIp = elanItmUtils.getSourceDpnTepIp(dpn.getDpId(), @@ -536,9 +619,9 @@ public class ElanL2GatewayMulticastUtils { * the devices * @return the all tep ips of l2 gw devices */ - private static List getAllTepIpsOfL2GwDevices(ConcurrentMap devices) { + private static List getAllTepIpsOfL2GwDevices(Collection devices) { List tepIps = new ArrayList<>(); - for (L2GatewayDevice otherDevice : devices.values()) { + for (L2GatewayDevice otherDevice : devices) { // There is no need to add the same tep ip to the list. if (!tepIps.contains(otherDevice.getTunnelIp())) { tepIps.add(otherDevice.getTunnelIp()); @@ -556,17 +639,15 @@ public class ElanL2GatewayMulticastUtils { * the l2 gateway device * @return the listenable future */ - public List> handleMcastForElanL2GwDeviceDelete(String elanName, + public List> handleMcastForElanL2GwDeviceDelete(String elanName, L2GatewayDevice l2GatewayDevice) { - ListenableFuture deleteTepFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { - tx.delete(LogicalDatastoreType.CONFIGURATION, - buildExternalTepPath(elanName, l2GatewayDevice.getTunnelIp())); - }); - ListenableFuture updateMcastMacsFuture = updateMcastMacsForAllElanDevices( - elanName, l2GatewayDevice, false/* updateThisDevice */); - ListenableFuture deleteRemoteMcastMacFuture = deleteRemoteMcastMac( + FluentFuture deleteTepFuture = + txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, + tx -> tx.delete(buildExternalTepPath(elanName, l2GatewayDevice.getTunnelIp()))); + updateMcastMacsForAllElanDevices(elanName, l2GatewayDevice, false/* updateThisDevice */); + FluentFuture deleteRemoteMcastMacFuture = deleteRemoteMcastMac( new NodeId(l2GatewayDevice.getHwvtepNodeId()), elanName); - return Arrays.asList(updateMcastMacsFuture, deleteRemoteMcastMacFuture, deleteTepFuture); + return Arrays.asList(deleteRemoteMcastMacFuture, deleteTepFuture); } /** @@ -578,7 +659,7 @@ public class ElanL2GatewayMulticastUtils { * the logical switch name * @return the listenable future */ - private ListenableFuture deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) { + public FluentFuture deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) { InstanceIdentifier logicalSwitch = HwvtepSouthboundUtils .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)); RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch), @@ -608,7 +689,7 @@ public class ElanL2GatewayMulticastUtils { DesignatedSwitchForTunnel desgSwitch = getDesignatedSwitchForExternalTunnel(l2GwDevice.getTunnelIp(), elanInstanceName); if (desgSwitch != null) { - tepIp = elanItmUtils.getSourceDpnTepIp(BigInteger.valueOf(desgSwitch.getDpId()), + tepIp = elanItmUtils.getSourceDpnTepIp(Uint64.valueOf(desgSwitch.getDpId()), new NodeId(l2GwDevice.getHwvtepNodeId())); } return tepIp; @@ -625,11 +706,22 @@ public class ElanL2GatewayMulticastUtils { */ public DesignatedSwitchForTunnel getDesignatedSwitchForExternalTunnel(IpAddress tunnelIp, String elanInstanceName) { - InstanceIdentifier instanceIdentifier = InstanceIdentifier + try { + InstanceIdentifier instanceIdentifier = InstanceIdentifier .builder(DesignatedSwitchesForExternalTunnels.class) - .child(DesignatedSwitchForTunnel.class, new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp)) + .child(DesignatedSwitchForTunnel.class, + new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp)) .build(); - return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier).orNull(); + return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier) + .orElse(null); + } catch (ExecutionException e) { + LOG.error("Exception while retriving DesignatedSwitch for elan {} and tunnel {}", + elanInstanceName, tunnelIp, e); + } catch (InterruptedException e) { + LOG.error("Exception while retriving DesignatedSwitch for elan {} and tunnel {}", + elanInstanceName, tunnelIp, e); + } + return null; } }