X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=vpnmanager%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Fvpnmanager%2FVpnUtil.java;h=492218577b304cbd86ee9702b7b983c03807a32e;hb=08ba938c488a04dcb24d15a2048848f5f5be2430;hp=c14d526c6dbd674fdc2953f38c87586e81ddfef4;hpb=f7778be59f1ee59fd4696257b5369cf9935a8ea4;p=netvirt.git diff --git a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java index c14d526c6d..492218577b 100644 --- a/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java +++ b/vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java @@ -9,7 +9,6 @@ package org.opendaylight.netvirt.vpnmanager; import static java.util.Collections.emptyList; -import static java.util.Objects.requireNonNull; import static org.opendaylight.genius.infra.Datastore.OPERATIONAL; import com.google.common.base.Optional; @@ -37,11 +36,12 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Predicate; import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import javax.inject.Singleton; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; 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; @@ -72,6 +72,7 @@ import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination; import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType; import org.opendaylight.genius.mdsalutil.matches.MatchMetadata; +import org.opendaylight.genius.utils.JvmGlobalLocks; import org.opendaylight.genius.utils.ServiceIndex; import org.opendaylight.genius.utils.SystemPropertyReader; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; @@ -154,7 +155,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev15033 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey; @@ -173,6 +173,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Vpn import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInterfaceOpData; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroutes; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortBuilder; @@ -227,6 +228,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev15060 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey; @@ -244,6 +246,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.s import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -254,6 +258,7 @@ public final class VpnUtil { private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class); public static final int SINGLE_TRANSACTION_BROKER_NO_RETRY = 1; + private static Boolean arpLearningEnabled = Boolean.TRUE; private final DataBroker dataBroker; private final IdManagerService idManager; @@ -332,7 +337,7 @@ public final class VpnUtil { } static VpnInterfaceOpDataEntry getVpnInterfaceOpDataEntry(String intfName, String vpnName, AdjacenciesOp aug, - BigInteger dpnId, long lportTag, + Uint64 dpnId, long lportTag, String gwMac) { return new VpnInterfaceOpDataEntryBuilder().withKey(new VpnInterfaceOpDataEntryKey(intfName, vpnName)) .setDpnId(dpnId).addAugmentation(AdjacenciesOp.class, aug) @@ -347,16 +352,16 @@ public final class VpnUtil { return vpnInterfaceOpDataEntry; } - static InstanceIdentifier getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) { + static InstanceIdentifier getPrefixToInterfaceIdentifier(Uint32 vpnId, String ipPrefix) { return InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)) .child(Prefixes.class, new PrefixesKey(ipPrefix)).build(); } - static InstanceIdentifier getPrefixToInterfaceIdentifier(long vpnId) { + static InstanceIdentifier getPrefixToInterfaceIdentifier(Uint32 vpnId) { return InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(); } - static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix, + static Prefixes getPrefixToInterface(Uint64 dpId, String vpnInterfaceName, String ipPrefix, Uuid networkId, NetworkType networkType, Long segmentationId, Prefixes.PrefixCue prefixCue) { return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName( vpnInterfaceName).setIpAddress(ipPrefix)//.setSubnetId(subnetId) @@ -364,13 +369,13 @@ public final class VpnUtil { .setPrefixCue(prefixCue).build(); } - static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix, + static Prefixes getPrefixToInterface(Uint64 dpId, String vpnInterfaceName, String ipPrefix, Prefixes.PrefixCue prefixCue) { return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(vpnInterfaceName).setIpAddress(ipPrefix) .setPrefixCue(prefixCue).build(); } - Optional getPrefixToInterface(long vpnId, String ipPrefix) { + Optional getPrefixToInterface(Uint32 vpnId, String ipPrefix) { return read(LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, getIpPrefix(ipPrefix))); } @@ -431,7 +436,7 @@ public final class VpnUtil { return vpnInstance.isPresent() ? vpnInstance.get() : null; } - @Nonnull + @NonNull List getAllVpnInstanceOpData() { InstanceIdentifier id = InstanceIdentifier.builder(VpnInstanceOpData.class).build(); Optional vpnInstanceOpDataOptional = read(LogicalDatastoreType.OPERATIONAL, id); @@ -441,10 +446,10 @@ public final class VpnUtil { : emptyList(); } - @Nonnull + @NonNull List getDpnVpnInterfaces(VpnInstance vpnInstance, - BigInteger dpnId) { + Uint64 dpnId) { String primaryRd = getPrimaryRd(vpnInstance); InstanceIdentifier dpnToVpnId = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId); Optional dpnInVpn = read(LogicalDatastoreType.OPERATIONAL, dpnToVpnId); @@ -452,7 +457,7 @@ public final class VpnUtil { : emptyList(); } - @Nonnull + @NonNull static List getListOfRdsFromVpnInstance(VpnInstance vpnInstance) { VpnAfConfig vpnConfig = vpnInstance.getIpv4Family(); LOG.trace("vpnConfig {}", vpnConfig); @@ -492,9 +497,9 @@ public final class VpnUtil { } @Nullable - String getVpnInterfaceName(BigInteger metadata) throws InterruptedException, ExecutionException { + String getVpnInterfaceName(Uint64 metadata) throws InterruptedException, ExecutionException { GetInterfaceFromIfIndexInputBuilder ifIndexInputBuilder = new GetInterfaceFromIfIndexInputBuilder(); - BigInteger lportTag = MetaDataUtil.getLportFromMetadata(metadata); + Uint64 lportTag = MetaDataUtil.getLportFromMetadata(metadata); ifIndexInputBuilder.setIfIndex(lportTag.intValue()); GetInterfaceFromIfIndexInput input = ifIndexInputBuilder.build(); Future> interfaceFromIfIndex = @@ -525,17 +530,18 @@ public final class VpnUtil { new InterfaceKey(interfaceName)).build(); } - public static BigInteger getCookieL3(int vpnId) { - return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0610000", 16)).add(BigInteger.valueOf(vpnId)); + public static Uint64 getCookieL3(int vpnId) { + return Uint64.valueOf(VpnConstants.COOKIE_L3_BASE.toJava().add(new BigInteger("0610000", 16)) + .add(BigInteger.valueOf(vpnId))); } - public int getUniqueId(String poolName, String idKey) { + public Uint32 getUniqueId(String poolName, String idKey) { AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build(); try { Future> result = idManager.allocateId(getIdInput); RpcResult rpcResult = result.get(); if (rpcResult.isSuccessful()) { - return rpcResult.getResult().getIdValue().intValue(); + return rpcResult.getResult().getIdValue(); } else { LOG.error("getUniqueId: RPC Call to Get Unique Id from pool {} with key {} returned with Errors {}", poolName, idKey, rpcResult.getErrors()); @@ -543,7 +549,7 @@ public final class VpnUtil { } catch (InterruptedException | ExecutionException e) { LOG.error("getUniqueId: Exception when getting Unique Id from pool {} for key {}", poolName, idKey, e); } - return 0; + return Uint32.ZERO; } void releaseId(String poolName, String idKey) { @@ -570,14 +576,15 @@ public final class VpnUtil { * @param vpnName Name of the VPN * @return the dataplane identifier of the VPN, the VrfTag. */ - public long getVpnId(String vpnName) { + public Uint32 getVpnId(String vpnName) { if (vpnName == null) { return VpnConstants.INVALID_ID; } return read(LogicalDatastoreType.CONFIGURATION, VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnName)) .toJavaUtil().map(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911 - .vpn.instance.to.vpn.id.VpnInstance::getVpnId).orElse(VpnConstants.INVALID_ID); + .vpn.instance.to.vpn.id.VpnInstance::getVpnId) + .orElse(VpnConstants.INVALID_ID); } /** @@ -628,8 +635,7 @@ public final class VpnUtil { ListenableFutures.addErrorLogging( new ManagedNewTransactionRunnerImpl(dataBroker).callWithNewWriteOnlyTransactionAndSubmit( Datastore.CONFIGURATION, tx -> { - for (VrfEntry vrfEntry : requireNonNullElse(vrfTables.getVrfEntry(), - Collections.emptyList())) { + for (VrfEntry vrfEntry : vrfTables.nonnullVrfEntry()) { if (origin == RouteOrigin.value(vrfEntry.getOrigin())) { tx.delete(vpnVrfTableIid.child(VrfEntry.class, vrfEntry.key())); } @@ -645,8 +651,8 @@ public final class VpnUtil { List matches = new ArrayList<>(); if (vrfTablesOpc.isPresent()) { VrfTables vrfTables = vrfTablesOpc.get(); - for (VrfEntry vrfEntry : requireNonNullElse(vrfTables.getVrfEntry(), Collections.emptyList())) { - requireNonNullElse(vrfEntry.getRoutePaths(), Collections.emptyList()).stream() + for (VrfEntry vrfEntry : vrfTables.nonnullVrfEntry()) { + vrfEntry.nonnullRoutePaths().stream() .filter(routePath -> routePath.getNexthopAddress() != null && routePath.getNexthopAddress() .equals(nexthop)).findFirst().ifPresent(routePath -> matches.add(vrfEntry)); } @@ -699,7 +705,7 @@ public final class VpnUtil { MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, VpnExtraRouteHelper.getUsedRdsIdentifier(getVpnId(vpnName), prefix, nextHop)); - LOG.debug("removeOrUpdateDSForExtraRoute: Removed vpn-to-extraroute with rd {} prefix {} nexthop {}", + LOG.info("removeOrUpdateDSForExtraRoute: Removed vpn-to-extraroute with rd {} prefix {} nexthop {}", extraRouteRd, prefix, nextHop); fibManager.refreshVrfEntry(primaryRd, prefix); operTx.delete(VpnUtil.getVpnInterfaceOpDataEntryAdjacencyIdentifier(vpnInterfaceName, vpnName, prefix)); @@ -712,13 +718,13 @@ public final class VpnUtil { } static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance - getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) { + getVpnInstanceToVpnId(String vpnName, Uint32 vpnId, String rd) { return new VpnInstanceBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build(); } static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds - getVpnIdToVpnInstance(long vpnId, String vpnName, String rd, boolean isExternalVpn) { + getVpnIdToVpnInstance(Uint32 vpnId, String vpnName, String rd, boolean isExternalVpn) { return new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance .VpnIdsBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).setExternalVpn(isExternalVpn) .build(); @@ -726,7 +732,7 @@ public final class VpnUtil { } static InstanceIdentifier getVpnIdToVpnInstanceIdentifier(long vpnId) { + .vpn.instance.VpnIds> getVpnIdToVpnInstanceIdentifier(Uint32 vpnId) { return InstanceIdentifier.builder(VpnIdToVpnInstance.class).child(org.opendaylight.yang.gen.v1.urn .opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance @@ -740,7 +746,7 @@ public final class VpnUtil { * @return the Vpn instance name */ @Nullable - String getVpnName(long vpnId) { + String getVpnName(Uint32 vpnId) { InstanceIdentifier id = getVpnIdToVpnInstanceIdentifier(vpnId); @@ -799,11 +805,7 @@ public final class VpnUtil { } public static String getIpPrefix(String prefix) { - String[] prefixValues = prefix.split("/"); - if (prefixValues.length == 1) { - prefix = NWUtil.toIpPrefix(prefix); - } - return prefix; + return prefix.indexOf('/') != -1 ? prefix : NWUtil.toIpPrefix(prefix); } static final FutureCallback DEFAULT_CALLBACK = @@ -886,38 +888,38 @@ public final class VpnUtil { new ElanTagNameKey(elanTag)).build(); } - static void removePrefixToInterfaceForVpnId(long vpnId, @Nonnull TypedWriteTransaction operTx) { + static void removePrefixToInterfaceForVpnId(Uint32 vpnId, @NonNull TypedWriteTransaction operTx) { // Clean up PrefixToInterface Operational DS operTx.delete(InstanceIdentifier.builder( PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build()); } - static void removeVpnExtraRouteForVpn(String vpnName, @Nonnull TypedWriteTransaction operTx) { + static void removeVpnExtraRouteForVpn(String vpnName, @NonNull TypedWriteTransaction operTx) { // Clean up VPNExtraRoutes Operational DS operTx.delete(InstanceIdentifier.builder(VpnToExtraroutes.class).child(Vpn.class, new VpnKey(vpnName)).build()); } @SuppressWarnings("checkstyle:IllegalCatch") - static void removeVpnOpInstance(String vpnName, @Nonnull TypedWriteTransaction operTx) { + static void removeVpnOpInstance(String vpnName, @NonNull TypedWriteTransaction operTx) { // Clean up VPNInstanceOpDataEntry operTx.delete(getVpnInstanceOpDataIdentifier(vpnName)); } - static void removeVpnInstanceToVpnId(String vpnName, @Nonnull TypedWriteTransaction confTx) { + static void removeVpnInstanceToVpnId(String vpnName, @NonNull TypedWriteTransaction confTx) { confTx.delete(VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnName)); } - static void removeVpnIdToVpnInstance(long vpnId, @Nonnull TypedWriteTransaction confTx) { + static void removeVpnIdToVpnInstance(Uint32 vpnId, @NonNull TypedWriteTransaction confTx) { confTx.delete(getVpnIdToVpnInstanceIdentifier(vpnId)); } - static void removeL3nexthopForVpnId(long vpnId, @Nonnull TypedWriteTransaction operTx) { + static void removeL3nexthopForVpnId(Uint32 vpnId, @NonNull TypedWriteTransaction operTx) { // Clean up L3NextHop Operational DS operTx.delete(InstanceIdentifier.builder(L3nexthop.class).child( VpnNexthops.class, new VpnNexthopsKey(vpnId)).build()); } - void scheduleVpnInterfaceForRemoval(String interfaceName, BigInteger dpnId, String vpnInstanceName, + void scheduleVpnInterfaceForRemoval(String interfaceName, Uint64 dpnId, String vpnInstanceName, @Nullable TypedWriteTransaction writeOperTxn) { InstanceIdentifier interfaceId = getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnInstanceName); @@ -934,8 +936,10 @@ public final class VpnUtil { public void createLearntVpnVipToPort(String vpnName, String fixedIp, String portName, String macAddress, TypedWriteTransaction writeOperTxn) { - synchronized ((vpnName + fixedIp).intern()) { - InstanceIdentifier id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp); + final InstanceIdentifier id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp); + final ReentrantLock lock = lockFor(vpnName, fixedIp); + lock.lock(); + try { LearntVpnVipToPortBuilder builder = new LearntVpnVipToPortBuilder().withKey(new LearntVpnVipToPortKey(fixedIp, vpnName)).setVpnName( vpnName).setPortFixedip(fixedIp).setPortName(portName) @@ -948,6 +952,8 @@ public final class VpnUtil { } LOG.debug("createLearntVpnVipToPort: ARP/NA learned for fixedIp: {}, vpn {}, interface {}, mac {}," + " added to LearntVpnVipToPort DS", fixedIp, vpnName, portName, macAddress); + } finally { + lock.unlock(); } } @@ -959,8 +965,10 @@ public final class VpnUtil { void removeLearntVpnVipToPort(String vpnName, String fixedIp, @Nullable TypedWriteTransaction writeOperTxn) { - synchronized ((vpnName + fixedIp).intern()) { - InstanceIdentifier id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp); + final InstanceIdentifier id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp); + final ReentrantLock lock = lockFor(vpnName, fixedIp); + lock.lock(); + try { if (writeOperTxn != null) { writeOperTxn.delete(id); } else { @@ -968,13 +976,17 @@ public final class VpnUtil { } LOG.debug("removeLearntVpnVipToPort: Deleted LearntVpnVipToPort entry for fixedIp: {}, vpn {}", fixedIp, vpnName); + } finally { + lock.unlock(); } } protected static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp, @Nullable TypedWriteTransaction writeConfigTxn) { - synchronized ((vpnName + fixedIp).intern()) { - InstanceIdentifier id = buildVpnPortipToPortIdentifier(vpnName, fixedIp); + final InstanceIdentifier id = buildVpnPortipToPortIdentifier(vpnName, fixedIp); + final ReentrantLock lock = lockFor(vpnName, fixedIp); + lock.lock(); + try { if (writeConfigTxn != null) { writeConfigTxn.delete(id); } else { @@ -982,6 +994,8 @@ public final class VpnUtil { } LOG.debug("removeVpnPortFixedIpToPort: Deleted VpnPortipToPort entry for fixedIp: {}, vpn {}", fixedIp, vpnName); + } finally { + lock.unlock(); } } @@ -1022,12 +1036,12 @@ public final class VpnUtil { } + // TODO Clean up the exception handling + @SuppressWarnings("checkstyle:IllegalCatch") public void removeMipAdjAndLearntIp(String vpnName, String vpnInterface, String prefix) { - synchronized ((vpnName + prefix).intern()) { - InstanceIdentifier id = buildLearntVpnVipToPortIdentifier(vpnName, prefix); - MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id); - LOG.info("removeMipAdjAndLearntIp: Delete learned ARP for fixedIp: {}, vpn {} removed from" - + "VpnPortipToPort DS", prefix, vpnName); + final ReentrantLock lock = lockFor(vpnName, prefix); + lock.lock(); + try { String ip = VpnUtil.getIpPrefix(prefix); InstanceIdentifier vpnInterfaceOpId = VpnUtil .getVpnInterfaceOpDataEntryIdentifier(vpnInterface, vpnName); @@ -1035,13 +1049,23 @@ public final class VpnUtil { Optional adjacenciesOp = read(LogicalDatastoreType.OPERATIONAL, path); if (adjacenciesOp.isPresent()) { InstanceIdentifier adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class) - .child(VpnInterface.class, new VpnInterfaceKey(vpnInterface)).augmentation(Adjacencies.class) - .child(Adjacency.class, new AdjacencyKey(ip)).build(); + .child(VpnInterface.class, new VpnInterfaceKey(vpnInterface)) + .augmentation(Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ip)).build(); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier); LOG.info("removeMipAdjAndLearntIp: Successfully Deleted Adjacency {} from interface {} vpn {}", ip, - vpnInterface, vpnName); + vpnInterface, vpnName); } + InstanceIdentifier id = buildLearntVpnVipToPortIdentifier(vpnName, prefix); + MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id); + LOG.info("removeMipAdjAndLearntIp: Delete learned ARP for fixedIp: {}, vpn {} removed from" + + "VpnPortipToPort DS", prefix, vpnName); + } catch (Exception e) { + LOG.error("removeMipAdjAndLearntIp: Exception Deleting learned Ip: {} interface {} vpn {} from " + + "LearntVpnPortipToPort DS", prefix, vpnInterface, vpnName, e); + } finally { + lock.unlock(); } + VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, prefix, null); } public void removeMipAdjacency(String vpnInterface, String ipAddress) { @@ -1104,9 +1128,9 @@ public final class VpnUtil { return null; } - @Nonnull - List getDpnsOnVpn(String vpnInstanceName) { - List result = new ArrayList<>(); + @NonNull + List getDpnsOnVpn(String vpnInstanceName) { + List result = new ArrayList<>(); String rd = getVpnRd(vpnInstanceName); if (rd == null) { LOG.debug("getDpnsOnVpn: Could not find Route-Distinguisher for VpnName={}", vpnInstanceName); @@ -1146,9 +1170,8 @@ public final class VpnUtil { String routerName = null; - for (Routers routerData : requireNonNullElse(extRouterData.get().getRouters(), - Collections.emptyList())) { - List externalIps = requireNonNullElse(routerData.getExternalIps(), emptyList()); + for (Routers routerData : extRouterData.get().nonnullRouters()) { + List externalIps = routerData.nonnullExternalIps(); for (ExternalIps externalIp : externalIps) { if (Objects.equals(externalIp.getIpAddress(), extIp)) { routerName = routerData.getRouterName(); @@ -1161,9 +1184,8 @@ public final class VpnUtil { return routerName; } - for (Routers routerData : requireNonNullElse(extRouterData.get().getRouters(), - Collections.emptyList())) { - List externalIps = requireNonNullElse(routerData.getExternalIps(), emptyList()); + for (Routers routerData : extRouterData.get().nonnullRouters()) { + List externalIps = routerData.nonnullExternalIps(); for (ExternalIps externalIp : externalIps) { Subnet neutronSubnet = neutronVpnService.getNeutronSubnet(externalIp.getSubnetId()); if (neutronSubnet == null) { @@ -1181,6 +1203,34 @@ public final class VpnUtil { return routerName; } + @Nullable + public String getAssociatedExternalSubnet(String extIp) { + InstanceIdentifier extRouterInstanceIndentifier = + InstanceIdentifier.builder(ExtRouters.class).build(); + Optional extRouterData = read(LogicalDatastoreType.CONFIGURATION, extRouterInstanceIndentifier); + if (!extRouterData.isPresent() || extRouterData.get().getRouters() == null) { + return null; + } + for (Routers routerData : extRouterData.get().getRouters()) { + List externalIps = routerData.getExternalIps(); + if (externalIps != null) { + for (ExternalIps externalIp : externalIps) { + Subnet neutronSubnet = neutronVpnService.getNeutronSubnet(externalIp.getSubnetId()); + if (neutronSubnet == null) { + LOG.warn("Failed to retrieve subnet {} referenced by router {}", + externalIp.getSubnetId(), routerData); + continue; + } + if (NWUtil.isIpAddressInRange(IpAddressBuilder.getDefaultInstance(extIp), + neutronSubnet.getCidr())) { + return neutronSubnet.getUuid().getValue(); + } + } + } + } + return null; + } + static InstanceIdentifier buildRouterIdentifier(String routerId) { return InstanceIdentifier.builder(ExtRouters.class).child(Routers.class, new RoutersKey(routerId)).build(); } @@ -1199,7 +1249,7 @@ public final class VpnUtil { return extNetwork != null ? extNetwork.getVpnid() : null; } - @Nonnull + @NonNull public List getExternalNetworkRouterIds(Uuid networkId) { Networks extNetwork = getExternalNetwork(networkId); return extNetwork != null && extNetwork.getRouterIds() != null ? extNetwork.getRouterIds() : emptyList(); @@ -1225,15 +1275,16 @@ public final class VpnUtil { return InstanceIdentifier.create(Subnetmaps.class); } - FlowEntity buildL3vpnGatewayFlow(BigInteger dpId, String gwMacAddress, long vpnId, - long subnetVpnId) { + FlowEntity buildL3vpnGatewayFlow(Uint64 dpId, String gwMacAddress, Uint32 vpnId, + Uint32 subnetVpnId) { List mkMatches = new ArrayList<>(); Subnetmap smap = null; - mkMatches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID)); + mkMatches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()), + MetaDataUtil.METADATA_MASK_VRFID)); mkMatches.add(new MatchEthernetDestination(new MacAddress(gwMacAddress))); List mkInstructions = new ArrayList<>(); mkInstructions.add(new InstructionGotoTable(NwConstants.L3_FIB_TABLE)); - if (subnetVpnId != VpnConstants.INVALID_ID) { + if (!VpnConstants.INVALID_ID.equals(subnetVpnId)) { String vpnName = getVpnName(subnetVpnId); if (vpnName != null) { smap = getSubnetmapFromItsUuid(Uuid.getDefaultInstance(vpnName)); @@ -1246,16 +1297,17 @@ public final class VpnUtil { } } } - BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(subnetVpnId); + Uint64 subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(subnetVpnId.longValue()); mkInstructions.add(new InstructionWriteMetadata(subnetIdMetaData, MetaDataUtil.METADATA_MASK_VRFID)); } String flowId = getL3VpnGatewayFlowRef(NwConstants.L3_GW_MAC_TABLE, dpId, vpnId, gwMacAddress, subnetVpnId); return MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_GW_MAC_TABLE, - flowId, 20, flowId, 0, 0, NwConstants.COOKIE_L3_GW_MAC_TABLE, mkMatches, mkInstructions); + flowId, 20, flowId, 0, 0, NwConstants.COOKIE_L3_GW_MAC_TABLE, + mkMatches, mkInstructions); } - static String getL3VpnGatewayFlowRef(short l3GwMacTable, BigInteger dpId, long vpnId, String gwMacAddress, - long subnetVpnId) { + static String getL3VpnGatewayFlowRef(short l3GwMacTable, Uint64 dpId, Uint32 vpnId, String gwMacAddress, + Uint32 subnetVpnId) { return gwMacAddress + NwConstants.FLOWID_SEPARATOR + vpnId + NwConstants.FLOWID_SEPARATOR + dpId + NwConstants.FLOWID_SEPARATOR + l3GwMacTable + NwConstants.FLOWID_SEPARATOR + subnetVpnId; } @@ -1318,13 +1370,13 @@ public final class VpnUtil { } private boolean doesInterfaceAndHiddenIpAddressTypeMatch(InetAddress hiddenIp, FixedIps portIp) { - return (hiddenIp instanceof Inet4Address && portIp.getIpAddress().getIpv4Address() != null) + return hiddenIp instanceof Inet4Address && portIp.getIpAddress().getIpv4Address() != null || hiddenIp instanceof Inet6Address && portIp.getIpAddress().getIpv6Address() != null; } public Optional getGWMacAddressFromInterface(MacEntry macEntry, IpAddress gatewayIp) { Optional gatewayMac = Optional.absent(); - long vpnId = getVpnId(macEntry.getVpnName()); + Uint32 vpnId = getVpnId(macEntry.getVpnName()); InstanceIdentifier vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId); @@ -1348,7 +1400,7 @@ public final class VpnUtil { return gatewayMac; } - void setupGwMacIfExternalVpn(BigInteger dpnId, String interfaceName, long vpnId, + void setupGwMacIfExternalVpn(Uint64 dpnId, String interfaceName, Uint32 vpnId, TypedReadWriteTransaction writeInvTxn, int addOrRemove, String gwMac) throws ExecutionException, InterruptedException { InstanceIdentifier allocateRdForExtraRouteAndUpdateUsedRdsMap(long vpnId, @Nullable Long parentVpnId, + java.util.Optional allocateRdForExtraRouteAndUpdateUsedRdsMap(Uint32 vpnId, @Nullable Uint32 parentVpnId, String prefix, String vpnName, - String nextHop, BigInteger dpnId) { + String nextHop, Uint64 dpnId) { //Check if rd is already allocated for this extraroute behind the same VM. If yes, reuse it. //This is particularly useful during reboot scenarios. java.util.Optional allocatedRd = VpnExtraRouteHelper @@ -1528,11 +1580,14 @@ public final class VpnUtil { .augmentation(Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build(); } - static InstanceIdentifier getVpnInterfaceOpDataEntryAdjacencyIdentifier(String intfName, String vpnName, - String ipAddress) { + static InstanceIdentifier getVpnInterfaceOpDataEntryAdjacencyIdentifier(String intfName, + String vpnName, + String ipAddress) { + LOG.debug("getVpnInterfaceO pDataEntryAdjacencyIdentifier intfName {}, vpnName {}, ipAddress {}", + intfName, vpnName, ipAddress); return InstanceIdentifier.builder(VpnInterfaceOpData.class) - .child(VpnInterfaceOpDataEntry.class, new VpnInterfaceOpDataEntryKey(intfName, vpnName)) - .augmentation(AdjacenciesOp.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build(); + .child(VpnInterfaceOpDataEntry.class, new VpnInterfaceOpDataEntryKey(intfName, vpnName)) + .augmentation(AdjacenciesOp.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build(); } public static List getIpsListFromExternalIps(List externalIps) { @@ -1560,12 +1615,13 @@ public final class VpnUtil { BoundServices getBoundServicesForVpnInterface(String vpnName, String interfaceName) { List instructions = new ArrayList<>(); int instructionKey = 0; - final long vpnId = getVpnId(vpnName); + final Uint32 vpnId = getVpnId(vpnName); List actions = Collections.singletonList( - new ActionRegLoad(0, VpnConstants.VPN_REG_ID, 0, VpnConstants.VPN_ID_LENGTH, vpnId).buildAction()); + new ActionRegLoad(0, VpnConstants.VPN_REG_ID, 0, VpnConstants.VPN_ID_LENGTH, vpnId.longValue()) + .buildAction()); instructions.add(MDSALUtil.buildApplyActionsInstruction(actions, ++instructionKey)); instructions.add( - MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId), + MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey)); instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_GW_MAC_TABLE, ++instructionKey)); @@ -1601,7 +1657,7 @@ public final class VpnUtil { } } - static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) { + static FlowEntity buildFlowEntity(Uint64 dpnId, short tableId, String flowId) { return new FlowEntityBuilder().setDpnId(dpnId).setTableId(tableId).setFlowId(flowId).build(); } @@ -1609,8 +1665,7 @@ public final class VpnUtil { return isVxLan ? VrfEntryBase.EncapType.Vxlan : VrfEntryBase.EncapType.Mplsgre; } - @Nullable - org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets + org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.@Nullable Subnets getExternalSubnet(Uuid subnetId) { InstanceIdentifier subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class) @@ -1653,7 +1708,7 @@ public final class VpnUtil { return read(LogicalDatastoreType.CONFIGURATION, inst).orNull(); } - public static boolean isEligibleForBgp(@Nullable String rd, @Nullable String vpnName, @Nullable BigInteger dpnId, + public static boolean isEligibleForBgp(@Nullable String rd, @Nullable String vpnName, @Nullable Uint64 dpnId, @Nullable String networkName) { if (rd != null) { if (rd.equals(vpnName)) { @@ -1670,14 +1725,14 @@ public final class VpnUtil { return false; } - static String getFibFlowRef(BigInteger dpnId, short tableId, String vpnName, int priority) { + static String getFibFlowRef(Uint64 dpnId, short tableId, String vpnName, int priority) { return VpnConstants.FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + vpnName + NwConstants.FLOWID_SEPARATOR + priority; } void removeExternalTunnelDemuxFlows(String vpnName) { LOG.info("Removing external tunnel flows for vpn {}", vpnName); - for (BigInteger dpnId: NWUtil.getOperativeDPNs(dataBroker)) { + for (Uint64 dpnId: NWUtil.getOperativeDPNs(dataBroker)) { LOG.debug("Removing external tunnel flows for vpn {} from dpn {}", vpnName, dpnId); String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY); @@ -1734,12 +1789,12 @@ public final class VpnUtil { List rts = new ArrayList<>(); VpnTargets targets = vpnInstance.getVpnTargets(); if (targets == null) { - LOG.info("getRts: vpn targets not available for {}", name); + LOG.debug("getRts: vpn targets not available for {}", name); return rts; } List vpnTargets = targets.getVpnTarget(); if (vpnTargets == null) { - LOG.info("getRts: vpnTarget values not available for {}", name); + LOG.debug("getRts: vpnTarget values not available for {}", name); return rts; } for (VpnTarget target : vpnTargets) { @@ -1868,7 +1923,7 @@ public final class VpnUtil { * @param vpnName the vpnName * @param dpnId the DPN id */ - void addRouterPortToElanForVlanInDpn(String vpnName, BigInteger dpnId) { + void addRouterPortToElanForVlanInDpn(String vpnName, Uint64 dpnId) { Map elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName); for (Entry elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) { addRouterPortToElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(), dpnId); @@ -1882,7 +1937,7 @@ public final class VpnUtil { * @param vpnName the vpn name * @param dpnId the DPN id */ - void removeRouterPortFromElanForVlanInDpn(String vpnName, BigInteger dpnId) { + void removeRouterPortFromElanForVlanInDpn(String vpnName, Uint64 dpnId) { Map elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName); for (Entry elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) { removeRouterPortFromElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(), @@ -1898,8 +1953,8 @@ public final class VpnUtil { */ void addRouterPortToElanDpnListForVlaninAllDpn(String vpnName) { Map elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName); - Set dpnList = getDpnInElan(elanInstanceRouterPortMap); - for (BigInteger dpnId : dpnList) { + Set dpnList = getDpnInElan(elanInstanceRouterPortMap); + for (Uint64 dpnId : dpnList) { for (Entry elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) { addRouterPortToElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(), dpnId); } @@ -1917,8 +1972,8 @@ public final class VpnUtil { String routerInterfacePortId, String vpnName) { Map elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName); elanInstanceRouterPortMap.put(elanInstanceName, routerInterfacePortId); - Set dpnList = getDpnInElan(elanInstanceRouterPortMap); - for (BigInteger dpnId : dpnList) { + Set dpnList = getDpnInElan(elanInstanceRouterPortMap); + for (Uint64 dpnId : dpnList) { for (Entry elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) { removeRouterPortFromElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(), vpnName, dpnId); @@ -1927,16 +1982,15 @@ public final class VpnUtil { } - Set getDpnInElan(Map elanInstanceRouterPortMap) { - Set dpnIdSet = new HashSet<>(); + Set getDpnInElan(Map elanInstanceRouterPortMap) { + Set dpnIdSet = new HashSet<>(); for (String elanInstanceName : elanInstanceRouterPortMap.keySet()) { InstanceIdentifier elanDpnInterfaceId = getElanDpnOperationalDataPath( elanInstanceName); Optional dpnInElanInterfaces = read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId); if (dpnInElanInterfaces.isPresent()) { - List dpnInterfaces = - requireNonNullElse(dpnInElanInterfaces.get().getDpnInterfaces(), emptyList()); + List dpnInterfaces = dpnInElanInterfaces.get().nonnullDpnInterfaces(); for (DpnInterfaces dpnInterface : dpnInterfaces) { dpnIdSet.add(dpnInterface.getDpId()); } @@ -1945,18 +1999,21 @@ public final class VpnUtil { return dpnIdSet; } - void addRouterPortToElanDpn(String elanInstanceName, String routerInterfacePortId, BigInteger dpnId) { + void addRouterPortToElanDpn(String elanInstanceName, String routerInterfacePortId, Uint64 dpnId) { InstanceIdentifier elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath( elanInstanceName,dpnId); - synchronized (elanInstanceName.intern()) { + final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanInstanceName); + lock.lock(); + try { Optional dpnInElanInterfaces = read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId); - List elanInterfaceList; + List elanInterfaceList = new ArrayList<>(); DpnInterfaces dpnInterface; if (!dpnInElanInterfaces.isPresent()) { elanInterfaceList = new ArrayList<>(); } else { dpnInterface = dpnInElanInterfaces.get(); - elanInterfaceList = dpnInterface.getInterfaces(); + elanInterfaceList = (dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) + ? new ArrayList<>(dpnInterface.getInterfaces()) : elanInterfaceList; } if (!elanInterfaceList.contains(routerInterfacePortId)) { elanInterfaceList.add(routerInterfacePortId); @@ -1964,24 +2021,28 @@ public final class VpnUtil { .withKey(new DpnInterfacesKey(dpnId)).build(); syncWrite(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId, dpnInterface); } + } finally { + lock.unlock(); } - } void removeRouterPortFromElanDpn(String elanInstanceName, String routerInterfacePortId, - String vpnName, BigInteger dpnId) { + String vpnName, Uint64 dpnId) { InstanceIdentifier elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath( elanInstanceName,dpnId); - synchronized (elanInstanceName.intern()) { + final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanInstanceName); + lock.lock(); + try { Optional dpnInElanInterfaces = read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId); - List elanInterfaceList; + List elanInterfaceList = new ArrayList<>(); DpnInterfaces dpnInterface; if (!dpnInElanInterfaces.isPresent()) { LOG.info("No interface in any dpn for {}", vpnName); return; } else { dpnInterface = dpnInElanInterfaces.get(); - elanInterfaceList = dpnInterface.getInterfaces(); + elanInterfaceList = (dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) + ? new ArrayList<>(dpnInterface.getInterfaces()) : elanInterfaceList; } if (!elanInterfaceList.contains(routerInterfacePortId)) { LOG.info("Router port not present in DPN {} for VPN {}", dpnId, vpnName); @@ -1991,6 +2052,8 @@ public final class VpnUtil { dpnInterface = new DpnInterfacesBuilder().setDpId(dpnId).setInterfaces(elanInterfaceList) .withKey(new DpnInterfacesKey(dpnId)).build(); syncWrite(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId, dpnInterface); + } finally { + lock.unlock(); } } @@ -2007,14 +2070,14 @@ public final class VpnUtil { } @Nullable - DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) { + DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, Uint64 dpId) { InstanceIdentifier elanDpnInterfacesId = getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId); return read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId).orNull(); } @Nullable - String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) { + String getExternalElanInterface(String elanInstanceName, Uint64 dpnId) { DpnInterfaces dpnInterfaces = getElanInterfaceInfoByElanDpn(elanInstanceName, dpnId); if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null) { LOG.info("Elan {} does not have interfaces in DPN {}", elanInstanceName, dpnId); @@ -2032,7 +2095,7 @@ public final class VpnUtil { static boolean isVlan(ElanInstance elanInstance) { return elanInstance != null && elanInstance.getSegmentType() != null && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeVlan.class) - && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId() != 0; + && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId().toJava() != 0; } boolean isVlan(String interfaceName) { @@ -2073,7 +2136,11 @@ public final class VpnUtil { Map elanInstanceRouterPortMap = new HashMap<>(); Optional subnetMapsData = read(LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath()); if (subnetMapsData.isPresent()) { - List subnetMapList = subnetMapsData.get().getSubnetmap(); + List subnetMapList = new ArrayList<>(); + Subnetmaps subnetMaps = subnetMapsData.get(); + subnetMapList = (subnetMaps.getSubnetmap() != null && !subnetMaps.getSubnetmap().isEmpty()) + ? new ArrayList<>(subnetMaps.getSubnetmap()) : subnetMapList; + if (subnetMapList != null && !subnetMapList.isEmpty()) { for (Subnetmap subnet : subnetMapList) { if (subnet.getVpnId() != null && subnet.getVpnId().getValue().equals(vpnName) @@ -2111,7 +2178,7 @@ public final class VpnUtil { return null; } - boolean shouldPopulateFibForVlan(String vpnName, @Nullable String elanInstanceName, BigInteger dpnId) { + boolean shouldPopulateFibForVlan(String vpnName, @Nullable String elanInstanceName, Uint64 dpnId) { Map elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName); boolean shouldPopulateFibForVlan = false; if (!elanInstanceRouterPortMap.isEmpty()) { @@ -2133,7 +2200,7 @@ public final class VpnUtil { } public static InstanceIdentifier getElanDpnInterfaceOperationalDataPath(String elanInstanceName, - BigInteger dpId) { + Uint64 dpId) { return InstanceIdentifier.builder(ElanDpnInterfaces.class) .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)) .child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build(); @@ -2158,7 +2225,7 @@ public final class VpnUtil { } public static void sendNeighborSolicationToOfGroup(Ipv6NdUtilService ipv6NdUtilService, Ipv6Address srcIpv6Address, - MacAddress srcMac, Ipv6Address dstIpv6Address, Long ofGroupId, BigInteger dpId) { + MacAddress srcMac, Ipv6Address dstIpv6Address, Long ofGroupId, Uint64 dpId) { SendNeighborSolicitationToOfGroupInput input = new SendNeighborSolicitationToOfGroupInputBuilder() .setSourceIpv6(srcIpv6Address).setSourceLlAddress(srcMac).setTargetIpAddress(dstIpv6Address) .setOfGroupId(ofGroupId).setDpId(dpId).build(); @@ -2266,40 +2333,46 @@ public final class VpnUtil { Also the Subnet overlap in a VPN detection logic to be addressed for router-based-l3vpns. */ static boolean areSubnetsOverlapping(String cidr1, String cidr2) { - String[] ipaddressValues1 = cidr1.split("/"); - int address1 = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues1[0])); - int cidrPart1 = Integer.parseInt(ipaddressValues1[1]); - String[] ipaddressValues2 = cidr2.split("/"); - int address2 = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues2[0])); - int cidrPart2 = Integer.parseInt(ipaddressValues2[1]); - int comparedValue = 0; + final int slash1 = cidr1.indexOf('/'); + final int address1 = addressForCidr(cidr1, slash1); + final int cidrPart1 = maskForCidr(cidr1, slash1); + + final int slash2 = cidr2.indexOf('/'); + final int address2 = addressForCidr(cidr2, slash2); + final int cidrPart2 = maskForCidr(cidr2, slash2); + + final int comparedValue = cidrPart1 <= cidrPart2 ? compare(address1, cidrPart1, address2) + : compare(address2, cidrPart2, address1); + return comparedValue == 0; + } + + private static int addressForCidr(String cidr, int slash) { + return InetAddresses.coerceToInteger(InetAddresses.forString(cidr.substring(0, slash))); + } + + private static int maskForCidr(String cidr, int slash) { + return Integer.parseInt(cidr.substring(slash + 1)); + } + + private static int compare(int address, int cidrPart, int address2) { + int prefix = address2 & computeNetmask(cidrPart); + return address ^ prefix; + } + + private static int computeNetmask(int cidrPart) { int netmask = 0; - if (cidrPart1 <= cidrPart2) { - for (int j = 0; j < cidrPart1; ++j) { - netmask |= (1 << 31 - j); - } - int prefix = address2 & netmask; - comparedValue = address1 ^ prefix; - } else { - for (int j = 0; j < cidrPart2; ++j) { - netmask |= (1 << 31 - j); - } - int prefix = address1 & netmask; - comparedValue = address2 ^ prefix; - } - if (comparedValue == 0) { - return true; - } else { - return false; + for (int j = 0; j < cidrPart; ++j) { + netmask |= 1 << 31 - j; } + return netmask; } public static String buildIpMonitorJobKey(String ip, String vpnName) { return VpnConstants.IP_MONITOR_JOB_PREFIX_KEY + "-" + vpnName + "-" + ip; } - public List getVpnListForVpnInterface(VpnInterface vpnInter) { - return requireNonNullElse(vpnInter.getVpnInstanceNames(), Collections.emptyList()).stream() + public static List getVpnListForVpnInterface(VpnInterface vpnInter) { + return vpnInter.nonnullVpnInstanceNames().stream() .map(VpnInstanceNames::getVpnName).collect(Collectors.toList()); } @@ -2325,9 +2398,72 @@ public final class VpnUtil { }); } - // Use Objects.requireNonNullElse instead with JDK9+ - @Nonnull - public static T requireNonNullElse(@Nullable T obj, @Nonnull T defaultObj) { - return obj != null ? obj : requireNonNull(defaultObj); + public static RouteOrigin getRouteOrigin(AdjacencyType adjacencyType) { + RouteOrigin origin = RouteOrigin.LOCAL; + switch (adjacencyType) { + case PrimaryAdjacency: + origin = RouteOrigin.LOCAL; + break; + case ExtraRoute: + origin = RouteOrigin.STATIC; + break; + case LearntIp: + origin = RouteOrigin.DYNAMIC; + break; + default: + LOG.warn("Unknown adjacencyType={}", adjacencyType); + } + return origin; + } + + public static boolean isDualRouterVpnUpdate(List oldVpnListCopy, List newVpnListCopy) { + return oldVpnListCopy.size() == 2 && newVpnListCopy.size() == 3 + || oldVpnListCopy.size() == 3 && newVpnListCopy.size() == 2; + } + + // TODO Clean up the exception handling + @SuppressWarnings("checkstyle:IllegalCatch") + public void createVpnPortFixedIpToPort(String vpnName, String fixedIp, + String portName, boolean isLearntIp, String macAddress, + WriteTransaction writeConfigTxn) { + InstanceIdentifier id = buildVpnPortipToPortIdentifier(vpnName, fixedIp); + VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder().withKey(new VpnPortipToPortKey(fixedIp, vpnName)) + .setVpnName(vpnName).setPortFixedip(fixedIp).setPortName(portName) + .setLearntIp(isLearntIp).setSubnetIp(false).setMacAddress(macAddress.toLowerCase(Locale.getDefault())); + try { + if (writeConfigTxn != null) { + writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, id, builder.build()); + } else { + syncWrite(LogicalDatastoreType.CONFIGURATION, id, builder.build()); + } + LOG.trace("Port with Ip: {}, vpn {}, interface {}, learntIp {} added to VpnPortipToPort DS", + fixedIp, vpnName, portName, isLearntIp); + } catch (Exception e) { + LOG.error("Failure while creating VpnPortIpToPort map for vpn {} learnIp{}", vpnName, fixedIp, e); + } + } + + protected VpnPortipToPort getVpnPortipToPort(String vpnName, String fixedIp) { + InstanceIdentifier id = buildVpnPortipToPortIdentifier(vpnName, fixedIp); + Optional vpnPortipToPortData = read(LogicalDatastoreType.CONFIGURATION, id); + if (vpnPortipToPortData.isPresent()) { + return vpnPortipToPortData.get(); + } + LOG.error("getVpnPortipToPort: Failed as vpnPortipToPortData DS is absent for VPN {} and fixed IP {}", + vpnName, fixedIp); + return null; + } + + public static void enableArpLearning(Boolean isArpLearningEnabled) { + arpLearningEnabled = isArpLearningEnabled; + } + + public static Boolean isArpLearningEnabled() { + return arpLearningEnabled; + } + + private static ReentrantLock lockFor(String vpnName, String fixedIp) { + // FIXME: is there some identifier we can use? LearntVpnVipToPortKey perhaps? + return JvmGlobalLocks.getLockForString(vpnName + fixedIp); } }