leaf tep-ip {
type inet:ip-address;
}
+ leaf nodeid {
+ type string;
+ }
}
}
}
return;
}
int vpnLabel = 0;
- long l2vni = elanInfo.getSegmentationId();
+ long l2vni = elanUtils.getVxlanSegmentationId(elanInfo);
long l3vni = 0;
String gatewayMacAddr = null;
String l3VpName = getL3vpnNameFromElan(elanInfo);
private void programEvpnL2vniFlow(ElanInstance elanInfo, BiConsumer<BigInteger, FlowEntity> flowHandler) {
long elanTag = elanInfo.getElanTag();
List<MatchInfo> mkMatches = new ArrayList<>();
- mkMatches.add(new MatchTunnelId(BigInteger.valueOf(elanInfo.getSegmentationId())));
+ mkMatches.add(new MatchTunnelId(BigInteger.valueOf(elanUtils.getVxlanSegmentationId(elanInfo))));
NWUtil.getOperativeDPNs(broker).forEach(dpnId -> {
LOG.debug("Updating tunnel flow to dpnid {}", dpnId);
List<InstructionInfo> instructions = getInstructionsForExtTunnelTable(elanTag);
BigInteger dpId = dataObjectModification.getDpId();
String elanInstanceName = key.firstKeyOf(ElanDpnInterfacesList.class).getElanInstanceName();
- if (!ElanUtils.isVxlan(elanInstanceCache.get(elanInstanceName).orNull())) {
+ if (!ElanUtils.isVxlanNetworkOrVxlanSegment(elanInstanceCache.get(elanInstanceName).orNull())) {
LOG.debug("ElanInstance {} is not vxlan network, nothing to do", elanInstanceName);
return;
}
BigInteger dpId = dataObjectModification.getDpId();
String elanInstanceName = key.firstKeyOf(ElanDpnInterfacesList.class).getElanInstanceName();
- if (!ElanUtils.isVxlan(elanInstanceCache.get(elanInstanceName).orNull())) {
+ if (!ElanUtils.isVxlanNetworkOrVxlanSegment(elanInstanceCache.get(elanInstanceName).orNull())) {
return;
}
--- /dev/null
+/*
+ * Copyright (c) 2018 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.internal;
+
+import javax.annotation.PostConstruct;
+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.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
+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.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class ElanExtnTepConfigListener
+ extends AsyncDataTreeChangeListenerBase<ExternalTeps, ElanExtnTepConfigListener> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ElanExtnTepConfigListener.class);
+
+ private final DataBroker broker;
+ private final ManagedNewTransactionRunner txRunner;
+
+ @Inject
+ public ElanExtnTepConfigListener(DataBroker dataBroker) {
+ super(ExternalTeps.class, ElanExtnTepConfigListener.class);
+ this.broker = dataBroker;
+ this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+ }
+
+ @Override
+ @PostConstruct
+ public void init() {
+ registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+ }
+
+ @Override
+ public InstanceIdentifier<ExternalTeps> getWildCardPath() {
+ return InstanceIdentifier
+ .builder(ElanInstances.class)
+ .child(ElanInstance.class)
+ .child(ExternalTeps.class).build();
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<ExternalTeps> iid, ExternalTeps tep) {
+ JdkFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ tx.put(LogicalDatastoreType.OPERATIONAL, iid, tep, true);
+ }), LOG, "Failed to update operational external teps {}", iid);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<ExternalTeps> iid, ExternalTeps tep, ExternalTeps t1) {
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<ExternalTeps> iid, ExternalTeps tep) {
+ JdkFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ tx.delete(LogicalDatastoreType.OPERATIONAL, iid);
+ }), LOG, "Failed to update operational external teps {}", iid);
+ }
+
+ @Override
+ protected ElanExtnTepConfigListener getDataTreeChangeListener() {
+ return this;
+ }
+}
@Override
@PostConstruct
public void init() {
- registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+ registerListener(LogicalDatastoreType.OPERATIONAL, broker);
}
@Override
- protected InstanceIdentifier<ExternalTeps> getWildCardPath() {
+ public InstanceIdentifier<ExternalTeps> getWildCardPath() {
return InstanceIdentifier.create(ElanInstances.class).child(ElanInstance.class).child(ExternalTeps.class);
}
*/
package org.opendaylight.netvirt.elan.internal;
-import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlan;
import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
import com.google.common.base.Optional;
removeEtreeBroadcastGrups(elanInfo, interfaceInfo, flowTx);
if (isVxlanNetworkOrVxlanSegment(elanInfo)) {
if (elanUtils.isOpenstackVniSemanticsEnforced()) {
- elanUtils.removeTerminatingServiceAction(dpId, elanInfo.getSegmentationId().intValue());
+ elanUtils.removeTerminatingServiceAction(dpId,
+ elanUtils.getVxlanSegmentationId(elanInfo).intValue());
}
unsetExternalTunnelTable(dpId, elanInfo);
}
// Terminating Service , UnknownDMAC Table.
// The 1st ELAN Interface in a DPN must program the INTERNAL_TUNNEL_TABLE, but only if the network type
// for ELAN Instance is VxLAN
- if (isVxlan(elanInstance)) {
+ if (isVxlanNetworkOrVxlanSegment(elanInstance)) {
setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
}
setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
try {
List<Action> remoteListActionInfo = elanItmUtils.getInternalTunnelItmEgressAction(
dpnInterface.getDpId(), otherFes.getDpId(),
- elanUtils.isOpenstackVniSemanticsEnforced() ? elanInfo.getSegmentationId()
- : elanTag);
+ elanUtils.isOpenstackVniSemanticsEnforced()
+ ? elanUtils.getVxlanSegmentationId(elanInfo) : elanTag);
if (!remoteListActionInfo.isEmpty()) {
remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil
.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
listMatchInfoBase = ElanUtils.getTunnelMatchesForServiceId((int) elanTag);
instructionInfos = getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag));
} else {
- serviceId = elanInfo.getSegmentationId();
+ serviceId = elanUtils.getVxlanSegmentationId(elanInfo);
listMatchInfoBase = buildMatchesForVni(serviceId);
instructionInfos = getInstructionsIntOrExtTunnelTable(elanTag);
}
String destination = datastoreType == CONFIGURATION ? "child" : "parent";
if (create) {
- if (isDataUpdated(existingDataOptional, data)) {
+ if (isDataUpdated(existingDataOptional, transformedItem)) {
LOG.debug("Copy to {} {} {}", destination, datastoreType, transformedId);
- tx.put(datastoreType, transformedId, data, true);
+ tx.put(datastoreType, transformedId, transformedItem, true);
} else {
LOG.debug("Data not updated skip copy to {}", transformedId);
}
package org.opendaylight.netvirt.elan.l2gw.listeners;
+import com.google.common.base.Optional;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
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.hwvtep.HwvtepAbstractDataTreeChangeListener;
import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
existingDevice.getDeviceName(), existingDevice.getTunnelIp());
Thread.sleep(10000L);//TODO remove these sleeps
LOG.info("Creating itm tunnels for device {}", existingDevice.getDeviceName());
- ElanL2GatewayUtils.createItmTunnels(itmRpcService, hwvtepId, psName,
+ ElanL2GatewayUtils.createItmTunnels(dataBroker, itmRpcService, hwvtepId, psName,
phySwitchAfter.getTunnelIps().get(0).getTunnelIpsKey());
return Collections.emptyList();
}
handleAdd(l2GwDevice);
elanClusterUtils.runOnlyInOwnerNode("Update config tunnels IP ", () -> {
- updateConfigTunnelIp(identifier, phySwitchAdded);
+ try {
+ updateConfigTunnelIp(identifier, phySwitchAdded);
+ } catch (ReadFailedException e) {
+ LOG.error("Failed to update tunnel ips {}", identifier);
+ }
});
return;
});
}
private void updateConfigTunnelIp(InstanceIdentifier<PhysicalSwitchAugmentation> identifier,
- PhysicalSwitchAugmentation phySwitchAdded) {
+ PhysicalSwitchAugmentation phySwitchAdded) throws ReadFailedException {
if (phySwitchAdded.getTunnelIps() != null) {
ListenableFutures.addErrorLogging(
txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
+ Optional<PhysicalSwitchAugmentation> existingSwitch = tx.read(
+ LogicalDatastoreType.CONFIGURATION, identifier).checkedGet();
PhysicalSwitchAugmentationBuilder psBuilder = new PhysicalSwitchAugmentationBuilder();
+ if (existingSwitch.isPresent()) {
+ psBuilder = new PhysicalSwitchAugmentationBuilder(existingSwitch.get());
+ }
psBuilder.setTunnelIps(phySwitchAdded.getTunnelIps());
- tx.merge(LogicalDatastoreType.CONFIGURATION, identifier, psBuilder.build());
+ tx.put(LogicalDatastoreType.CONFIGURATION, identifier, psBuilder.build(), true);
LOG.trace("Updating config tunnel ips {}", identifier);
- }),
- LOG, "Failed to update config tunnel ip for iid {}", identifier);
+ }), LOG, "Failed to update the config tunnel ips {}", identifier);
}
}
}
*/
package org.opendaylight.netvirt.elan.l2gw.utils;
-import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlan;
+import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
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.interfacemanager.interfaces.IInterfaceManager;
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.l2gw.jobs.HwvtepDeviceMcastMacUpdateJob;
import org.opendaylight.netvirt.elan.utils.ElanConstants;
import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
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.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
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.elan.instances.elan.instance.ExternalTepsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
*/
public ListenableFuture<Void> handleMcastForElanL2GwDeviceAdd(String elanName, ElanInstance elanInstance,
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, elanInstance, device, true/* updateThisDevice */);
}
+ public static InstanceIdentifier<ExternalTeps> buildExternalTepPath(String elan, IpAddress tepIp) {
+ return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elan))
+ .child(ExternalTeps.class, new ExternalTepsKey(tepIp)).build();
+ }
+
+ protected ExternalTeps buildExternalTeps(L2GatewayDevice device) {
+ return new ExternalTepsBuilder().setTepIp(device.getTunnelIp()).setNodeid(device.getHwvtepNodeId()).build();
+ }
+
/**
* Updates the remote mcast mac table for all the devices in this elan
* includes all the dpn tep ips and other devices tep ips in broadcast
SettableFuture<Void> ft = SettableFuture.create();
ft.set(null);
- updateRemoteBroadcastGroupForAllElanDpns(elanInstance);
-
List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
ConcurrentMap<String, L2GatewayDevice> devices = ElanL2GwCacheUtils
List<Bucket> listBucketInfo = new ArrayList<>();
ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
- if (isVxlan(elanInfo)) {
+ if (isVxlanNetworkOrVxlanSegment(elanInfo)) {
listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId,
- elanUtils.isOpenstackVniSemanticsEnforced() ? elanInfo.getSegmentationId() : elanTag));
+ elanUtils.isOpenstackVniSemanticsEnforced()
+ ? elanUtils.getVxlanSegmentationId(elanInfo) : elanTag));
}
listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId,
- getNextAvailableBucketId(listBucketInfo.size())));
- listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId,
- getNextAvailableBucketId(listBucketInfo.size())));
+ getNextAvailableBucketId(listBucketInfo.size())));
listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanExternalTeps(elanInfo, dpnId,
getNextAvailableBucketId(listBucketInfo.size())));
return listBucketInfo;
public List<Bucket> getRemoteBCGroupBucketsOfElanExternalTeps(ElanInstance elanInfo, BigInteger dpnId,
int bucketId) {
List<Bucket> listBucketInfo = new ArrayList<>();
- List<ExternalTeps> teps = elanInfo.getExternalTeps();
+ ElanInstance operElanInstance = null;
+ try {
+ operElanInstance = new SingleTransactionDataBroker(broker).syncRead(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, elanInfo.getKey())
+ .build());
+ } catch (ReadFailedException e) {
+ LOG.error("Failed to read elan instance operational path {}", elanInfo);
+ return Collections.emptyList();
+ }
+ List<ExternalTeps> teps = operElanInstance.getExternalTeps();
if (teps == null || teps.isEmpty()) {
return listBucketInfo;
}
for (ExternalTeps tep : teps) {
+ String externalTep = tep.getNodeid() != null ? tep.getNodeid() : tep.getTepIp().toString();
String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
- tep.getTepIp().toString());
+ externalTep);
if (interfaceName == null) {
LOG.error("Could not get interface name to ext tunnel {} {}", dpnId, tep.getTepIp());
continue;
}
List<Action> listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName,
- elanInfo.getSegmentationId());
+ elanUtils.getVxlanSegmentationId(elanInfo));
listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
bucketId++;
*/
public List<ListenableFuture<Void>> handleMcastForElanL2GwDeviceDelete(String elanName,
ElanInstance elanInstance, L2GatewayDevice l2GatewayDevice) {
+ ListenableFuture<Void> deleteTepFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+ tx.delete(LogicalDatastoreType.CONFIGURATION,
+ buildExternalTepPath(elanName, l2GatewayDevice.getTunnelIp()));
+ });
ListenableFuture<Void> updateMcastMacsFuture = updateMcastMacsForAllElanDevices(
elanName, elanInstance, l2GatewayDevice, false/* updateThisDevice */);
ListenableFuture<Void> deleteRemoteMcastMacFuture = deleteRemoteMcastMac(
new NodeId(l2GatewayDevice.getHwvtepNodeId()), elanName);
- return Arrays.asList(updateMcastMacsFuture, deleteRemoteMcastMacFuture);
+ return Arrays.asList(updateMcastMacsFuture, deleteRemoteMcastMacFuture, deleteTepFuture);
}
/**
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.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.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;
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 {
+ deleteStaleTunnelsOfHwvtepInITM(dataBroker, itmRpcService, hwvtepId, psName, tunnelIp);
Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
RpcResult<Void> rpcResult = result.get();
if (rpcResult.isSuccessful()) {
}
}
+ 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(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(LogicalDatastoreType.CONFIGURATION, 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();
}
String hwvtepNodeId, IpAddress tunnelIpAddr) {
elanClusterUtils.runOnlyInOwnerNode(hwvtepNodeId, "Handling Physical Switch add create itm tunnels ",
() -> {
- ElanL2GatewayUtils.createItmTunnels(itmRpcService, hwvtepNodeId, psName, tunnelIpAddr);
+ ElanL2GatewayUtils.createItmTunnels(dataBroker, itmRpcService, hwvtepNodeId, psName, tunnelIpAddr);
return Collections.emptyList();
});
Flow flowEntity;
// if openstack-vni-semantics are enforced, segmentation ID is passed as network VNI for VxLAN based provider
// networks, 0 otherwise
- long lportTagOrVni = !isOpenstackVniSemanticsEnforced() ? lportTag : isVxlan(elanInstance)
- ? elanInstance.getSegmentationId() : 0;
+ long lportTagOrVni = !isOpenstackVniSemanticsEnforced() ? lportTag : isVxlanNetworkOrVxlanSegment(elanInstance)
+ ? getVxlanSegmentationId(elanInstance) : 0;
flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTagOrVni, elanTag, macAddress, displayName,
elanInstance);
mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
elanInstance);
}
actions = getEgressActionsForInterface(interfaceName, null);
- } else if (isVxlan(elanInstance)) {
+ } else if (isVxlanNetworkOrVxlanSegment(elanInstance)) {
actions = elanItmUtils.getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTagOrVni);
}
mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
continue;
}
- if (ElanUtils.isVxlan(elanInstanceCache.get(elanInt.getElanInstanceName()).orNull())) {
+ if (ElanUtils.isVxlanNetworkOrVxlanSegment(
+ elanInstanceCache.get(elanInt.getElanInstanceName()).orNull())) {
return true;
} else {
LOG.debug("Non-VXLAN elanInstance: " + elanInt.getElanInstanceName());