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.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;
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;
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;
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<Void> handleMcastForElanL2GwDeviceAdd(String elanName, L2GatewayDevice device) {
+ public void handleMcastForElanL2GwDeviceAdd(String elanName, L2GatewayDevice device) {
InstanceIdentifier<ExternalTeps> 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<ExternalTeps> buildExternalTepPath(String elan, IpAddress tepIp) {
*
* @param elanName
* the elan to be updated
- * @return the listenable future
*/
- @SuppressWarnings("checkstyle:IllegalCatch")
- public ListenableFuture<Void> 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) {
* the elan name
* @param device
* the device
- * @return the listenable future
*/
- public ListenableFuture<Void> 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<String, L2GatewayDevice> elanL2gwDevices = ElanL2GwCacheUtils
- .getInvolvedL2GwDevices(elanName);
- List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
+ public ListenableFuture<Void> prepareRemoteMcastMacUpdateOnDevice(String elanName, L2GatewayDevice device,
+ boolean addCase, IpAddress removedDstTep) {
+ NodeId dstNodeId = new NodeId(device.getHwvtepNodeId());
+ RemoteMcastMacs existingMac = null;
+ try {
+ Optional<RemoteMcastMacs> 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<L2GatewayDevice> elanL2gwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
+ Collection<DpnInterfaces> dpns = elanRefUtil.getElanInstanceDpnsCache().get(elanName);
List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(elanL2gwDevices);
- preapareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps);
+ return prepareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps, addCase);
+ }
+
+ private ListenableFuture<Void> deleteLocatorFromMcast(String elanName, NodeId dstNodeId,
+ IpAddress removedDstTep,
+ RemoteMcastMacs existingMac) {
+
+ LocatorSet tobeDeleted = buildLocatorSet(dstNodeId, removedDstTep);
+ RemoteMcastMacsBuilder newMacBuilder = new RemoteMcastMacsBuilder(existingMac);
+
+ List<LocatorSet> locatorList = new ArrayList<>(existingMac.nonnullLocatorSet());
+ locatorList.remove(tobeDeleted);
+ newMacBuilder.setLocatorSet(locatorList);
+ RemoteMcastMacs mac = newMacBuilder.build();
+ //configMcastCache.add(macIid, mac);
+ InstanceIdentifier<RemoteMcastMacs> 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();
}
/**
* the device
* @param updateThisDevice
* the update this device
- * @return the listenable future
*/
- private ListenableFuture<Void> updateMcastMacsForAllElanDevices(String elanName, L2GatewayDevice device,
+ public void updateMcastMacsForAllElanDevices(String elanName, L2GatewayDevice device,
boolean updateThisDevice) {
-
- SettableFuture<Void> ft = SettableFuture.create();
- ft.set(null);
-
- List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
-
- ConcurrentMap<String, L2GatewayDevice> devices = ElanL2GwCacheUtils
- .getInvolvedL2GwDevices(elanName);
-
- List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
- List<IpAddress> 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<Datastore.Configuration> confTx) {
List<DpnInterfaces> 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<Datastore.Configuration> confTx) {
+ setupElanBroadcastGroups(elanInfo, null, dpnId, confTx);
+ }
+
+ public void setupElanBroadcastGroups(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces, Uint64 dpnId,
+ TypedWriteTransaction<Datastore.Configuration> 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<Datastore.Configuration> 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<Datastore.Configuration> confTx) {
List<Bucket> listBucket = new ArrayList<>();
int bucketId = 0;
int actionKey = 0;
- Long elanTag = elanInfo.getElanTag();
+ Long elanTag = elanInfo.getElanTag().toJava();
List<Action> listAction = new ArrayList<>();
listAction.add(new ActionGroup(ElanUtils.getElanLocalBCGId(elanTag)).buildAction(++actionKey));
listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
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<Datastore.Configuration> confTx) {
+ EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
if (etreeInstance != null) {
- long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
+ long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue().toJava();
List<Bucket> listBucket = new ArrayList<>();
int bucketId = 0;
int actionKey = 0;
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()) {
+ if (Objects.equals(dpnInterface.getDpId(), dpnId)) {
return dpnInterface;
}
}
}
private List<Bucket> 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()) {
return listBucketInfo;
}
- @Nonnull
- public List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId,
- int bucketId, long elanTag) {
+ @NonNull
+ public List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces,
+ Uint64 dpnId, int bucketId, long elanTag) {
List<Bucket> 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())));
return listBucketInfo;
}
- public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
+ public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, Uint64 dpnId,
int bucketId) {
List<Bucket> listBucketInfo = new ArrayList<>();
- ConcurrentMap<String, L2GatewayDevice> 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<Action> 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++;
return listBucketInfo;
}
- public List<Bucket> getRemoteBCGroupBucketsOfElanExternalTeps(ElanInstance elanInfo, BigInteger dpnId,
+ public List<Bucket> 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();
}
continue;
}
List<Action> 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++;
return listBucketInfo;
}
- private int getNextAvailableBucketId(int bucketSize) {
+ private static int getNextAvailableBucketId(int bucketSize) {
return bucketSize + 1;
}
@SuppressWarnings("checkstyle:IllegalCatch")
- private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
+ private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, Uint64 dpnId, int bucketId,
long elanTagOrVni) {
List<Bucket> 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()) {
+ if (!Objects.equals(dpnInterface.getDpId(), dpnId) && dpnInterface.getInterfaces() != null
+ && !dpnInterface.getInterfaces().isEmpty()) {
try {
List<Action> 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;
}
* the l2 gw devices tep ips
* @return the write transaction
*/
- private void preapareRemoteMcastMacEntry(String elanName,
+ private ListenableFuture<Void> prepareRemoteMcastMacEntry(String elanName,
L2GatewayDevice device, List<IpAddress> dpnsTepIps,
- List<IpAddress> l2GwDevicesTepIps) {
+ List<IpAddress> l2GwDevicesTepIps, boolean addCase) {
NodeId nodeId = new NodeId(device.getHwvtepNodeId());
ArrayList<IpAddress> remoteTepIps = new ArrayList<>(l2GwDevicesTepIps);
remoteTepIps.add(dhcpDesignatedSwitchTepIp);
HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
- .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dhcpDesignatedSwitchTepIp.getValue()));
+ .createHwvtepPhysicalLocatorAugmentation(dhcpDesignatedSwitchTepIp);
InstanceIdentifier<TerminationPoint> 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);
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);
}
/**
* @param tepIps
* the tep ips
*/
- private static void putRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
- ArrayList<IpAddress> tepIps) {
+ private ListenableFuture<Void> putRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
+ ArrayList<IpAddress> tepIps, boolean addCase) {
List<LocatorSet> 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());
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<RemoteMcastMacs> iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
- remoteMcastMac.getKey());
- ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY,
- iid, remoteMcastMac);
+ newRemoteMcastMac.key());
+ RemoteMcastMacs existingRemoteMcastMac = null;
+ try {
+ Optional<RemoteMcastMacs> 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<RemoteMcastMacs> 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.
*
* the dpns
* @return the all tep ips of dpns and devices
*/
- private List<IpAddress> getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, List<DpnInterfaces> dpns) {
+ private List<IpAddress> getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, Collection<DpnInterfaces> dpns) {
List<IpAddress> tepIps = new ArrayList<>();
for (DpnInterfaces dpn : dpns) {
IpAddress internalTunnelIp = elanItmUtils.getSourceDpnTepIp(dpn.getDpId(),
* the devices
* @return the all tep ips of l2 gw devices
*/
- private static List<IpAddress> getAllTepIpsOfL2GwDevices(ConcurrentMap<String, L2GatewayDevice> devices) {
+ private static List<IpAddress> getAllTepIpsOfL2GwDevices(Collection<L2GatewayDevice> devices) {
List<IpAddress> 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());
* the l2 gateway device
* @return the listenable future
*/
- public List<ListenableFuture<Void>> handleMcastForElanL2GwDeviceDelete(String elanName,
+ public List<FluentFuture<?>> handleMcastForElanL2GwDeviceDelete(String elanName,
L2GatewayDevice l2GatewayDevice) {
- ListenableFuture<Void> deleteTepFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
- tx.delete(LogicalDatastoreType.CONFIGURATION,
- buildExternalTepPath(elanName, l2GatewayDevice.getTunnelIp()));
- });
- ListenableFuture<Void> updateMcastMacsFuture = updateMcastMacsForAllElanDevices(
- elanName, l2GatewayDevice, false/* updateThisDevice */);
- ListenableFuture<Void> 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);
}
/**
* the logical switch name
* @return the listenable future
*/
- private ListenableFuture<Void> deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) {
+ public FluentFuture<? extends @NonNull CommitInfo> deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) {
InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
.createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
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;
*/
public DesignatedSwitchForTunnel getDesignatedSwitchForExternalTunnel(IpAddress tunnelIp,
String elanInstanceName) {
- InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier
+ try {
+ InstanceIdentifier<DesignatedSwitchForTunnel> 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;
}
}