--- /dev/null
+/*
+ * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.elan.cache;
+
+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.genius.mdsalutil.cache.InstanceIdDataObjectCache;
+import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.infrautils.caches.CacheProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class ConfigMcastCache extends InstanceIdDataObjectCache<RemoteMcastMacs> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigMcastCache.class);
+
+ @Inject
+ public ConfigMcastCache(DataBroker dataBroker, CacheProvider cacheProvider) {
+ super(RemoteMcastMacs.class, dataBroker, LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+ .child(Node.class).augmentation(HwvtepGlobalAugmentation.class)
+ .child(RemoteMcastMacs.class), cacheProvider);
+ }
+}
import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
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.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.jdt.annotation.NonNull;
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, ElanClusterUtils elanClusterUtils,
- Scheduler scheduler) {
- 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 = elanClusterUtils;
- this.scheduler = scheduler;
+ this.elanClusterUtils = elanRefUtil.getElanClusterUtils();
+ this.scheduler = elanRefUtil.getScheduler();
}
/**
*/
public void updateRemoteMcastMacOnElanL2GwDevices(String elanName) {
for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName)) {
- prepareRemoteMcastMacUpdateOnDevice(elanName, device);
+ prepareRemoteMcastMacUpdateOnDevice(elanName, device, false, null);
}
}
* the device
*/
public void updateRemoteMcastMacOnElanL2GwDevice(String elanName, L2GatewayDevice device) {
- prepareRemoteMcastMacUpdateOnDevice(elanName, device);
+ prepareRemoteMcastMacUpdateOnDevice(elanName, device, false, null);
}
- public ListenableFuture<Void> prepareRemoteMcastMacUpdateOnDevice(String elanName, L2GatewayDevice device) {
+ 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);
- List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
+ Collection<DpnInterfaces> dpns = elanRefUtil.getElanInstanceDpnsCache().get(elanName);
List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(elanL2gwDevices);
- return prepareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps);
+ return prepareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps, addCase);
+ }
+
+ private ListenableFuture<Void> deleteLocatorFromMcast(String elanName, NodeId dstNodeId,
+ IpAddress removedDstTep,
+ RemoteMcastMacs existingMac) {
+ InstanceIdentifier<RemoteMcastMacs> macIid = HwvtepSouthboundUtils
+ .createRemoteMcastMacsInstanceIdentifier(dstNodeId, existingMac.key());
+ LocatorSet tobeDeleted = buildLocatorSet(dstNodeId, removedDstTep);
+ RemoteMcastMacsBuilder newMacBuilder = new RemoteMcastMacsBuilder(existingMac);
+ newMacBuilder.getLocatorSet().remove(tobeDeleted);
+ RemoteMcastMacs mac = newMacBuilder.build();
+ //configMcastCache.add(macIid, mac);
+ 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();
}
/**
*/
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);
String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName);
LOG.info("Adding RemoteMcastMac for node: {} with physical locators: {}", device.getHwvtepNodeId(),
remoteTepIps);
- return putRemoteMcastMac(nodeId, logicalSwitchName, remoteTepIps);
+ return putRemoteMcastMac(nodeId, logicalSwitchName, remoteTepIps, addCase);
}
/**
* @param tepIps
* the tep ips
*/
- private static ListenableFuture<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
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.key());
+ 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, remoteMcastMac);
+ 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());
}
/**
* 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(),