*/
package org.opendaylight.netvirt.elan.l2gw.utils;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.FutureCallback;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
-
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-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.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.utils.SystemPropertyReader;
import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
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.netvirt.elan.ElanException;
+import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
+import org.opendaylight.netvirt.elan.cache.ElanInstanceDpnsCache;
+import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteLogicalSwitchJob;
import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.IetfYangUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
private static final int DEFAULT_LOGICAL_SWITCH_DELETE_DELAY_SECS = 20;
private final DataBroker broker;
+ private final ManagedNewTransactionRunner txRunner;
private final ElanDmacUtils elanDmacUtils;
private final ElanItmUtils elanItmUtils;
private final ElanClusterUtils elanClusterUtils;
private final OdlInterfaceRpcService interfaceManagerRpcService;
private final JobCoordinator jobCoordinator;
private final ElanUtils elanUtils;
+ private final ElanInstanceCache elanInstanceCache;
+ private final ElanInstanceDpnsCache elanInstanceDpnsCache;
private final ConcurrentMap<Pair<NodeId, String>, ScheduledFuture> logicalSwitchDeletedTasks
= new ConcurrentHashMap<>();
public ElanL2GatewayUtils(DataBroker broker, ElanDmacUtils elanDmacUtils, ElanItmUtils elanItmUtils,
ElanClusterUtils elanClusterUtils, OdlInterfaceRpcService interfaceManagerRpcService,
JobCoordinator jobCoordinator, ElanUtils elanUtils,
- Scheduler scheduler, ElanConfig elanConfig) {
+ Scheduler scheduler, ElanConfig elanConfig, ElanInstanceCache elanInstanceCache,
+ ElanInstanceDpnsCache elanInstanceDpnsCache) {
this.broker = broker;
+ this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
this.elanDmacUtils = elanDmacUtils;
this.elanItmUtils = elanItmUtils;
this.elanClusterUtils = elanClusterUtils;
this.elanUtils = elanUtils;
this.scheduler = scheduler;
this.elanConfig = elanConfig;
+ this.elanInstanceCache = elanInstanceCache;
+ this.elanInstanceDpnsCache = elanInstanceDpnsCache;
}
@PreDestroy
RemoteMcastMacs remoteMcastMac, IpAddress expectedPhyLocatorIp) {
if (remoteMcastMac != null) {
HwvtepPhysicalLocatorAugmentation expectedPhyLocatorAug = HwvtepSouthboundUtils
- .createHwvtepPhysicalLocatorAugmentation(String.valueOf(expectedPhyLocatorIp.getValue()));
+ .createHwvtepPhysicalLocatorAugmentation(expectedPhyLocatorIp);
HwvtepPhysicalLocatorRef expectedPhyLocRef = new HwvtepPhysicalLocatorRef(
HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, expectedPhyLocatorAug));
if (remoteMcastMac.getLocatorSet() != null) {
.createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
new MacAddress(ElanConstants.UNKNOWN_DMAC));
- RemoteMcastMacs remoteMcastMac = HwvtepUtils.getRemoteMcastMac(broker, datastoreType, nodeId,
- remoteMcastMacsKey);
- return remoteMcastMac;
+ return HwvtepUtils.getRemoteMcastMac(broker, datastoreType, nodeId, remoteMcastMacsKey);
}
/**
(InstanceIdentifier<LogicalSwitches>) localUcastMac.getLogicalSwitchRef().getValue());
if (lsOpc.isPresent()) {
LogicalSwitches ls = lsOpc.get();
- if (ls != null) {
- // Logical switch name is Elan name
- String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
- return ElanUtils.getElanInstanceByName(broker, elanName);
- } else {
- String macAddress = localUcastMac.getMacEntryKey().getValue();
- LOG.error("Could not find logical_switch for {} being added/deleted", macAddress);
- }
+ // Logical switch name is Elan name
+ String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
+ return elanInstanceCache.get(elanName).orNull();
}
return null;
}
final String macToBeAdded, final LocalUcastMacs localUcastMacs, String interfaceName) {
final String extDeviceNodeId = extL2GwDevice.getHwvtepNodeId();
final String elanInstanceName = elan.getElanInstanceName();
- final List<DpnInterfaces> elanDpns = getElanDpns(elanInstanceName);
+ final Collection<DpnInterfaces> elanDpns = getElanDpns(elanInstanceName);
ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
.getInvolvedL2GwDevices(elanInstanceName);
return;
}
- final List<DpnInterfaces> elanDpns = getElanDpns(elan.getElanInstanceName());
+ final Collection<DpnInterfaces> elanDpns = getElanDpns(elan.getElanInstanceName());
// Retrieve all participating DPNs in this Elan. Populate this MAC in
// DMAC table. Looping through all DPNs in order to add/remove mac flows
for (DpnInterfaces elanDpn : elanDpns) {
BigInteger dpnId = elanDpn.getDpId();
result.addAll(elanDmacUtils.deleteDmacFlowsToExternalMac(elan.getElanTag(), dpnId,
- l2GwDevice.getHwvtepNodeId(), mac.getValue().toLowerCase(Locale.getDefault())));
+ l2GwDevice.getHwvtepNodeId(),
+ IetfYangUtil.INSTANCE.canonizeMacAddress(mac).getValue()));
}
return result;
});
* the elan name
* @param dpnId
* the dpn id
- * @throws ReadFailedException if a read fails throws ReadFailedException
*/
- public void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId)
- throws ReadFailedException {
+ public void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId) {
ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
if (elanL2GwDevices == null || elanL2GwDevices.isEmpty()) {
LOG.trace("No L2 gateway devices in Elan [{}] cache.", elanName);
return;
}
- final ElanInstance elan = ElanUtils.getElanInstanceByName(broker, elanName);
+ final ElanInstance elan = elanInstanceCache.get(elanName).orNull();
if (elan == null) {
LOG.error("Could not find Elan by name: {}", elanName);
return;
@Override
public void onSuccess(Optional<Node> configNode) {
if (configNode != null && configNode.isPresent()) {
- HwvtepGlobalAugmentation augmentation = configNode.get().getAugmentation(
+ HwvtepGlobalAugmentation augmentation = configNode.get().augmentation(
HwvtepGlobalAugmentation.class);
if (augmentation != null && augmentation.getLocalUcastMacs() != null) {
macs.addAll(augmentation.getLocalUcastMacs().stream()
.filter(mac -> getLogicalSwitchName(mac).equals(elanName))
- .map(mac -> mac.getMacEntryKey())
+ .map(HwvtepMacTableGenericAttributes::getMacEntryKey)
.collect(Collectors.toSet()));
}
function.apply(macs);
@Override
public void onFailure(Throwable throwable) {
- LOG.error("Failed to read config topology node ", nodeIid);
+ LOG.error("Failed to read config topology node {}", nodeIid);
}
}, MoreExecutors.directExecutor());
}
@Override
public void onFailure(Throwable error) {
- LOG.warn(String.format("Failed during batch delete of elan [%s] macs from l2gw device [%s]. "
- + "Retrying with sequential deletes.", elanName, hwvtepNodeId), error);
+ LOG.warn("Failed during batch delete of elan {} macs from l2gw device {}. "
+ + "Retrying with sequential deletes.", elanName, hwvtepNodeId, error);
if (lstElanMacs != null && !lstElanMacs.isEmpty()) {
for (MacAddress mac : lstElanMacs) {
HwvtepUtils.deleteRemoteUcastMac(broker, new NodeId(hwvtepNodeId), logicalSwitch, mac);
List<MacAddress> lstMacs = Collections.emptyList();
Node hwvtepNode = HwvtepUtils.getHwVtepNode(broker, datastoreType, hwvtepNodeId);
if (hwvtepNode != null) {
- List<RemoteUcastMacs> remoteUcastMacs = hwvtepNode.getAugmentation(HwvtepGlobalAugmentation.class)
+ List<RemoteUcastMacs> remoteUcastMacs = hwvtepNode.augmentation(HwvtepGlobalAugmentation.class)
.getRemoteUcastMacs();
if (remoteUcastMacs != null && !remoteUcastMacs.isEmpty()) {
// Filtering remoteUcastMacs based on the logical switch and
List<RemoteUcastMacs> lstL2GatewayDevicesMacs = getOtherDevicesMacs(elanName, l2GatewayDevice, hwVtepNodeId,
logicalSwitchName);
- List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName, l2GatewayDevice,
+ List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName,
hwVtepNodeId, logicalSwitchName);
List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>(lstL2GatewayDevicesMacs);
if (!areMLAGDevices(l2GatewayDeviceToBeConfigured, otherDevice)) {
for (LocalUcastMacs localUcastMac : otherDevice.getUcastLocalMacs()) {
HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
- .createHwvtepPhysicalLocatorAugmentation(
- String.valueOf(otherDevice.getTunnelIp().getValue()));
+ .createHwvtepPhysicalLocatorAugmentation(otherDevice.getTunnelIp());
RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
- localUcastMac.getMacEntryKey().getValue().toLowerCase(Locale.getDefault()),
- localUcastMac.getIpaddr(), logicalSwitchName, physLocatorAug);
+ IetfYangUtil.INSTANCE.canonizeMacAddress(localUcastMac.getMacEntryKey()).getValue(),
+ localUcastMac.getIpaddr(), logicalSwitchName, physLocatorAug);
lstRemoteUcastMacs.add(remoteUcastMac);
}
}
*
* @param elanName
* the elan name
- * @param l2GatewayDeviceToBeConfigured
- * the l2 gateway device to be configured
* @param hwVtepNodeId
* the hw vtep node id
* @param logicalSwitchName
* @return the elan mac table entries as remote ucast macs
*/
public List<RemoteUcastMacs> getElanMacTableEntriesMacs(String elanName,
- L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
+ NodeId hwVtepNodeId, String logicalSwitchName) {
List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
MacTable macTable = ElanUtils.getElanMacTable(broker, elanName);
continue;
}
HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
- .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dpnTepIp.getValue()));
+ .createHwvtepPhysicalLocatorAugmentation(dpnTepIp);
// TODO: Query ARP cache to get IP address corresponding to the
// MAC
RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
- macEntry.getMacAddress().getValue().toLowerCase(Locale.getDefault()), null /*IpAddress*/,
+ IetfYangUtil.INSTANCE.canonizePhysAddress(macEntry.getMacAddress()).getValue(), null /*IpAddress*/,
logicalSwitchName, physLocatorAug);
lstRemoteUcastMacs.add(remoteUcastMac);
}
dpId = rpcResult.getResult().getDpid();
}
} catch (InterruptedException | ExecutionException e) {
- LOG.error("Failed to get the DPN ID for interface {}: {} ", interfaceName, e);
+ LOG.error("Failed to get the DPN ID for interface {}", interfaceName, e);
}
return dpId;
}
return Futures.immediateFailedFuture(new RuntimeException(errMsg));
}
- WriteTransaction transaction = broker.newWriteOnlyTransaction();
- for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
- .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
- //Removed the check for checking terminationPoint present in OP or not
- //for coniguring vlan bindings
- //As we are not any more dependent on it , plugin takes care of this
- // with port reconcilation.
- List<VlanBindings> vlanBindings = new ArrayList<>();
- if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
- for (Integer vlanId : deviceInterface.getSegmentationIds()) {
- vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, vlanId, logicalSwitchName));
+ return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
+ .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
+ //Removed the check for checking terminationPoint present in OP or not
+ //for coniguring vlan bindings
+ //As we are not any more dependent on it , plugin takes care of this
+ // with port reconcilation.
+ List<VlanBindings> vlanBindings = new ArrayList<>();
+ if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
+ for (Integer vlanId : deviceInterface.getSegmentationIds()) {
+ vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, vlanId, logicalSwitchName));
+ }
+ } else {
+ // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
+ // ID not specified at interface level.
+ vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, defaultVlanId, logicalSwitchName));
}
- } else {
- // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
- // ID not specified at interface level.
- vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, defaultVlanId, logicalSwitchName));
+ HwvtepUtils.mergeVlanBindings(tx, nodeId, hwVtepDevice.getDeviceName(),
+ deviceInterface.getInterfaceName(), vlanBindings);
}
- HwvtepUtils.mergeVlanBindings(transaction, nodeId, hwVtepDevice.getDeviceName(),
- deviceInterface.getInterfaceName(), vlanBindings);
- }
- ListenableFuture<Void> future = transaction.submit();
- LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}, LogicalSwitch: {}", nodeId.getValue(),
- logicalSwitchName);
- return future;
+ LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}, LogicalSwitch: {}", nodeId.getValue(),
+ logicalSwitchName);
+ });
}
/**
*/
public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String psName,
String interfaceName, List<VlanBindings> vlanBindings) {
- WriteTransaction transaction = broker.newWriteOnlyTransaction();
- HwvtepUtils.mergeVlanBindings(transaction, nodeId, psName, interfaceName, vlanBindings);
- ListenableFuture<Void> future = transaction.submit();
- LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}", nodeId.getValue());
- return future;
+ return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ HwvtepUtils.mergeVlanBindings(tx, nodeId, psName, interfaceName, vlanBindings);
+ LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}", nodeId.getValue());
+ });
}
/**
}
NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, hwVtepDevice.getDeviceName());
- WriteTransaction transaction = broker.newWriteOnlyTransaction();
- for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
- .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
- String phyPortName = deviceInterface.getInterfaceName();
- if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
- for (Integer vlanId : deviceInterface.getSegmentationIds()) {
- HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, vlanId);
+ return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712
+ .l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice.getInterfaces()) {
+ String phyPortName = deviceInterface.getInterfaceName();
+ if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
+ for (Integer vlanId : deviceInterface.getSegmentationIds()) {
+ HwvtepUtils.deleteVlanBinding(tx, physicalSwitchNodeId, phyPortName, vlanId);
+ }
+ } else {
+ // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
+ // ID not specified at interface level.
+ HwvtepUtils.deleteVlanBinding(tx, physicalSwitchNodeId, phyPortName, defaultVlanId);
}
- } else {
- // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
- // ID not specified at interface level.
- HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, defaultVlanId);
}
- }
- ListenableFuture<Void> future = transaction.submit();
-
- LOG.info("Deleted Hwvtep VlanBindings from config DS. NodeID: {}, hwVtepDevice: {}, defaultVlanId: {} ",
- nodeId.getValue(), hwVtepDevice, defaultVlanId);
- return future;
+ LOG.info("Deleted Hwvtep VlanBindings from config DS. NodeID: {}, hwVtepDevice: {}, defaultVlanId: {} ",
+ nodeId.getValue(), hwVtepDevice, defaultVlanId);
+ });
}
/**
/**
* Gets the l2 gateway connection job key.
*
- * @param nodeId
- * the node id
* @param logicalSwitchName
* the logical switch name
* @return the l2 gateway connection job key
*/
- public static String getL2GatewayConnectionJobKey(String nodeId, String logicalSwitchName) {
+ public static String getL2GatewayConnectionJobKey(String logicalSwitchName) {
return logicalSwitchName;
}
* from elan
* @param elanName
* the elan name
- * @throws ReadFailedException if a read fails
*/
public void deleteL2GwDeviceUcastLocalMacsFromElan(L2GatewayDevice l2GatewayDevice,
- String elanName) throws ReadFailedException {
+ String elanName) {
LOG.info("Deleting L2GatewayDevice [{}] UcastLocalMacs from elan [{}]", l2GatewayDevice.getHwvtepNodeId(),
elanName);
- ElanInstance elan = ElanUtils.getElanInstanceByName(broker, elanName);
+ ElanInstance elan = elanInstanceCache.get(elanName).orNull();
if (elan == null) {
LOG.error("Could not find Elan by name: {}", elanName);
return;
unInstallL2GwUcastMacFromElanDpns(elan, l2GatewayDevice, localMacs);
}
- public static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
- IpAddress tunnelIp) {
+ public static void createItmTunnels(DataBroker dataBroker, ItmRpcService itmRpcService,
+ String hwvtepId, String psName, IpAddress tunnelIp) {
AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
builder.setIpAddress(tunnelIp);
try {
- Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
- RpcResult<Void> rpcResult = result.get();
+ deleteStaleTunnelsOfHwvtepInITM(dataBroker, itmRpcService, hwvtepId, psName, tunnelIp);
+ RpcResult<AddL2GwDeviceOutput> rpcResult = itmRpcService.addL2GwDevice(builder.build()).get();
if (rpcResult.isSuccessful()) {
LOG.info("Created ITM tunnels for {}", hwvtepId);
} else {
- LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
+ LOG.error("Failed to create ITM Tunnels: {}", rpcResult.getErrors());
}
} catch (InterruptedException | ExecutionException e) {
LOG.error("RPC to create ITM tunnels failed", e);
}
}
+ private static void deleteStaleTunnelsOfHwvtepInITM(DataBroker dataBroker,
+ ItmRpcService itmRpcService,
+ String globalNodeId,
+ String psName,
+ IpAddress tunnelIp) {
+ try {
+ Optional<TransportZones> tzonesoptional = readTransportZone(dataBroker);
+ if (!tzonesoptional.isPresent() || tzonesoptional.get().getTransportZone() == null) {
+ return;
+ }
+ String psNodeId = globalNodeId + HwvtepHAUtil.PHYSICALSWITCH + psName;
+ tzonesoptional.get().getTransportZone().stream()
+ .filter(transportZone -> transportZone.getSubnets() != null)
+ .flatMap(transportZone -> transportZone.getSubnets().stream())
+ .filter(subnet -> subnet.getDeviceVteps() != null)
+ .flatMap(subnet -> subnet.getDeviceVteps().stream())
+ .filter(deviceVteps -> Objects.equals(getPsName(deviceVteps), psName)) //get device with same ps name
+ .filter(deviceVteps -> !Objects.equals(psNodeId, deviceVteps.getNodeId())
+ || !Objects.equals(tunnelIp, deviceVteps.getIpAddress()))//node id or tunnel ip is changed
+ .forEach(deviceVteps -> deleteStaleL2gwTep(dataBroker, itmRpcService, deviceVteps));
+ } catch (ReadFailedException e) {
+ LOG.error("Failed delete stale tunnels for {}", globalNodeId);
+ }
+ }
+
+ private static Optional<TransportZones> readTransportZone(DataBroker dataBroker) throws ReadFailedException {
+ return new SingleTransactionDataBroker(dataBroker).syncReadOptional(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(TransportZones.class).build());
+ }
+
+ private static Optional<ElanInstances> readElanInstances(DataBroker dataBroker) throws ReadFailedException {
+ return new SingleTransactionDataBroker(dataBroker).syncReadOptional(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(ElanInstances.class).build());
+ }
+
+ private static String getPsName(DeviceVteps deviceVteps) {
+ return HwvtepHAUtil.getPsName(HwvtepHAUtil.convertToInstanceIdentifier(deviceVteps.getNodeId()));
+ }
+
+ private static void deleteStaleL2gwTep(DataBroker dataBroker,
+ ItmRpcService itmRpcService,
+ DeviceVteps deviceVteps) {
+ String psName = HwvtepHAUtil.getPsName(HwvtepHAUtil.convertToInstanceIdentifier(deviceVteps.getNodeId()));
+ String globalNodeId = HwvtepHAUtil.convertToGlobalNodeId(deviceVteps.getNodeId());
+ try {
+ LOG.info("Deleting stale tep {} ", deviceVteps);
+ L2GatewayUtils.deleteItmTunnels(itmRpcService, globalNodeId, psName, deviceVteps.getIpAddress());
+ Optional<ElanInstances> optionalElan = readElanInstances(dataBroker);
+ if (!optionalElan.isPresent()) {
+ return;
+ }
+ JdkFutures.addErrorLogging(
+ new ManagedNewTransactionRunnerImpl(dataBroker).callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+ tx -> {
+ optionalElan.get().getElanInstance().stream()
+ .flatMap(elan -> elan.getExternalTeps().stream()
+ .map(externalTep -> ElanL2GatewayMulticastUtils.buildExternalTepPath(
+ elan.getElanInstanceName(), externalTep.getTepIp())))
+ .filter(externalTepIid -> Objects.equals(
+ deviceVteps.getIpAddress(), externalTepIid.firstKeyOf(ExternalTeps.class).getTepIp()))
+ .peek(externalTepIid -> LOG.info("Deleting stale external tep {}", externalTepIid))
+ .forEach(externalTepIid -> tx.delete(externalTepIid));
+ }), LOG, "Failed to delete stale external teps {}", deviceVteps);
+ Thread.sleep(10000);//TODO remove the sleep currently it waits for interfacemgr to finish the cleanup
+ } catch (ReadFailedException | InterruptedException e) {
+ LOG.error("Failed to delete stale l2gw tep {}", deviceVteps, e);
+ }
+ }
+
public static String getNodeIdFromDpnId(BigInteger dpnId) {
return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
}
public void scheduleDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName, final boolean clearUcast) {
final Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
- logicalSwitchDeletedTasks.computeIfAbsent(nodeIdLogicalSwitchNamePair, (key) -> {
- return scheduler.getScheduledExecutorService().schedule(() -> {
+ logicalSwitchDeletedTasks.computeIfAbsent(nodeIdLogicalSwitchNamePair,
+ (key) -> scheduler.getScheduledExecutorService().schedule(() -> {
DeleteLogicalSwitchJob deleteLsJob = new DeleteLogicalSwitchJob(broker,
ElanL2GatewayUtils.this, hwvtepNodeId, lsName, clearUcast);
jobCoordinator.enqueueJob(deleteLsJob.getJobKey(), deleteLsJob,
SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
deleteJobs.put(nodeIdLogicalSwitchNamePair, deleteLsJob);
logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
- }, getLogicalSwitchDeleteDelaySecs(), TimeUnit.SECONDS);
- });
+ }, getLogicalSwitchDeleteDelaySecs(), TimeUnit.SECONDS));
}
public void cancelDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
}
@Nonnull
- public List<DpnInterfaces> getElanDpns(String elanName) {
- Set<DpnInterfaces> dpnInterfaces = ElanUtils.getElanInvolvedDPNsFromCache(elanName);
- if (dpnInterfaces == null) {
- return elanUtils.getElanDPNByName(elanName);
+ public Collection<DpnInterfaces> getElanDpns(String elanName) {
+ Collection<DpnInterfaces> dpnInterfaces = elanInstanceDpnsCache.get(elanName);
+ if (!dpnInterfaces.isEmpty()) {
+ return dpnInterfaces;
}
- return new ArrayList<>(dpnInterfaces);
+
+ return elanUtils.getElanDPNByName(elanName);
}
/**
Optional<Node> configNode = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
HwvtepSouthboundUtils.createInstanceIdentifier(new NodeId(l2gwDevice.getHwvtepNodeId())));
if (configNode.isPresent()) {
- HwvtepGlobalAugmentation augmentation = configNode.get().getAugmentation(HwvtepGlobalAugmentation.class);
+ HwvtepGlobalAugmentation augmentation = configNode.get().augmentation(HwvtepGlobalAugmentation.class);
if (augmentation != null && augmentation.getLocalUcastMacs() != null) {
macs.addAll(augmentation.getLocalUcastMacs().stream()
.filter(mac -> getLogicalSwitchName(mac).equals(elanName))
- .map(mac -> mac.getMacEntryKey())
+ .map(HwvtepMacTableGenericAttributes::getMacEntryKey)
.collect(Collectors.toSet()));
}
}