/*
- * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2016, 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,
package org.opendaylight.netvirt.neutronvpn;
+import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
+import static org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils.requireNonNullElse;
+
+import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.SettableFuture;
+
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
+
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+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.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.infra.Datastore;
import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.utils.JvmGlobalLocks;
import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIdsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.ext.rev150712.NetworkL3Extension;
private final IdManagerService idManager;
private final JobCoordinator jobCoordinator;
private final IPV6InternetDefaultRouteProgrammer ipV6InternetDefRt;
+ private static final int JOB_MAX_RETRIES = 3;
@Inject
public NeutronvpnUtils(final DataBroker dataBroker, final IdManagerService idManager,
this.ipV6InternetDefRt = ipV6InternetDefRt;
}
+ @Nullable
protected Subnetmap getSubnetmap(Uuid subnetId) {
InstanceIdentifier<Subnetmap> id = buildSubnetMapIdentifier(subnetId);
Optional<Subnetmap> sn = read(LogicalDatastoreType.CONFIGURATION, id);
return null;
}
+ @Nullable
public VpnMap getVpnMap(Uuid id) {
InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap.class,
new VpnMapKey(id)).build();
return null;
}
+ @Nullable
protected Uuid getVpnForNetwork(Uuid network) {
InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
Optional<VpnMaps> optionalVpnMaps = read(LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
- List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
- for (VpnMap vpnMap : allMaps) {
+ for (VpnMap vpnMap : requireNonNullElse(optionalVpnMaps.get().getVpnMap(),
+ Collections.<VpnMap>emptyList())) {
List<Uuid> netIds = vpnMap.getNetworkIds();
if (netIds != null && netIds.contains(network)) {
return vpnMap.getVpnId();
return null;
}
+ @Nullable
protected Uuid getVpnForSubnet(Uuid subnetId) {
InstanceIdentifier<Subnetmap> subnetmapIdentifier = buildSubnetMapIdentifier(subnetId);
Optional<Subnetmap> optionalSubnetMap = read(LogicalDatastoreType.CONFIGURATION,
return null;
}
+ @Nullable
protected Uuid getNetworkForSubnet(Uuid subnetId) {
InstanceIdentifier<Subnetmap> subnetmapIdentifier = buildSubnetMapIdentifier(subnetId);
Optional<Subnetmap> optionalSubnetMap = read(LogicalDatastoreType.CONFIGURATION,
}
// @param external vpn - true if external vpn being fetched, false for internal vpn
- protected Uuid getVpnForRouter(Uuid routerId, Boolean externalVpn) {
+ @Nullable
+ protected Uuid getVpnForRouter(@Nullable Uuid routerId, boolean externalVpn) {
if (routerId == null) {
return null;
}
InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
Optional<VpnMaps> optionalVpnMaps = read(LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
- List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
- for (VpnMap vpnMap : allMaps) {
- if (routerId.equals(vpnMap.getRouterId())) {
+ for (VpnMap vpnMap : requireNonNullElse(optionalVpnMaps.get().getVpnMap(),
+ Collections.<VpnMap>emptyList())) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap
+ .RouterIds> routerIdsList = vpnMap.getRouterIds();
+ if (routerIdsList == null || routerIdsList.isEmpty()) {
+ continue;
+ }
+ // Skip router vpnId fetching from internet BGP-VPN
+ if (vpnMap.getNetworkIds() != null && !vpnMap.getNetworkIds().isEmpty()) {
+ // We only need to check the first network; if it’s not an external network there’s no
+ // need to check the rest of the VPN’s network list
+ if (getIsExternal(getNeutronNetwork(vpnMap.getNetworkIds().iterator().next()))) {
+ continue;
+ }
+ }
+ // FIXME: NETVIRT-1503: this check can be replaced by a ReadOnlyTransaction.exists()
+ if (routerIdsList.stream().anyMatch(routerIds -> routerId.equals(routerIds.getRouterId()))) {
if (externalVpn) {
if (!routerId.equals(vpnMap.getVpnId())) {
return vpnMap.getVpnId();
return null;
}
- protected Uuid getRouterforVpn(Uuid vpnId) {
+ @Nullable
+ protected List<Uuid> getRouterIdListforVpn(Uuid vpnId) {
InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap.class,
new VpnMapKey(vpnId)).build();
Optional<VpnMap> optionalVpnMap = read(LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
if (optionalVpnMap.isPresent()) {
VpnMap vpnMap = optionalVpnMap.get();
- return vpnMap.getRouterId();
+ return NeutronUtils.getVpnMapRouterIdsListUuid(vpnMap.getRouterIds());
}
- LOG.error("getRouterforVpn: Failed as VPNMaps DS is absent for VPN {}", vpnId.getValue());
+ LOG.error("getRouterIdListforVpn: Failed as VPNMaps DS is absent for VPN {}", vpnId.getValue());
return null;
}
+ @Nullable
protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap.class,
new VpnMapKey(vpnId)).build();
return subnets;
}
+ @Nullable
protected String getNeutronPortNameFromVpnPortFixedIp(String vpnName, String fixedIp) {
InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
Optional<VpnPortipToPort> vpnPortipToPortData = read(LogicalDatastoreType.CONFIGURATION, id);
return null;
}
+ @Nullable
protected List<Uuid> getSubnetIdsFromNetworkId(Uuid networkId) {
InstanceIdentifier<NetworkMap> id = buildNetworkMapIdentifier(networkId);
Optional<NetworkMap> optionalNetworkMap = read(LogicalDatastoreType.CONFIGURATION, id);
return null;
}
+ @Nullable
protected List<Uuid> getPortIdsFromSubnetId(Uuid subnetId) {
InstanceIdentifier<Subnetmap> id = buildSubnetMapIdentifier(subnetId);
Optional<Subnetmap> optionalSubnetmap = read(LogicalDatastoreType.CONFIGURATION, id);
* @param port2SecurityGroups the port 2 security groups
* @return the security groups delta
*/
- protected static List<Uuid> getSecurityGroupsDelta(List<Uuid> port1SecurityGroups,
- List<Uuid> port2SecurityGroups) {
+ @Nullable
+ protected static List<Uuid> getSecurityGroupsDelta(@Nullable List<Uuid> port1SecurityGroups,
+ @Nullable List<Uuid> port2SecurityGroups) {
if (port1SecurityGroups == null) {
return null;
}
* @param port2AllowedAddressPairs the port 2 allowed address pairs
* @return the allowed address pairs delta
*/
+ @Nullable
protected static List<AllowedAddressPairs> getAllowedAddressPairsDelta(
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes
+ @Nullable List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes
.AllowedAddressPairs> port1AllowedAddressPairs,
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes
+ @Nullable List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes
.AllowedAddressPairs> port2AllowedAddressPairs) {
if (port1AllowedAddressPairs == null) {
return null;
org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddress ipAddress) {
AllowedAddressPairsBuilder aclAllowedAdressPairBuilder = new AllowedAddressPairsBuilder();
aclAllowedAdressPairBuilder.setMacAddress(macAddress);
- if (ipAddress != null && ipAddress.getValue() != null) {
+ if (ipAddress != null && ipAddress.stringValue() != null) {
if (ipAddress.getIpPrefix() != null) {
aclAllowedAdressPairBuilder.setIpAddress(new IpPrefixOrAddress(ipAddress.getIpPrefix()));
} else {
List<AllowedAddressPairs> aclAllowedAddressPairs = new ArrayList<>();
for (FixedIps fixedIp : fixedIps) {
aclAllowedAddressPairs.add(getAclAllowedAddressPairs(macAddress,
- new org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddress(
- fixedIp.getIpAddress().getValue())));
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddressBuilder
+ .getDefaultInstance(fixedIp.getIpAddress().stringValue())));
}
return aclAllowedAddressPairs;
}
protected static AllowedAddressPairs updateIPv6LinkLocalAddressForAclService(MacAddress macAddress) {
IpAddress ipv6LinkLocalAddress = getIpv6LinkLocalAddressFromMac(macAddress);
return getAclAllowedAddressPairs(macAddress,
- new org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddress(
- ipv6LinkLocalAddress.getValue()));
+ org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.types.rev160517.IpPrefixOrAddressBuilder
+ .getDefaultInstance(
+ ipv6LinkLocalAddress.stringValue()));
}
/**
}
}
+ @Nullable
protected List<SubnetInfo> getSubnetInfo(Port port) {
List<FixedIps> portFixedIps = port.getFixedIps();
if (portFixedIps == null) {
if (sn.isPresent()) {
subnet = sn.get();
+ addToSubnetCache(subnet);
}
return subnet;
}
+ protected List<Subnetmap> getNeutronRouterSubnetMapList(Uuid routerId) {
+ List<Subnetmap> subnetMapList = new ArrayList<>();
+ Optional<Subnetmaps> subnetMaps = read(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(Subnetmaps.class).build());
+ if (subnetMaps.isPresent() && subnetMaps.get().getSubnetmap() != null) {
+ for (Subnetmap subnetmap : subnetMaps.get().getSubnetmap()) {
+ if (routerId.equals(subnetmap.getRouterId())) {
+ subnetMapList.add(subnetmap);
+ }
+ }
+ }
+ LOG.debug("getNeutronRouterSubnetMapList returns {}", subnetMapList);
+ return subnetMapList;
+ }
+
@Nonnull
protected List<Uuid> getNeutronRouterSubnetIds(Uuid routerId) {
LOG.debug("getNeutronRouterSubnetIds for {}", routerId.getValue());
// TODO Clean up the exception handling and the console output
@SuppressWarnings({"checkstyle:IllegalCatch", "checkstyle:RegexpSinglelineJava"})
+ @Nullable
protected Short getIPPrefixFromPort(Port port) {
try {
Uuid subnetUUID = port.getFixedIps().get(0).getSubnetId();
.class).child(Subnet.class, subnetkey);
Optional<Subnet> subnet = read(LogicalDatastoreType.CONFIGURATION, subnetidentifier);
if (subnet.isPresent()) {
- String cidr = String.valueOf(subnet.get().getCidr().getValue());
+ String cidr = subnet.get().getCidr().stringValue();
// Extract the prefix length from cidr
String[] parts = cidr.split("/");
if (parts.length == 2) {
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
protected void createVpnPortFixedIpToPort(String vpnName, String fixedIp, String portName, String macAddress,
- boolean isSubnetIp, WriteTransaction writeConfigTxn) {
+ boolean isSubnetIp, TypedWriteTransaction<Datastore.Configuration> writeConfigTxn) {
InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier(vpnName, fixedIp);
VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder()
.withKey(new VpnPortipToPortKey(fixedIp, vpnName))
.setPortName(portName).setMacAddress(macAddress).setSubnetIp(isSubnetIp);
try {
if (writeConfigTxn != null) {
- writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, id, builder.build());
+ writeConfigTxn.put(id, builder.build());
} else {
MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
}
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
- protected void removeVpnPortFixedIpToPort(String vpnName, String fixedIp, WriteTransaction writeConfigTxn) {
+ protected void removeVpnPortFixedIpToPort(String vpnName, String fixedIp,
+ TypedWriteTransaction<Datastore.Configuration> writeConfigTxn) {
InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier(vpnName, fixedIp);
try {
if (writeConfigTxn != null) {
- writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, id);
+ writeConfigTxn.delete(id);
} else {
MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
}
@SuppressWarnings("checkstyle:IllegalCatch")
protected void removeLearntVpnVipToPort(String vpnName, String fixedIp) {
InstanceIdentifier<LearntVpnVipToPort> id = NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
+ // FIXME: can we use 'id' as the lock name?
+ final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName + fixedIp);
+ lock.lock();
try {
- synchronized ((vpnName + fixedIp).intern()) {
- MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
- }
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
LOG.trace("Neutron router port with fixedIp: {}, vpn {} removed from LearntVpnPortipToPort DS", fixedIp,
vpnName);
} catch (Exception e) {
LOG.error("Failure while removing LearntVpnPortFixedIpToPort map for vpn {} - fixedIP {}",
vpnName, fixedIp, e);
+ } finally {
+ lock.unlock();
}
}
return providerExtension != null ? providerExtension.getNetworkType() : null;
}
+ @Nullable
static ProviderTypes getProviderNetworkType(Network network) {
if (network == null) {
LOG.error("Error in getting provider network type since network is null");
Optional<InterVpnLinks> interVpnLinksOpData = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
interVpnLinksIid);
if (interVpnLinksOpData.isPresent()) {
- List<InterVpnLink> allInterVpnLinks = interVpnLinksOpData.get().getInterVpnLink();
- for (InterVpnLink interVpnLink : allInterVpnLinks) {
+ for (InterVpnLink interVpnLink : requireNonNullElse(interVpnLinksOpData.get().getInterVpnLink(),
+ Collections.<InterVpnLink>emptyList())) {
if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
|| interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
return Optional.of(interVpnLink);
MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnId);
if (neutronRouterDpnsOpt.isPresent()) {
NeutronRouterDpns neutronRouterDpns = neutronRouterDpnsOpt.get();
- List<RouterDpnList> routerDpnLists = neutronRouterDpns.getRouterDpnList();
- for (RouterDpnList routerDpnList : routerDpnLists) {
+ for (RouterDpnList routerDpnList : requireNonNullElse(neutronRouterDpns.getRouterDpnList(),
+ Collections.<RouterDpnList>emptyList())) {
if (routerDpnList.getDpnVpninterfacesList() != null) {
for (DpnVpninterfacesList dpnInterfaceList : routerDpnList.getDpnVpninterfacesList()) {
if (dpnInterfaceList.getDpnId().equals(dpid)) {
return ret;
}
+ @Nullable
protected Integer getUniqueRDId(String poolName, String idKey) {
AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
try {
interfaceID.append(StringUtils.leftPad(Integer.toHexString(0xFF & octets[5]), 2, "0"));
Ipv6Address ipv6LLA = new Ipv6Address("fe80:0:0:0:" + interfaceID.toString());
- IpAddress ipAddress = new IpAddress(ipv6LLA.getValue().toCharArray());
+ IpAddress ipAddress = new IpAddress(ipv6LLA);
return ipAddress;
}
*
* @return the route-distinguisher of the VPN
*/
+ @Nullable
public String getVpnRd(String vpnName) {
InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
.instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
return IpVersionChoice.UNDEFINED;
}
+ @Nullable
public VpnInstanceOpDataEntry getVpnInstanceOpDataEntryFromVpnId(String vpnName) {
String primaryRd = getVpnRd(vpnName);
if (primaryRd == null) {
.child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(primaryRd)).build();
}
- public boolean shouldVpnHandleIpVersionChangeToAdd(Subnetmap sm, Uuid vpnId) {
- if (sm == null) {
- return false;
- }
- IpVersionChoice ipVersion = getIpVersionFromString(sm.getSubnetIp());
- return shouldVpnHandleIpVersionChoiceChangeToAdd(ipVersion, vpnId);
- }
-
- public boolean shouldVpnHandleIpVersionChoiceChangeToAdd(IpVersionChoice ipVersion, Uuid vpnId) {
- VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnId.getValue());
- if (vpnInstanceOpDataEntry == null) {
- return false;
- }
- if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
- LOG.error("shouldVpnHandleIpVersionChangeToAdd: {} "
- + "VpnInstanceOpDataEntry is L2 instance. Do nothing.", vpnId.getValue());
+ public boolean shouldVpnHandleIpVersionChoiceChange(IpVersionChoice ipVersion, Uuid routerId, boolean add) {
+ int subnetCount = -1;
+ if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
+ subnetCount = getSubnetCountFromRouter(routerId, ipVersion);
+ } else if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
+ subnetCount = getSubnetCountFromRouter(routerId, ipVersion);
+ } else {
+ //Possible value of ipversion choice is either V4 or V6 only. Not accepted V4andV6 and Undefined
return false;
}
- boolean isIpv4Configured = vpnInstanceOpDataEntry.isIpv4Configured();
- boolean isVpnInstanceIpv4Changed = false;
- if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4) && !isIpv4Configured) {
- isVpnInstanceIpv4Changed = true;
- }
- boolean isIpv6Configured = vpnInstanceOpDataEntry.isIpv6Configured();
- boolean isVpnInstanceIpv6Changed = false;
- if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV6) && !isIpv6Configured) {
- isVpnInstanceIpv6Changed = true;
- }
- if (!isVpnInstanceIpv4Changed && !isVpnInstanceIpv6Changed) {
- LOG.debug("shouldVpnHandleIpVersionChangeToAdd: VPN {} did not change with IpFamily {}",
- vpnId.getValue(), ipVersion.toString());
+ /* ADD: Update vpnInstanceOpDataEntry with address family only on first IPv4/IPv6 subnet
+ * for the VPN Instance.
+ *
+ * REMOVE: Update vpnInstanceOpDataEntry with address family only on last IPv4/IPv6 subnet
+ * for the VPN Instance.
+ */
+ if (add && subnetCount == 1) {
+ return true;
+ } else if (!add && subnetCount == 0) {
+ return true;
+ } else {
return false;
}
- return true;
}
public boolean shouldVpnHandleIpVersionChangeToRemove(Subnetmap sm, Uuid vpnId) {
Optional<Subnetmaps> allSubnetMaps = read(LogicalDatastoreType.CONFIGURATION, subnetMapsId);
// calculate and store in list IpVersion for each subnetMap, belonging to current VpnInstance
List<IpVersionChoice> snIpVersions = new ArrayList<>();
- for (Subnetmap snMap: allSubnetMaps.get().getSubnetmap()) {
+ for (Subnetmap snMap : requireNonNullElse(allSubnetMaps.get().getSubnetmap(),
+ Collections.<Subnetmap>emptyList())) {
if (snMap.getId().equals(sm.getId())) {
continue;
}
return false;
}
- public void updateVpnInstanceWithIpFamily(String vpnName, IpVersionChoice ipVersion, boolean add) {
- VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName);
- if (vpnInstanceOpDataEntry == null) {
- return;
- }
- if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
- LOG.debug("updateVpnInstanceWithIpFamily: Update VpnInstance {} with ipFamily {}."
- + "VpnInstanceOpDataEntry is L2 instance. Do nothing.", vpnName,
- ipVersion.toString());
- return;
+ public int getSubnetCountFromRouter(Uuid routerId, IpVersionChoice ipVer) {
+ List<Subnetmap> subnetMapList = getNeutronRouterSubnetMapList(routerId);
+ int subnetCount = 0;
+ for (Subnetmap subMap : subnetMapList) {
+ IpVersionChoice ipVersion = getIpVersionFromString(subMap.getSubnetIp());
+ if (ipVersion.isIpVersionChosen(ipVer)) {
+ subnetCount++;
+ }
+ if (subnetCount > 1) {
+ break;
+ }
}
- final boolean isFinalVpnInstanceIpv6Changed = ipVersion
- .isIpVersionChosen(IpVersionChoice.IPV6) ? true : false;
- final boolean isFinalVpnInstanceIpv4Changed = ipVersion
- .isIpVersionChosen(IpVersionChoice.IPV4) ? true : false;
- final boolean finalIsIpv4Configured = ipVersion.isIpVersionChosen(IpVersionChoice.IPV4) ? add : false;
- final boolean finalIsIpv6Configured = ipVersion.isIpVersionChosen(IpVersionChoice.IPV6) ? add : false;
+ return subnetCount;
+ }
+
+ public void updateVpnInstanceWithIpFamily(String vpnName, IpVersionChoice ipVersion, boolean add) {
jobCoordinator.enqueueJob("VPN-" + vpnName, () -> {
- VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder(vpnInstanceOpDataEntry);
- if (isFinalVpnInstanceIpv4Changed) {
- builder.setIpv4Configured(finalIsIpv4Configured);
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName);
+ if (vpnInstanceOpDataEntry == null) {
+ return Collections.emptyList();
+ }
+ if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
+ LOG.debug("updateVpnInstanceWithIpFamily: Update VpnInstance {} with ipFamily {}."
+ + "VpnInstanceOpDataEntry is L2 instance. Do nothing.", vpnName, ipVersion);
+ return Collections.emptyList();
}
- if (isFinalVpnInstanceIpv6Changed) {
- builder.setIpv6Configured(finalIsIpv6Configured);
+ if (ipVersion == IpVersionChoice.UNDEFINED) {
+ LOG.debug("updateVpnInstanceWithIpFamily: Update VpnInstance {} with Undefined address family"
+ + "is not allowed. Do nothing", vpnName);
+ return Collections.emptyList();
}
- return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
- InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
- .child(VpnInstanceOpDataEntry.class,
- new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
- tx.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
- LOG.info("updateVpnInstanceWithIpFamily: Successfully {} {} to Vpn {}",
- add ? "added" : "removed",
- ipVersion.toString(), vpnName);
- }));
+ VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder(vpnInstanceOpDataEntry);
+ boolean ipConfigured = add;
+ if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4AND6)) {
+ builder.setIpv4Configured(ipConfigured);
+ builder.setIpv6Configured(ipConfigured);
+ } else if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
+ builder.setIpv4Configured(ipConfigured);
+ } else if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV6)) {
+ builder.setIpv6Configured(ipConfigured);
+ }
+ return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+ OPERATIONAL, tx -> {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier
+ .builder(VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class,
+ new VpnInstanceOpDataEntryKey(vpnInstanceOpDataEntry.getVrfId())).build();
+ tx.merge(id, builder.build(), false);
+ LOG.info("updateVpnInstanceWithIpFamily: Successfully {} {} to Vpn {}",
+ add == true ? "added" : "removed", ipVersion, vpnName);
+ }));
});
}
* @param vpnId the Uuid of the VPN
* @return the VpnInstance or null if unfindable
*/
+ @Nullable
public VpnInstance getVpnInstance(DataBroker broker, Uuid vpnId) {
if (broker == null || vpnId == null) {
return null;
* @param subnetUuid Uuid of subnet where you are finding a link to an external network
* @return Uuid of externalVpn or null if it is not found
*/
+ @Nullable
public Uuid getInternetvpnUuidBoundToSubnetRouter(@Nonnull Uuid subnetUuid) {
Subnetmap subnetmap = getSubnetmap(subnetUuid);
Uuid routerUuid = subnetmap.getRouterId();
* @param extNet Provider Network, which has a port attached as external network gateway to router
* @return a list of Private Subnetmap Ids of the router with external network gateway
*/
- public @Nonnull List<Uuid> getPrivateSubnetsToExport(@Nonnull Network extNet) {
+ public @Nonnull List<Uuid> getPrivateSubnetsToExport(@Nonnull Network extNet, Uuid internetVpnId) {
List<Uuid> subList = new ArrayList<>();
- Uuid extNetVpnId = getVpnForNetwork(extNet.getUuid());
- if (extNetVpnId == null) {
- return subList;
+ List<Uuid> rtrList = new ArrayList<>();
+ if (internetVpnId != null) {
+ rtrList.addAll(getRouterIdListforVpn(internetVpnId));
+ } else {
+ Uuid extNwVpnId = getVpnForNetwork(extNet.getUuid());
+ rtrList.addAll(getRouterIdListforVpn(extNwVpnId));
}
- Router router = getNeutronRouter(getRouterforVpn(extNetVpnId));
- ExternalGatewayInfo info = router.getExternalGatewayInfo();
- if (info == null) {
- LOG.error("getPrivateSubnetsToExport: can not get info about external gateway for router {}",
- router.getUuid().getValue());
+ if (rtrList.isEmpty()) {
return subList;
}
- // check that router really has given provider network as its external gateway port
- if (!extNet.getUuid().equals(info.getExternalNetworkId())) {
- LOG.error("getPrivateSubnetsToExport: router {} is not attached to given provider network {}",
- router.getUuid().getValue(), extNet.getUuid().getValue());
- return subList;
+ for (Uuid rtrId: rtrList) {
+ Router router = getNeutronRouter(rtrId);
+ ExternalGatewayInfo info = router.getExternalGatewayInfo();
+ if (info == null) {
+ LOG.error("getPrivateSubnetsToExport: can not get info about external gateway for router {}",
+ router.getUuid().getValue());
+ continue;
+ }
+ // check that router really has given provider network as its external gateway port
+ if (!extNet.getUuid().equals(info.getExternalNetworkId())) {
+ LOG.error("getPrivateSubnetsToExport: router {} is not attached to given provider network {}",
+ router.getUuid().getValue(), extNet.getUuid().getValue());
+ continue;
+ }
+ subList.addAll(getNeutronRouterSubnetIds(rtrId));
}
- return getSubnetsforVpn(router.getUuid());
+ return subList;
}
- public void updateVpnInstanceWithFallback(String vpnName, boolean add) {
- VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName);
+ public void updateVpnInstanceWithFallback(Uuid routerId, Uuid vpnName, boolean add) {
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(vpnName.getValue());
if (vpnInstanceOpDataEntry == null) {
- // BGPVPN context not found
+ LOG.error("updateVpnInstanceWithFallback: vpnInstanceOpDataEntry not found for vpn {}", vpnName);
return;
}
- String routerIdUuid = getRouterIdfromVpnInstance(vpnInstanceOpDataEntry.getVrfId());
- if (routerIdUuid != null) {
- List<BigInteger> dpnIds = getDpnsForRouter(routerIdUuid);
- if (!dpnIds.isEmpty()) {
- Long vpnId = vpnInstanceOpDataEntry.getVpnId();
- VpnInstanceOpDataEntry vpnOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(routerIdUuid);
- Long routerIdAsLong = vpnOpDataEntry.getVpnId();
- if (routerIdAsLong == null) {
- return;
- }
- for (BigInteger dpnId : dpnIds) {
- if (add) {
- ipV6InternetDefRt.installDefaultRoute(dpnId, vpnId, routerIdAsLong);
- } else {
- ipV6InternetDefRt.removeDefaultRoute(dpnId, vpnId, routerIdAsLong);
- }
+ Long internetBgpVpnId = vpnInstanceOpDataEntry.getVpnId();
+ List<Uuid> routerIds = new ArrayList<>();
+ //Handle router specific V6 internet fallback flow else handle all V6 external routers
+ if (routerId != null) {
+ routerIds.add(routerId);
+ } else {
+ //This block will execute for ext-nw to Internet VPN association/disassociation event.
+ routerIds = getRouterIdListforVpn(vpnName);
+ }
+ if (routerIds == null || routerIds.isEmpty()) {
+ LOG.error("updateVpnInstanceWithFallback: router not found for vpn {}", vpnName);
+ return;
+ }
+ for (Uuid rtrId: routerIds) {
+ if (rtrId == null) {
+ continue;
+ }
+ List<BigInteger> dpnIds = getDpnsForRouter(rtrId.getValue());
+ if (dpnIds.isEmpty()) {
+ continue;
+ }
+ VpnInstanceOpDataEntry vpnOpDataEntry = getVpnInstanceOpDataEntryFromVpnId(rtrId.getValue());
+ Long routerIdAsLong = vpnOpDataEntry.getVpnId();
+ long vpnId;
+ Uuid rtrVpnId = getVpnForRouter(rtrId, true);
+ if (rtrVpnId == null) {
+ //If external BGP-VPN is not associated with router then routerId is same as routerVpnId
+ vpnId = routerIdAsLong;
+ } else {
+ vpnId = getVpnId(rtrVpnId.getValue());
+ }
+ for (BigInteger dpnId : dpnIds) {
+ if (add) {
+ ipV6InternetDefRt.installDefaultRoute(dpnId, rtrId.getValue(), internetBgpVpnId, vpnId);
+ } else {
+ ipV6InternetDefRt.removeDefaultRoute(dpnId, rtrId.getValue(), internetBgpVpnId, vpnId);
}
}
}
}
VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder(vpnInstanceOpDataEntry);
builder.setBgpvpnType(choice);
- ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
- tx.merge(LogicalDatastoreType.OPERATIONAL, id, builder.build(), false);
+ ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
+ tx.merge(id, builder.build(), false);
LOG.debug("updateVpnInstanceOpWithType: sent merge to operDS BgpvpnType {} for {}", choice, vpn.getValue());
}), LOG, "Error updating VPN instance op {} with type {}", vpn, choice);
}
+ public List<Uuid> getAssociateRouterInputRouterIdsListUuid(List<RouterIds> routerIds) {
+ if (routerIds == null) {
+ return Collections.emptyList();
+ }
+ return routerIds.stream().map(
+ routerId -> routerId.getRouterId()).collect(Collectors.toList());
+ }
+
+ public List<Uuid> getDisassociateRouterInputRouterIdsListUuid(List<RouterIds> routerIds) {
+ if (routerIds == null) {
+ return Collections.emptyList();
+ }
+ return routerIds.stream().map(
+ routerId -> routerId.getRouterId()).collect(Collectors.toList());
+ }
+
+ public RouterIds getvpnMapRouterIds(Uuid routerId) {
+ return new RouterIdsBuilder().setRouterId(routerId).build();
+ }
+
+ public void removeVpnMapRouterIdsFromList(Uuid routerId, List<RouterIds> vpnRouterIds) {
+ Iterator<RouterIds> vpnRouterIdIter = vpnRouterIds.iterator();
+ while (vpnRouterIdIter.hasNext()) {
+ RouterIds vpnRouterId = vpnRouterIdIter.next();
+ if (vpnRouterId.getRouterId().getValue().equals(routerId.getValue())) {
+ vpnRouterIdIter.remove();
+ return;
+ }
+ }
+ return;
+ }
+
+ public boolean vpnMapRouterIdsContainsRouterId(Uuid routerId, List<RouterIds> vpnRouterIds) {
+ if (routerId == null) {
+ return false;
+ }
+ return vpnRouterIds.stream().anyMatch(vpnRouterId ->
+ vpnRouterId.getRouterId().getValue().equals(routerId.getValue()));
+ }
+
+ public List<Uuid> getVpnInstanceRouterIdsListUuid(List<RouterIds> routerIds) {
+ if (routerIds == null) {
+ return Collections.emptyList();
+ }
+ return routerIds.stream().map(
+ routerId -> routerId.getRouterId()).collect(Collectors.toList());
+ }
+
+ public static RouterIds getvpnInstanceRouterIds(Uuid routerId) {
+ return new RouterIdsBuilder().setRouterId(routerId).build();
+ }
+
+ public static List<RouterIds> getVpnInstanceRouterIdsList(List<Uuid> routerIds) {
+ List<RouterIds> listRouterIds = new ArrayList<>();
+ for (Uuid routerId : routerIds) {
+ final RouterIds routerIdInstance = getvpnInstanceRouterIds(routerId);
+ listRouterIds.add(routerIdInstance);
+ }
+ return listRouterIds;
+ }
+
@Nonnull
public List<BigInteger> getDpnsForRouter(String routerUuid) {
InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class)
LogicalDatastoreType.OPERATIONAL, id);
List<BigInteger> dpns = new ArrayList<>();
if (routerDpnListData.isPresent()) {
- List<DpnVpninterfacesList> dpnVpninterfacesList = routerDpnListData.get().getDpnVpninterfacesList();
- for (DpnVpninterfacesList dpnVpnInterface : dpnVpninterfacesList) {
+ for (DpnVpninterfacesList dpnVpnInterface : requireNonNullElse(
+ routerDpnListData.get().getDpnVpninterfacesList(), Collections.<DpnVpninterfacesList>emptyList())) {
dpns.add(dpnVpnInterface.getDpnId());
}
}
return dpns;
}
- public String getRouterIdfromVpnInstance(String vpnName) {
+ @Nullable
+ public List<Uuid> getRouterIdsfromVpnInstance(String vpnName) {
// returns only router, attached to IPv4 networks
InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
.child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
if (!optionalVpnMap.isPresent()) {
- LOG.error("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
+ LOG.error("getRouterIdsfromVpnInstance : Router not found for vpn : {}", vpnName);
return null;
}
- Uuid routerId = optionalVpnMap.get().getRouterId();
- if (routerId != null) {
- return routerId.getValue();
- }
- LOG.info("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
- return null;
+ List<Uuid> rtrIds = optionalVpnMap.get().getRouterIds().stream().map(routerIds -> routerIds.getRouterId())
+ .collect(Collectors.toList());
+ return rtrIds;
+
}
public InstanceIdentifier<Router> buildNeutronRouterIdentifier(Uuid routerUuid) {
.child(Routers.class).child(Router.class, new RouterKey(routerUuid));
return routerInstanceIdentifier;
}
+
+ @Nullable
+ List<Subnetmap> getSubnetmapListFromNetworkId(Uuid networkId) {
+ List<Uuid> subnetIdList = getSubnetIdsFromNetworkId(networkId);
+ if (subnetIdList != null) {
+ List<Subnetmap> subnetmapList = new ArrayList<>();
+ for (Uuid subnetId : subnetIdList) {
+ Subnetmap subnetmap = getSubnetmap(subnetId);
+ if (subnetmap != null) {
+ subnetmapList.add(subnetmap);
+ } else {
+ LOG.error("getSubnetmapListFromNetworkId: subnetmap is null for subnet {} belonging to network {}",
+ subnetId.getValue(), networkId.getValue());
+ }
+ }
+ return subnetmapList;
+ }
+ LOG.error("getSubnetmapListFromNetworkId: Failed as subnetIdList is null for network {}",
+ networkId.getValue());
+ return null;
+ }
+
+ @Nullable
+ public long getVpnId(String vpnName) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
+ .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
+ return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
+ .VpnInstance::getVpnId).orElse(null);
+ }
+
+ protected boolean isV6SubnetPartOfRouter(Uuid routerId) {
+ List<Subnetmap> subnetList = getNeutronRouterSubnetMapList(routerId);
+ for (Subnetmap sm : subnetList) {
+ if (sm == null) {
+ continue;
+ }
+ IpVersionChoice ipVers = getIpVersionFromString(sm.getSubnetIp());
+ //skip further subnet processing once found first V6 subnet for the router
+ if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public <T extends DataObject> void asyncReadAndExecute(final LogicalDatastoreType datastoreType,
+ final InstanceIdentifier<T> iid, final String jobKey,
+ final Function<Optional<T>, Void> function) {
+ jobCoordinator.enqueueJob(jobKey, () -> {
+ SettableFuture<Optional<T>> settableFuture = SettableFuture.create();
+ List futures = Collections.singletonList(settableFuture);
+ try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
+ Futures.addCallback(tx.read(datastoreType, iid),
+ new SettableFutureCallback<Optional<T>>(settableFuture) {
+ @Override
+ public void onSuccess(Optional<T> data) {
+ function.apply(data);
+ super.onSuccess(data);
+ }
+ }, MoreExecutors.directExecutor());
+
+ return futures;
+ }
+ }, JOB_MAX_RETRIES);
+ }
+
+ private class SettableFutureCallback<T> implements FutureCallback<T> {
+
+ private final SettableFuture<T> settableFuture;
+
+ SettableFutureCallback(SettableFuture<T> settableFuture) {
+ this.settableFuture = settableFuture;
+ }
+
+ @Override
+ public void onSuccess(T objT) {
+ settableFuture.set(objT);
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ settableFuture.setException(throwable);
+ }
+ }
}
+