package org.opendaylight.netvirt.vpnmanager.api.intervpnlink;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
private static void addToEndpointCache(InterVpnLinkDataComposite iVpnLink) {
ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
(ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(ENDPOINT_2_IVPNLINK_CACHE_NAME);
+ if ( cache == null ) {
+ LOG.warn("Cache {} is not ready", ENDPOINT_2_IVPNLINK_CACHE_NAME);
+ return;
+ }
if ( iVpnLink.getFirstEndpointIpAddr().isPresent() ) {
cache.put(iVpnLink.getFirstEndpointIpAddr().get(), iVpnLink);
}
private static void addToVpnUuidCache(InterVpnLinkDataComposite iVpnLink) {
ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
(ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(UUID_2_IVPNLINK_CACHE_NAME);
+ if ( cache == null ) {
+ LOG.warn("Cache {} is not ready", UUID_2_IVPNLINK_CACHE_NAME);
+ return;
+ }
if ( iVpnLink.getFirstEndpointVpnUuid().isPresent() ) {
cache.put(iVpnLink.getFirstEndpointVpnUuid().get(), iVpnLink);
}
private static void addToIVpnLinkNameCache(InterVpnLinkDataComposite iVpnLink) {
ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
(ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(IVPNLINK_NAME_2_IVPNLINK_CACHE_NAME);
+ if ( cache == null ) {
+ LOG.warn("Cache {} is not ready", IVPNLINK_NAME_2_IVPNLINK_CACHE_NAME);
+ return;
+ }
cache.put(iVpnLink.getInterVpnLinkName(), iVpnLink);
if ( iVpnLink.getSecondEndpointIpAddr().isPresent() ) {
cache.put(iVpnLink.getSecondEndpointIpAddr().get(), iVpnLink);
public static void removeInterVpnLinkFromCache(InterVpnLink iVpnLink) {
ConcurrentHashMap<String, InterVpnLink> cache =
(ConcurrentHashMap<String, InterVpnLink>) CacheUtil.getCache(ENDPOINT_2_IVPNLINK_CACHE_NAME);
- cache.remove(iVpnLink.getFirstEndpoint().getIpAddress().getValue());
- cache.remove(iVpnLink.getSecondEndpoint().getIpAddress().getValue());
+ if ( cache != null ) {
+ cache.remove(iVpnLink.getFirstEndpoint().getIpAddress().getValue());
+ cache.remove(iVpnLink.getSecondEndpoint().getIpAddress().getValue());
+ } else {
+ LOG.warn("Cache {} is not ready", ENDPOINT_2_IVPNLINK_CACHE_NAME);
+ }
ConcurrentHashMap<String, InterVpnLink> cache2 =
(ConcurrentHashMap<String, InterVpnLink>) CacheUtil.getCache(UUID_2_IVPNLINK_CACHE_NAME);
- cache2.remove(iVpnLink.getFirstEndpoint().getVpnUuid().getValue());
- cache2.remove(iVpnLink.getSecondEndpoint().getVpnUuid().getValue());
+ if ( cache2 != null ) {
+ cache2.remove(iVpnLink.getFirstEndpoint().getVpnUuid().getValue());
+ cache2.remove(iVpnLink.getSecondEndpoint().getVpnUuid().getValue());
+ } else {
+ LOG.warn("Cache {} is not ready", UUID_2_IVPNLINK_CACHE_NAME);
+ }
}
private static void removeFromInterVpnLinkNameCache(InterVpnLinkDataComposite iVpnLinkComposite) {
ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
(ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(IVPNLINK_NAME_2_IVPNLINK_CACHE_NAME);
- cache.remove(iVpnLinkComposite.getInterVpnLinkName());
+ if ( cache != null ) {
+ cache.remove(iVpnLinkComposite.getInterVpnLinkName());
+ } else {
+ LOG.warn("removeFromInterVpnLinkNameCache: Cache {} is not ready", IVPNLINK_NAME_2_IVPNLINK_CACHE_NAME);
+ }
}
private static void removeFromVpnUuidCache(InterVpnLinkDataComposite iVpnLinkComposite) {
ConcurrentHashMap<String, InterVpnLink> cache =
(ConcurrentHashMap<String, InterVpnLink>) CacheUtil.getCache(UUID_2_IVPNLINK_CACHE_NAME);
+ if ( cache == null ) {
+ LOG.warn("removeFromVpnUuidCache: Cache {} is not ready", UUID_2_IVPNLINK_CACHE_NAME);
+ return;
+ }
Optional<String> opt1stEndpointUuid = iVpnLinkComposite.getFirstEndpointVpnUuid();
if ( opt1stEndpointUuid.isPresent() ) {
cache.remove(opt1stEndpointUuid.get());
private static void removeFromEndpointIpAddressCache(InterVpnLinkDataComposite iVpnLinkComposite) {
ConcurrentHashMap<String, InterVpnLink> cache =
(ConcurrentHashMap<String, InterVpnLink>) CacheUtil.getCache(ENDPOINT_2_IVPNLINK_CACHE_NAME);
+ if ( cache == null ) {
+ LOG.warn("removeFromVpnUuidCache: Cache {} is not ready", ENDPOINT_2_IVPNLINK_CACHE_NAME);
+ return;
+ }
Optional<String> opt1stEndpointIpAddr = iVpnLinkComposite.getFirstEndpointIpAddr();
if ( opt1stEndpointIpAddr.isPresent() ) {
cache.remove(opt1stEndpointIpAddr.get());
public static Optional<InterVpnLinkDataComposite> getInterVpnLinkByName(String iVpnLinkName) {
ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
(ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(IVPNLINK_NAME_2_IVPNLINK_CACHE_NAME);
- InterVpnLinkDataComposite iVpnLink = cache.get(iVpnLinkName);
- return (iVpnLink == null) ? Optional.<InterVpnLinkDataComposite>absent() : Optional.of(iVpnLink);
+ return (cache == null) ? Optional.<InterVpnLinkDataComposite>absent()
+ : Optional.fromNullable(cache.get(iVpnLinkName));
}
public static Optional<InterVpnLinkDataComposite> getInterVpnLinkByEndpoint(String endpointIp) {
LOG.trace("Checking if {} is configured as an InterVpnLink endpoint", endpointIp);
ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
(ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(ENDPOINT_2_IVPNLINK_CACHE_NAME);
- InterVpnLinkDataComposite iVpnLink = cache.get(endpointIp);
- LOG.trace("_XX IP {} is configured for InterVpnLink {}", endpointIp, iVpnLink);
- return (iVpnLink == null) ? Optional.<InterVpnLinkDataComposite>absent() : Optional.of(iVpnLink);
+ return (cache == null) ? Optional.<InterVpnLinkDataComposite>absent()
+ : Optional.fromNullable(cache.get(endpointIp));
}
public static Optional<InterVpnLinkDataComposite> getInterVpnLinkByVpnId(String vpnId) {
- ConcurrentHashMap<String, InterVpnLinkDataComposite> cache2 =
+ ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
+ (ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(UUID_2_IVPNLINK_CACHE_NAME);
+ return (cache == null) ? Optional.<InterVpnLinkDataComposite>absent() : Optional.fromNullable(cache.get(vpnId));
+ }
+
+ public static List<InterVpnLinkDataComposite> getAllInterVpnLinks() {
+ ConcurrentHashMap<String, InterVpnLinkDataComposite> cache =
(ConcurrentHashMap<String, InterVpnLinkDataComposite>) CacheUtil.getCache(UUID_2_IVPNLINK_CACHE_NAME);
- InterVpnLinkDataComposite iVpnLink = cache2.get(vpnId);
- return (iVpnLink == null) ? Optional.<InterVpnLinkDataComposite>absent() : Optional.of(iVpnLink);
+ return (cache == null) ? Collections.<InterVpnLinkDataComposite>emptyList()
+ : Collections.list(cache.elements());
}
}
package org.opendaylight.netvirt.vpnmanager.api.intervpnlink;
+import com.google.common.base.Optional;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState.State;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
/**
* It holds all info about an InterVpnLink, combining both configurational
- * and stateful
+ * and stateful.
*/
public class InterVpnLinkDataComposite {
private InterVpnLink interVpnLinkCfg;
private InterVpnLinkState interVpnLinkState;
- public InterVpnLinkDataComposite(InterVpnLink iVpnLink) {
- this.interVpnLinkCfg = iVpnLink;
+ public InterVpnLinkDataComposite(InterVpnLink interVpnLink) {
+ this.interVpnLinkCfg = interVpnLink;
}
- public InterVpnLinkDataComposite(InterVpnLinkState iVpnLinkState) {
- this.interVpnLinkState = iVpnLinkState;
+ public InterVpnLinkDataComposite(InterVpnLinkState interVpnLinkState) {
+ this.interVpnLinkState = interVpnLinkState;
}
- public InterVpnLinkDataComposite(InterVpnLink iVpnLink, InterVpnLinkState iVpnLinkState) {
- this.interVpnLinkCfg = iVpnLink;
- this.interVpnLinkState = iVpnLinkState;
+ public InterVpnLinkDataComposite(InterVpnLink interVpnLink, InterVpnLinkState interVpnLinkState) {
+ this.interVpnLinkCfg = interVpnLink;
+ this.interVpnLinkState = interVpnLinkState;
}
public InterVpnLink getInterVpnLinkConfig() {
return this.interVpnLinkCfg;
}
- public void setInterVpnLinkConfig(InterVpnLink iVpnLink) {
- this.interVpnLinkCfg = iVpnLink;
+ public void setInterVpnLinkConfig(InterVpnLink interVpnLink) {
+ this.interVpnLinkCfg = interVpnLink;
}
public InterVpnLinkState getInterVpnLinkState() {
return this.interVpnLinkState;
}
- public void setInterVpnLinkState(InterVpnLinkState iVpnLinkState) {
- this.interVpnLinkState = iVpnLinkState;
+ public void setInterVpnLinkState(InterVpnLinkState interVpnLinkState) {
+ this.interVpnLinkState = interVpnLinkState;
}
public boolean isComplete() {
- return interVpnLinkCfg != null && interVpnLinkState != null;
+ return interVpnLinkCfg != null && interVpnLinkState != null
+ && interVpnLinkState.getFirstEndpointState() != null
+ && interVpnLinkState.getSecondEndpointState() != null;
}
public Optional<InterVpnLinkState.State> getState() {
return this.interVpnLinkState == null ? Optional.absent()
- : Optional.of(this.interVpnLinkState.getState());
+ : Optional.fromNullable(this.interVpnLinkState.getState());
}
public boolean isActive() {
public boolean isSecondEndpointIpAddr(String endpointIp) {
return interVpnLinkCfg != null
- &&interVpnLinkCfg.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp);
+ && interVpnLinkCfg.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp);
}
public boolean isIpAddrTheOtherVpnEndpoint(String ipAddr, String vpnUuid) {
return Optional.of(this.interVpnLinkCfg.getFirstEndpoint().getIpAddress().getValue());
}
+ public List<BigInteger> getFirstEndpointDpns() {
+ return ( !isComplete() || this.interVpnLinkState.getFirstEndpointState().getDpId() == null )
+ ? Collections.<BigInteger>emptyList()
+ : this.interVpnLinkState.getFirstEndpointState().getDpId();
+ }
+
public Optional<String> getSecondEndpointVpnUuid() {
if ( !isComplete() ) {
return Optional.absent();
return Optional.of(this.interVpnLinkCfg.getSecondEndpoint().getIpAddress().getValue());
}
+ public List<BigInteger> getSecondEndpointDpns() {
+ return (!isComplete() || this.interVpnLinkState.getSecondEndpointState().getDpId() == null )
+ ? Collections.<BigInteger>emptyList()
+ : this.interVpnLinkState.getSecondEndpointState().getDpId();
+ }
+
public Optional<Long> getEndpointLportTagByIpAddr(String endpointIp) {
if ( !isComplete() ) {
return Optional.absent();
}
- return isFirstEndpointIpAddr(endpointIp) ? Optional.of(interVpnLinkState.getFirstEndpointState().getLportTag())
- : Optional.of(interVpnLinkState.getSecondEndpointState().getLportTag());
+ return isFirstEndpointIpAddr(endpointIp)
+ ? Optional.fromNullable(interVpnLinkState.getFirstEndpointState().getLportTag())
+ : Optional.fromNullable(interVpnLinkState.getSecondEndpointState().getLportTag());
}
public Optional<Long> getOtherEndpointLportTagByVpnName(String vpnName) {
}
public List<BigInteger> getEndpointDpnsByVpnName(String vpnUuid) {
- List<BigInteger> result = new ArrayList<>();
- if ( !isComplete()) {
- return result;
+ if ( !isComplete() ) {
+ return new ArrayList<>();
}
return isFirstEndpointVpnName(vpnUuid) ? interVpnLinkState.getFirstEndpointState().getDpId()
public List<BigInteger> getOtherEndpointDpnsByVpnName(String vpnUuid) {
List<BigInteger> result = new ArrayList<>();
- if ( !isComplete()) {
+ if ( !isComplete() ) {
return result;
}
.setInterfaceName(interfaceName).setRouterName(routerName).build();
}
- static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
+ public static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
- Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
- if (vpnInstanceOpData.isPresent()) {
- return vpnInstanceOpData.get();
- }
- return null;
+ return read(broker, LogicalDatastoreType.OPERATIONAL, id).orNull();
}
static VpnInstanceOpDataEntry getVpnInstanceOpDataFromCache(DataBroker broker, String rd) {
import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(InterVpnLinkListener.class);
- private static final String NBR_OF_DPNS_PROPERTY_NAME = "vpnservice.intervpnlink.number.dpns";
+
private static final long INVALID_ID = 0;
+ private final InterVpnLinkService ivpnLinkService;
private final DataBroker dataBroker;
private final IMdsalApiManager mdsalManager;
private final IdManagerService idManager;
public InterVpnLinkListener(final DataBroker dataBroker, final IdManagerService idManager,
final IMdsalApiManager mdsalManager, final IBgpManager bgpManager,
final IFibManager fibManager, final NotificationPublishService notifService,
- final VpnFootprintService vpnFootprintService, final VpnOpDataSyncer vpnOpDataSyncer) {
+ final InterVpnLinkService interVpnLinkService,
+ final VpnFootprintService vpnFootprintService,
+ final VpnOpDataSyncer vpnOpDataSyncer) {
super(InterVpnLink.class, InterVpnLinkListener.class);
this.dataBroker = dataBroker;
this.idManager = idManager;
this.bgpManager = bgpManager;
this.fibManager = fibManager;
this.notificationsService = notifService;
+ this.ivpnLinkService = interVpnLinkService;
this.vpnFootprintService = vpnFootprintService;
this.vpnOpDataSyncer = vpnOpDataSyncer;
}
}
}
- int numberOfDpns = Integer.getInteger(NBR_OF_DPNS_PROPERTY_NAME, 1);
- List<BigInteger> firstDpnList = VpnUtil.pickRandomDPNs(dataBroker, numberOfDpns, null);
+ List<BigInteger> firstDpnList = ivpnLinkService.selectSuitableDpns(add);
if (firstDpnList != null && !firstDpnList.isEmpty()) {
List<BigInteger> secondDpnList = firstDpnList;
Long firstVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn1Name);
Long secondVpnLportTag = allocateVpnLinkLportTag(key.getName() + vpn2Name);
FirstEndpointState firstEndPointState =
- new FirstEndpointStateBuilder().setVpnUuid(vpn1Uuid).setLportTag(firstVpnLportTag).build();
+ new FirstEndpointStateBuilder().setVpnUuid(vpn1Uuid).setLportTag(firstVpnLportTag)
+ .setDpId(Collections.emptyList()).build();
SecondEndpointState secondEndPointState =
- new SecondEndpointStateBuilder().setVpnUuid(vpn2Uuid).setLportTag(secondVpnLportTag).build();
+ new SecondEndpointStateBuilder().setVpnUuid(vpn2Uuid).setLportTag(secondVpnLportTag)
+ .setDpId(Collections.emptyList()).build();
InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Error,
firstEndPointState, secondEndPointState);
}
// Retrieving all Routers
InstanceIdentifier<Routers> routersIid = InstanceIdentifier.builder(Neutron.class).child(Routers.class).build();
Optional<Routers> routerOpData = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersIid);
+ if ( !routerOpData.isPresent() ) {
+
+ return;
+ }
List<Router> routers = routerOpData.get().getRouter();
for ( Router router : routers ) {
String vpnId = routerXL3VpnMap.get(router.getUuid().getValue());
LOG.warn("Could not find suitable VPN for router {}", router.getUuid());
continue; // with next router
}
- for ( Routes route : router.getRoutes() ) {
- handleStaticRoute(vpnId, route, iVpnLink);
+ List<Routes> routerRoutes = router.getRoutes();
+ if ( routerRoutes != null ) {
+ for ( Routes route : routerRoutes ) {
+ handleStaticRoute(vpnId, route, iVpnLink);
+ }
}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.vpnmanager.intervpnlink;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.NWUtil;
+import org.opendaylight.netvirt.vpnmanager.VpnUtil;
+import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
+import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnTargets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InterVpnLinkService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(InterVpnLinkService.class);
+ private static final String NBR_OF_DPNS_PROPERTY_NAME = "vpnservice.intervpnlink.number.dpns";
+
+ private final DataBroker dataBroker;
+
+ public InterVpnLinkService(final DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ /**
+ * Retrieves a list of randomly selected DPNs avoiding to select DPNs
+ * where there is already an InterVpnLink of the same group (i.e., an
+ * InterVpnLink that links similar L3VPNs).
+ *
+ * @param interVpnLink InterVpnLink to find suitable DPNs for.
+ * @return the list of the selected DPN Ids
+ */
+ public List<BigInteger> selectSuitableDpns(InterVpnLink interVpnLink) {
+ int numberOfDpns = Integer.getInteger(NBR_OF_DPNS_PROPERTY_NAME, 1);
+ List<BigInteger> dpnIdPool = NWUtil.getOperativeDPNs(dataBroker);
+ LOG.trace("selectSuitableDpns for {} with numberOfDpns={} and availableDpns={}",
+ interVpnLink.getName(), numberOfDpns, dpnIdPool);
+ int poolSize = dpnIdPool.size();
+ if (poolSize <= numberOfDpns) {
+ // You requested more than there is, I give you all I have.
+ return dpnIdPool;
+ }
+
+ List<InterVpnLinkDataComposite> allInterVpnLinks = InterVpnLinkCache.getAllInterVpnLinks();
+
+ // 1st criteria is to select those DPNs where there is no InterVpnLink at all
+ List<BigInteger> dpnsWithNoIVL = findDPNsWithNoInterVpnLink(dpnIdPool, allInterVpnLinks);
+ if ( dpnsWithNoIVL.size() >= numberOfDpns ) {
+ return dpnsWithNoIVL.subList(0, numberOfDpns); // Best case scenario
+ }
+
+ // Not enough. 2nd criteria is to avoid DPNs where there are InterVpnLinks of the same group
+ List<BigInteger> result = new ArrayList<>(dpnsWithNoIVL);
+ dpnIdPool.removeAll(result);
+ int pendingDPNs = numberOfDpns - result.size();
+
+ List<BigInteger> dpnsToAvoid = findDpnsWithSimilarIVpnLinks(interVpnLink, allInterVpnLinks);
+ result.addAll(dpnIdPool.stream().filter(dpId -> dpnsToAvoid == null || !dpnsToAvoid.contains(dpId))
+ .limit(pendingDPNs).collect(Collectors.toList()));
+
+ int currentNbrOfItems = result.size();
+ if (currentNbrOfItems < numberOfDpns) {
+ // Still not enough. 3rd criteria: whatever is available
+ dpnIdPool.removeAll(result);
+ pendingDPNs = numberOfDpns - currentNbrOfItems;
+ result.addAll(dpnIdPool.subList(0, Math.max(dpnIdPool.size(), pendingDPNs)));
+ }
+ return result;
+ }
+
+ /*
+ * Given a list of Dpn Ids and a list of InterVpnLinks, this method finds
+ * the DPNs in the first list where no InterVpnLink is instantiated there.
+ *
+ * @param dpnList A list of DPN IDs
+ * @param interVpnLinks A List of InterVpnLinks to avoid
+ *
+ * @return the list of available DPNs among the specified ones
+ */
+ private List<BigInteger> findDPNsWithNoInterVpnLink(List<BigInteger> dpnList,
+ List<InterVpnLinkDataComposite> interVpnLinks) {
+ List<BigInteger> occupiedDpns = new ArrayList<>();
+ for ( InterVpnLinkDataComposite ivl : interVpnLinks ) {
+ if ( ivl.isActive() ) {
+ occupiedDpns.addAll(ivl.getFirstEndpointDpns());
+ occupiedDpns.addAll(ivl.getSecondEndpointDpns());
+ }
+ }
+
+ List<BigInteger> result = new ArrayList<>(dpnList);
+ result.removeAll(occupiedDpns);
+ return result;
+ }
+
+ /*
+ * Given an InterVpnLink, this method finds those DPNs where there is an
+ * InterVpnLink of the same group. Two InterVpnLinks are in the same group
+ * if they link 2 L3VPNs that are from the same group, and 2 L3VPNs are in
+ * the same group if their iRTs match.
+ *
+ * @param interVpnLink InterVpnLink to be checked
+ * @return the list of dpnIds where the specified InterVpnLink should not
+ * be installed
+ */
+ private List<BigInteger> findDpnsWithSimilarIVpnLinks(InterVpnLink interVpnLink,
+ List<InterVpnLinkDataComposite> allInterVpnLinks) {
+ List<InterVpnLinkDataComposite> sameGroupInterVpnLinks = findInterVpnLinksSameGroup(interVpnLink,
+ allInterVpnLinks);
+ Set<BigInteger> resultDpns = new HashSet<>();
+ for ( InterVpnLinkDataComposite ivl : sameGroupInterVpnLinks ) {
+ resultDpns.addAll(ivl.getFirstEndpointDpns());
+ resultDpns.addAll(ivl.getSecondEndpointDpns());
+ }
+ return new ArrayList<>(resultDpns);
+ }
+
+ private List<String> getRts(VpnInstanceOpDataEntry vpnInstance, VpnTarget.VrfRTType rtType) {
+ String name = vpnInstance.getVpnInstanceName();
+ VpnTargets targets = vpnInstance.getVpnTargets();
+ if (targets == null) {
+ LOG.trace("vpn targets not available for {}", name);
+ return new ArrayList<>();
+ }
+ List<VpnTarget> vpnTargets = targets.getVpnTarget();
+ if (vpnTargets == null) {
+ LOG.trace("vpnTarget values not available for {}", name);
+ return new ArrayList<>();
+ }
+ return vpnTargets.stream()
+ .filter(target-> target.getVrfRTType().equals(rtType) ||
+ target.getVrfRTType().equals(VpnTarget.VrfRTType.Both))
+ .map(target-> target.getVrfRTValue())
+ .collect(Collectors.toList());
+ }
+
+ private List<String> getIRTsByVpnName(String vpnName) {
+ String vpn1Rd = VpnUtil.getVpnRd(dataBroker, vpnName);
+ final VpnInstanceOpDataEntry vpnInstance = VpnUtil.getVpnInstanceOpData(dataBroker, vpn1Rd);
+ return getRts(vpnInstance, VpnTarget.VrfRTType.ImportExtcommunity);
+ }
+
+ private boolean haveSameIRTs(List<String> irts1, List<String> irts2) {
+ if ( irts1 == null && irts2 == null ) {
+ return true;
+ }
+ if ( (irts1 == null && irts2 != null) || (irts1 != null && irts2 == null) ) {
+ return false;
+ }
+ if ( irts1.size() != irts2.size() ) {
+ return false;
+ }
+ irts1.sort(/*comparator*/ null);
+ irts2.sort(/*comparator*/ null);
+ return irts1.equals(irts2);
+ }
+
+ public List<InterVpnLinkDataComposite> findInterVpnLinksSameGroup(InterVpnLink ivpnLinkToMatch,
+ List<InterVpnLinkDataComposite> interVpnLinks) {
+
+ List<String> vpnToMatch1IRTs = getIRTsByVpnName(ivpnLinkToMatch.getFirstEndpoint().getVpnUuid().getValue());
+ List<String> vpnToMatch2IRTs = getIRTsByVpnName(ivpnLinkToMatch.getSecondEndpoint().getVpnUuid().getValue());
+
+ Predicate<InterVpnLinkDataComposite> areSameGroup = (ivl) -> {
+ if ( ivl.getInterVpnLinkName().equals(ivpnLinkToMatch.getName())) {
+ return false; // ivl and ivpnLinlToMatch are the same InterVpnLink
+ }
+ String vpn1Name = ivl.getFirstEndpointVpnUuid().orNull();
+ String vpn2Name = ivl.getSecondEndpointVpnUuid().orNull();
+ if ( vpn1Name == null ) {
+ return false;
+ }
+ List<String> vpn1IRTs = getIRTsByVpnName(vpn1Name);
+ List<String> vpn2IRTs = getIRTsByVpnName(vpn2Name);
+ return (haveSameIRTs(vpn1IRTs, vpnToMatch1IRTs) && haveSameIRTs(vpn2IRTs, vpnToMatch2IRTs)
+ || (haveSameIRTs(vpn1IRTs, vpnToMatch2IRTs) && haveSameIRTs(vpn2IRTs, vpnToMatch1IRTs)) );
+ };
+
+ return interVpnLinks.stream().filter(areSameGroup).collect(Collectors.toList());
+ }
+
+}
<service ref="vpnRpcServiceImpl"
interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService" />
+ <bean id="interVpnLinkService"
+ class="org.opendaylight.netvirt.vpnmanager.intervpnlink.InterVpnLinkService">
+ <argument ref="dataBroker" />
+ </bean>
+
<bean id="interVpnLinkListener"
class="org.opendaylight.netvirt.vpnmanager.intervpnlink.InterVpnLinkListener"
init-method="start" destroy-method="close">
<argument ref="bgpmanager" />
<argument ref="fibManager" />
<argument ref="notificationPublishService" />
+ <argument ref="interVpnLinkService" />
<argument ref="vpnFootprintService" />
<argument ref="vpnOpDataSyncer" />
</bean>