Vrfs dto = new VrfsBuilder().setRd(rd)
.setImportRts(irts)
.setExportRts(erts).build();
-
- asyncWrite(iid, dto);
+ BgpUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
}
public synchronized void stopConfig() {
import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
return Optional.absent();
}
+ public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
public static void setBroker(final DataBroker broker) {
BgpUtil.dataBroker = broker;
initTransactionChain();
public long createLocalNextHop(long vpnId, BigInteger dpnId,
String ifName, String ipAddress) {
long groupId = createNextHopPointer(getNextHopKey(vpnId, ipAddress));
+ if (groupId == 0) {
+ LOG.error("Unable to allocate groupId for vpnId {} , prefix {}", vpnId, ipAddress);
+ return groupId;
+ }
String nextHopLockStr = new String(vpnId + ipAddress);
synchronized (nextHopLockStr.intern()) {
VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
if (localNextHopInfo != null) {
final BigInteger dpnId = localNextHopInfo.getDpnId();
if (!isVpnPresentInDpn(rd, dpnId)) {
+ LOG.error("The vpnName with vpnId {} rd {} is not available on dpn {}", vpnId, rd, dpnId.toString());
return BigInteger.ZERO;
}
final long groupId = nextHopManager.createLocalNextHop(parentVpnId, dpnId, localNextHopInfo.getVpnInterfaceName(), localNextHopIP);
-
+ if (groupId == 0) {
+ LOG.error("Unable to create Group for local prefix {} on rd {} for vpninterface {} on Node {}",
+ vrfEntry.getDestPrefix(), rd, localNextHopInfo.getVpnInterfaceName(), dpnId.toString());
+ return BigInteger.ZERO;
+ }
List<ActionInfo> actionsInfos =
Arrays.asList(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
final List<InstructionInfo> instructions =
LOG.debug("NAT Service : BGP VPN ID {}", bgpVpnId);
String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
+ if (routerName == null) {
+ LOG.error("NAT Service: Unable to find router for VpnName {}", vpnName);
+ return;
+ }
routerId = NatUtil.getVpnId(dataBroker, routerName);
LOG.debug("NAT Service : Router ID {}", routerId);
dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
LOG.debug("NaptFlowRemovedEventHandler : BGP VPN ID {}", bgpVpnId);
String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
+ if (routerName == null) {
+ LOG.error("NAT Service: Unable to find router for VpnName {}", vpnName);
+ return;
+ }
routerId = NatUtil.getVpnId(dataBroker, routerName);
LOG.debug("NaptFlowRemovedEventHandler : Router ID {}", routerId);
ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId, internalIpv4HostAddress, internalPortNumber.toString(), protocol);
Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
vpnMapIdentifier);
if (optionalVpnMap.isPresent()) {
- return optionalVpnMap.get().getRouterId().getValue();
+ Uuid routerId = optionalVpnMap.get().getRouterId();
+ if (routerId != null) {
+ return routerId.getValue();
+ }
}
return null;
}
public static final long MIN_WAIT_TIME_IN_MILLISECONDS = 10000;
public static final long MAX_WAIT_TIME_IN_MILLISECONDS = 180000;
public static final long PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS = 50000;
+ public static final long PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS = 90000;
+ public static final long PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS = 180000;
public static final int ELAN_GID_MIN = 200000;
public static final int INVALID_LABEL = 0;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
private final IdManagerService idManager;
private final VpnInterfaceManager vpnInterfaceManager;
private final IFibManager fibManager;
- private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
- .setNameFormat("NV-VpnMgr-%d").build();
- private ExecutorService executorService = Executors.newSingleThreadExecutor(threadFactory);
+ private ExecutorService executorService = Executors.newSingleThreadExecutor();
private ConcurrentMap<String, Runnable> vpnOpMap = new ConcurrentHashMap<String, Runnable>();
public VpnInstanceListener(final DataBroker dataBroker, final IBgpManager bgpManager,
return VpnInstanceListener.this;
}
- void notifyTaskIfRequired(String vpnName) {
- Runnable notifyTask = vpnOpMap.remove(vpnName);
- if (notifyTask == null) {
- LOG.trace("VpnInstanceListener update: No Notify Task queued for vpnName {}", vpnName);
- return;
- }
- executorService.execute(notifyTask);
- }
-
private void waitForOpRemoval(String rd, String vpnName) {
//wait till DCN for update on VPN Instance Op Data signals that vpn interfaces linked to this vpn instance is zero
//TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(writeConfigTxn.submit());
ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
- if (rd != null) {
- Futures.addCallback(listenableFuture,
- new AddBgpVrfWorker(config , vpnInstance.getVpnInstanceName()));
- }
+ Futures.addCallback(listenableFuture,
+ new AddBgpVrfWorker(config , vpnInstance.getVpnInstanceName()));
return futures;
}
}
long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
if (vpnId == 0) {
+ LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
return;
}
- LOG.trace("VPN instance to ID generated.");
+ LOG.info("VPN Id {} generated for VpnInstanceName {}", vpnId, vpnInstanceName);
org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
: vpnInstanceName);
try {
String cachedTransType = fibManager.getConfTransType();
- LOG.trace("Value for confTransportType is " + cachedTransType);
if (cachedTransType.equals("Invalid")) {
try {
fibManager.setConfTransType("L3VPN", "VXLAN");
} catch (Exception e) {
- LOG.trace("Exception caught setting the cached value for transportType");
- LOG.error(e.getMessage());
+ LOG.error("Exception caught setting the L3VPN tunnel transportType", e);
}
} else {
- LOG.trace(":cached val is neither unset/invalid. NO-op.");
+ LOG.trace("Configured tunnel transport type for L3VPN as {}", cachedTransType);
}
} catch (Exception e) {
- LOG.error(e.getMessage());
+ LOG.error("Error when trying to retrieve tunnel transport type for L3VPN ", e);
}
if (rd == null) {
builder.build(), TransactionUtil.DEFAULT_CALLBACK);
}
}
+ LOG.info("VpnInstanceOpData populated successfully for vpn {} rd {}", vpnInstanceName, rd);
}
LOG.error("Exception when adding VRF to BGP", e);
return;
}
- vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
+ notifyTaskIfRequired(vpnName, vpnInterfaceManager.getvpnInstanceToIdSynchronizerMap());
+ notifyTaskIfRequired(vpnName, vpnInterfaceManager.getvpnInstanceOpDataSynchronizerMap());
+ if (rd != null) {
+ vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
+ }
}
}
/**
}
return null;
}
+
+ private void notifyTaskIfRequired(String vpnName,
+ ConcurrentHashMap<String, List<Runnable>> vpnInstanceMap) {
+ synchronized (vpnInstanceMap) {
+ List<Runnable> notifieeList = vpnInstanceMap.remove(vpnName);
+ if (notifieeList == null) {
+ LOG.trace(" No notify tasks found for vpnName {}", vpnName);
+ return;
+ }
+ Iterator<Runnable> notifieeIter = notifieeList.iterator();
+ while (notifieeIter.hasNext()) {
+ Runnable notifyTask = notifieeIter.next();
+ executorService.execute(notifyTask);
+ notifieeIter.remove();
+ }
+ }
+ }
}
private final OdlArputilService arpManager;
private final OdlInterfaceRpcService ifaceMgrRpcService;
private final NotificationPublishService notificationPublishService;
- private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
- private final ExecutorService executorService = Executors.newSingleThreadExecutor();
+ private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
+ private ConcurrentHashMap<String, List<Runnable>> vpnInstanceToIdSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
+ private ConcurrentHashMap<String, List<Runnable>> vpnInstanceOpDataSynchronizerMap = new ConcurrentHashMap<String, List<Runnable>>();
+ private ExecutorService executorService = Executors.newSingleThreadExecutor();
public VpnInterfaceManager(final DataBroker dataBroker,
final IBgpManager bgpManager,
return VpnInterfaceManager.this;
}
+ public ConcurrentHashMap<String, List<Runnable>> getvpnInstanceToIdSynchronizerMap() {
+ return vpnInstanceToIdSynchronizerMap;
+ }
+
+ public ConcurrentHashMap<String, List<Runnable>> getvpnInstanceOpDataSynchronizerMap() {
+ return vpnInstanceOpDataSynchronizerMap;
+ }
private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
return InstanceIdentifier.create(InterfacesState.class)
return;
}
} else {
- LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
+ LOG.error("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
}
}
LOG.info("Binding vpn service to interface {} ", interfaceName);
long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
if (vpnId == VpnConstants.INVALID_ID) {
- LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
- return;
+ waitForVpnInstance(vpnName, VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS, vpnInstanceToIdSynchronizerMap);
+ vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+ if (vpnId == VpnConstants.INVALID_ID) {
+ LOG.error("VpnInstance to VPNId mapping not yet available for VpnName {} processing vpninterface {} " +
+ ", bailing out now.", vpnName, interfaceName);
+ return;
+ }
+ } else {
+ // Incase of cluster reboot , VpnId would be available already as its a configDS fetch.
+ // However VpnInstanceOpData will be repopulated, so if its not available
+ // wait for 180 seconds and retry.
+ // TODO: This wait to be removed by making vpnManager the central engine in carbon
+ String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
+ if (vpnInstanceOpDataEntry == null) {
+ LOG.debug("VpnInstanceOpData not yet populated for vpn {} rd {}", vpnName, vpnRd);
+ int retry = 2;
+ while (retry > 0) {
+ waitForVpnInstance(vpnName, VpnConstants.PER_VPN_INSTANCE_OPDATA_MAX_WAIT_TIME_IN_MILLISECONDS, vpnInstanceOpDataSynchronizerMap);
+ vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
+ if (vpnInstanceOpDataEntry != null) {
+ break;
+ }
+ retry--;
+ if (retry <= 0) {
+ LOG.error("VpnInstanceOpData not populated even after second retry for vpn {} rd {} vpninterface {}, bailing out ", vpnName, vpnRd, interfaceName);
+ return;
+ }
+ }
+ }
}
+
boolean waitForVpnInterfaceOpRemoval = false;
VpnInterface opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, vpnInterface.getName());
if (opVpnInterface != null ) {
}
}
- void notifyTaskIfRequired(String intfName) {
- Runnable notifyTask = vpnIntfMap.remove(intfName);
- if (notifyTask == null) {
- return;
+ //TODO(vivek) This waiting business to be removed in carbon
+ public void waitForVpnInstance(String vpnName, long wait_time,
+ ConcurrentHashMap<String, List<Runnable>> vpnInstanceMap) {
+ List<Runnable> notifieeList = null;
+ Runnable notifyTask = new VpnNotifyTask();
+ try {
+ synchronized (vpnInstanceMap) {
+ notifieeList = vpnInstanceMap.get(vpnName);
+ if (notifieeList == null) {
+ notifieeList = new ArrayList<Runnable>();
+ vpnInstanceMap.put(vpnName, notifieeList);
+ }
+ notifieeList.add(notifyTask);
+ }
+ synchronized (notifyTask) {
+ try {
+ notifyTask.wait(wait_time);
+ } catch (InterruptedException e) {
+ }
+ }
+ } finally {
+ synchronized (vpnInstanceMap) {
+ notifieeList = vpnInstanceMap.get(vpnName);
+ if (notifieeList != null) {
+ notifieeList.remove(notifyTask);
+ if (notifieeList.isEmpty()) {
+ vpnInstanceMap.remove(vpnName);
+ }
+ }
+ }
}
- executorService.execute(notifyTask);
}
}
Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
logger.info("onSubnetAddedToVpn: Subnet " + subnetId.getValue() + " being added to vpn");
+ long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+ if (vpnId == VpnConstants.INVALID_ID) {
+ vpnInterfaceManager.waitForVpnInstance(vpnName, VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS, vpnInterfaceManager.getvpnInstanceToIdSynchronizerMap());
+ vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+ if (vpnId == VpnConstants.INVALID_ID) {
+ logger.error("onSubnetAddedToVpn: VpnInstance to VPNId mapping not yet available for VpnName {} processing subnet {} with IP {} " +
+ ", bailing out now.", vpnName, subnetId, subnetIp);
+ return;
+ }
+ }
//TODO(vivek): Change this to use more granularized lock at subnetId level
try {
VpnUtil.lockSubnet(lockManager, subnetId.getValue());