use of org.opendaylight.mdsal.binding.api.DataBroker in project netvirt by opendaylight.
the class VpnOpStatusListener method update.
@Override
@SuppressWarnings("checkstyle:IllegalCatch")
public void update(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry original, VpnInstanceOpDataEntry update) {
LOG.info("update: Processing update for vpn {} with rd {}", update.getVpnInstanceName(), update.getVrfId());
if (update.getVpnState() == VpnInstanceOpDataEntry.VpnState.PendingDelete && vpnFootprintService.isVpnFootPrintCleared(update)) {
// Cleanup VPN data
final String vpnName = update.getVpnInstanceName();
final List<String> rds = update.getRd();
String primaryRd = update.getVrfId();
final Uint32 vpnId = vpnUtil.getVpnId(vpnName);
jobCoordinator.enqueueJob("VPN-" + update.getVpnInstanceName(), () -> {
// Two transactions are used, one for operational, one for config; we only submit the config
// transaction if the operational transaction succeeds
ListenableFuture<?> operationalFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.OPERATIONAL, operTx -> {
// Clean up VPNExtraRoutes Operational DS
if (rds != null && VpnUtil.isBgpVpn(vpnName, primaryRd)) {
if (update.getType() == VpnInstanceOpDataEntry.Type.L2) {
rds.parallelStream().forEach(rd -> bgpManager.deleteVrf(rd, false, AddressFamily.L2VPN));
}
if (update.getIpAddressFamilyConfigured() == VpnInstanceOpDataEntry.IpAddressFamilyConfigured.Ipv4) {
rds.parallelStream().forEach(rd -> bgpManager.deleteVrf(rd, false, AddressFamily.IPV4));
}
if (update.getIpAddressFamilyConfigured() == VpnInstanceOpDataEntry.IpAddressFamilyConfigured.Ipv6) {
rds.parallelStream().forEach(rd -> bgpManager.deleteVrf(rd, false, AddressFamily.IPV6));
}
if (update.getIpAddressFamilyConfigured() == VpnInstanceOpDataEntry.IpAddressFamilyConfigured.Ipv4AndIpv6) {
rds.parallelStream().forEach(rd -> bgpManager.deleteVrf(rd, false, AddressFamily.IPV4));
rds.parallelStream().forEach(rd -> bgpManager.deleteVrf(rd, false, AddressFamily.IPV6));
}
}
InstanceIdentifier<Vpn> vpnToExtraroute = VpnExtraRouteHelper.getVpnToExtrarouteVpnIdentifier(vpnName);
Optional<Vpn> optVpnToExtraroute = Optional.empty();
try {
optVpnToExtraroute = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
} catch (InterruptedException | ExecutionException e) {
LOG.error("update: Failed to read VpnToExtraRoute for vpn {}", vpnName);
}
if (optVpnToExtraroute.isPresent()) {
VpnUtil.removeVpnExtraRouteForVpn(vpnName, operTx);
}
if (VpnUtil.isL3VpnOverVxLan(update.getL3vni())) {
vpnUtil.removeExternalTunnelDemuxFlows(vpnName);
}
// Clean up PrefixToInterface Operational DS
Optional<VpnIds> optPrefixToIntf = Optional.empty();
try {
optPrefixToIntf = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, VpnUtil.getPrefixToInterfaceIdentifier(vpnId));
} catch (InterruptedException | ExecutionException e) {
LOG.error("update: Failed to read PrefixToInterface for vpn {}", vpnName);
}
if (optPrefixToIntf.isPresent()) {
VpnUtil.removePrefixToInterfaceForVpnId(vpnId, operTx);
}
// Clean up L3NextHop Operational DS
InstanceIdentifier<VpnNexthops> vpnNextHops = InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build();
Optional<VpnNexthops> optL3nexthopForVpnId = Optional.empty();
try {
optL3nexthopForVpnId = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, vpnNextHops);
} catch (InterruptedException | ExecutionException e) {
LOG.error("update: Failed to read VpnNextHops for vpn {}", vpnName);
}
if (optL3nexthopForVpnId.isPresent()) {
VpnUtil.removeL3nexthopForVpnId(vpnId, operTx);
}
// Clean up VPNInstanceOpDataEntry
VpnUtil.removeVpnOpInstance(primaryRd, operTx);
});
Futures.addCallback(operationalFuture, new FutureCallback<Object>() {
@Override
public void onSuccess(Object result) {
Futures.addCallback(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION, confTx -> {
// Clean up VpnInstanceToVpnId from Config DS
VpnUtil.removeVpnIdToVpnInstance(vpnId, confTx);
VpnUtil.removeVpnInstanceToVpnId(vpnName, confTx);
LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", primaryRd, vpnName);
// Clean up FIB Entries Config DS
// FIXME: separate out to somehow?
final ReentrantLock lock = JvmGlobalLocks.getLockForString(vpnName);
lock.lock();
try {
fibManager.removeVrfTable(primaryRd, confTx);
} finally {
lock.unlock();
}
}), new VpnOpStatusListener.PostDeleteVpnInstanceWorker(vpnName), MoreExecutors.directExecutor());
// Note: Release the of VpnId will happen in PostDeleteVpnInstancWorker only if
// operationalTxn/Config succeeds.
}
@Override
public void onFailure(Throwable throwable) {
LOG.error("Error deleting VPN {}", vpnName, throwable);
}
}, MoreExecutors.directExecutor());
LOG.info("Removed vpn data for vpnname {}", vpnName);
return Collections.singletonList(operationalFuture);
}, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
} else if (update.getVpnState() == VpnInstanceOpDataEntry.VpnState.Created) {
final String vpnName = update.getVpnInstanceName();
String primaryRd = update.getVrfId();
if (!VpnUtil.isBgpVpn(vpnName, primaryRd)) {
return;
}
if (original == null) {
LOG.error("VpnOpStatusListener.update: vpn {} with RD {}. add() handler already called", vpnName, primaryRd);
return;
}
if (update.getVpnTargets() == null) {
LOG.error("VpnOpStatusListener.update: vpn {} with RD {} vpnTargets not ready", vpnName, primaryRd);
return;
}
Map<VpnTargetKey, VpnTarget> vpnTargetMap = update.getVpnTargets().getVpnTarget();
List<String> ertList = new ArrayList<>();
List<String> irtList = new ArrayList<>();
if (vpnTargetMap != null) {
for (VpnTarget vpnTarget : vpnTargetMap.values()) {
if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
ertList.add(vpnTarget.getVrfRTValue());
}
if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
irtList.add(vpnTarget.getVrfRTValue());
}
if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
ertList.add(vpnTarget.getVrfRTValue());
irtList.add(vpnTarget.getVrfRTValue());
}
}
} else {
LOG.error("VpnOpStatusListener.update: vpn target list is empty, cannot add BGP" + " VPN {} RD {}", vpnName, primaryRd);
return;
}
jobCoordinator.enqueueJob("VPN-" + update.getVpnInstanceName(), () -> {
// RD update case get only updated RD list
List<String> rds = update.getRd() != null ? new ArrayList<>(update.getRd()) : new ArrayList<>();
if (original.getRd() != null && original.getRd().size() != rds.size()) {
rds.removeAll(original.getRd());
}
rds.parallelStream().forEach(rd -> {
try {
List<String> importRTList = rd.equals(primaryRd) ? irtList : emptyList();
LOG.info("VpnOpStatusListener.update: updating BGPVPN for vpn {} with RD {}" + " Type is {}, IPtype is {}, iRT {}", vpnName, primaryRd, update.getType(), update.getIpAddressFamilyConfigured(), importRTList);
int ipValue = VpnUtil.getIpFamilyValueToRemove(original, update);
switch(ipValue) {
case 4:
bgpManager.deleteVrf(rd, false, AddressFamily.IPV4);
break;
case 6:
bgpManager.deleteVrf(rd, false, AddressFamily.IPV6);
break;
case 10:
bgpManager.deleteVrf(rd, false, AddressFamily.IPV4);
bgpManager.deleteVrf(rd, false, AddressFamily.IPV6);
break;
default:
break;
}
/* Update vrf entry with newly added RD list. VPN does not support for
* deleting existing RDs
*/
if (original.getRd().size() != update.getRd().size()) {
ipValue = VpnUtil.getIpFamilyValueToAdd(original, update);
switch(ipValue) {
case 4:
bgpManager.addVrf(rd, importRTList, ertList, AddressFamily.IPV4);
break;
case 6:
bgpManager.addVrf(rd, importRTList, ertList, AddressFamily.IPV6);
break;
case 10:
bgpManager.addVrf(rd, importRTList, ertList, AddressFamily.IPV4);
bgpManager.addVrf(rd, importRTList, ertList, AddressFamily.IPV6);
break;
default:
break;
}
}
} catch (RuntimeException e) {
LOG.error("VpnOpStatusListener.update: Exception when updating VRF to BGP for vpn {} rd {}", vpnName, rd, e);
}
});
return emptyList();
});
}
}
use of org.opendaylight.mdsal.binding.api.DataBroker in project netvirt by opendaylight.
the class VpnInterfaceManager method updateVpnInterfacesForUnProcessAdjancencies.
public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
String primaryRd = vpnUtil.getVpnRd(vpnName);
VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
if (vpnInstanceOpData == null || vpnInstanceOpData.getVpnToDpnList() == null) {
return;
}
List<VpnToDpnList> vpnToDpnLists = new ArrayList<>(vpnInstanceOpData.getVpnToDpnList().values());
if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
return;
}
LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
vpnToDpnLists.forEach(vpnToDpnList -> {
if (vpnToDpnList.getVpnInterfaces() == null) {
return;
}
vpnToDpnList.nonnullVpnInterfaces().values().forEach(vpnInterface -> {
try {
InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
if (!vpnInterfaceOptional.isPresent()) {
return;
}
List<Adjacency> configVpnAdjacencies = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(vpnInterface.getInterfaceName());
if (configVpnAdjacencies == null) {
LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
return;
}
List<Adjacency> operationVpnAdjacencies = new ArrayList<>(vpnInterfaceOptional.get().augmentation(AdjacenciesOp.class).nonnullAdjacency().values());
// Due to insufficient rds, some of the extra route wont get processed when it is added.
// The unprocessed adjacencies will be present in config vpn interface DS but will be missing
// in operational DS. These unprocessed adjacencies will be handled below.
// To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in
// operational DS are retrieved which is used to call addNewAdjToVpnInterface method.
configVpnAdjacencies.stream().filter(adjacency -> operationVpnAdjacencies.stream().noneMatch(operationalAdjacency -> Objects.equals(operationalAdjacency.getIpAddress(), adjacency.getIpAddress()))).forEach(adjacency -> {
LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(), () -> {
// if the oper tx goes in
if (vpnUtil.isAdjacencyEligibleToVpn(adjacency, vpnName)) {
List<ListenableFuture<?>> futures = new ArrayList<>();
futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
// set of prefix used, as entry in prefix-to-interface datastore
// is prerequisite for refresh Fib to avoid race condition leading
// to missing remote next hop in bucket actions on bgp-vpn delete
Set<String> prefixListForRefreshFib = new HashSet<>();
ListenableFuture<?> configTxFuture = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd, adjacency, vpnInterfaceOptional.get().getDpnId(), operTx, confTx, confTx, prefixListForRefreshFib));
Futures.addCallback(configTxFuture, new VpnInterfaceCallBackHandler(primaryRd, prefixListForRefreshFib), MoreExecutors.directExecutor());
futures.add(configTxFuture);
}));
return futures;
} else {
return emptyList();
}
});
});
} catch (InterruptedException | ExecutionException e) {
LOG.error("updateVpnInterfacesForUnProcessAdjancencies: Failed to read data store for vpn {} rd {}", vpnName, primaryRd);
}
});
});
}
use of org.opendaylight.mdsal.binding.api.DataBroker in project netvirt by opendaylight.
the class IVpnLinkServiceImpl method leakRoute.
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
private void leakRoute(InterVpnLinkDataComposite interVpnLink, String vpnName, String prefix, List<String> nextHopList, Uint32 label, int addOrRemove) {
String dstVpnName = interVpnLink.getOtherVpnName(vpnName);
LOG.trace("leakingRoute: from VPN={} to VPN={}: prefix={} nhList={} label={}", vpnName, dstVpnName, prefix, nextHopList, label);
// For leaking, we need the InterVpnLink to be active.
if (addOrRemove == NwConstants.ADD_FLOW && !interVpnLink.isActive()) {
LOG.warn("Cannot leak route [prefix={}, label={}] from VPN {} to VPN {} because " + "InterVpnLink {} is not active", prefix, label, vpnName, dstVpnName, interVpnLink.getInterVpnLinkName());
return;
}
String dstVpnRd = vpnUtil.getVpnRd(dstVpnName);
if (addOrRemove == NwConstants.ADD_FLOW) {
LOG.debug("Leaking route (prefix={}, nexthop={}) from Vpn={} to Vpn={} (RD={})", prefix, nextHopList, vpnName, dstVpnName, dstVpnRd);
String key = dstVpnRd + VpnConstants.SEPARATOR + prefix;
Uint32 leakedLabel = vpnUtil.getUniqueId(VpnConstants.VPN_IDPOOL_NAME, key);
String leakedNexthop = interVpnLink.getEndpointIpAddr(vpnName);
fibManager.addOrUpdateFibEntry(dstVpnRd, null, /*macAddress*/
prefix, Collections.singletonList(leakedNexthop), VrfEntry.EncapType.Mplsgre, leakedLabel, Uint32.ZERO, /*l3vni*/
null, /*gatewayMacAddress*/
null, /*parentVpnRd*/
RouteOrigin.INTERVPN, null);
List<String> ivlNexthops = interVpnLink.getEndpointDpnsByVpnName(dstVpnName).stream().map(dpnId -> InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId)).collect(Collectors.toList());
try {
bgpManager.advertisePrefix(dstVpnRd, null, /*macAddress*/
prefix, ivlNexthops, VrfEntry.EncapType.Mplsgre, leakedLabel, Uint32.ZERO, /*l3vni*/
Uint32.ZERO, /*l2vni*/
null);
} catch (Exception e) {
LOG.error("Exception while advertising prefix {} on vpnRd {} for intervpn link", prefix, dstVpnRd, e);
}
} else {
LOG.debug("Removing leaked route to {} from VPN {}", prefix, dstVpnName);
fibManager.removeFibEntry(dstVpnRd, prefix, null, null);
bgpManager.withdrawPrefix(dstVpnRd, prefix);
}
}
use of org.opendaylight.mdsal.binding.api.DataBroker in project netvirt by opendaylight.
the class RouterDpnChangeListener method remove.
@Override
public void remove(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList dpnInfo) {
LOG.trace("remove : key: {}, value: {}", dpnInfo.key(), dpnInfo);
final String routerUuid = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
Uint32 routerId = NatUtil.getVpnId(dataBroker, routerUuid);
if (routerId == NatConstants.INVALID_ID) {
LOG.error("REMOVE: Invalid routId returned for routerName {}", routerUuid);
return;
}
Uint64 dpnId = dpnInfo.getDpnId();
// check router is associated to external network
InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerUuid);
Optional<Routers> routerData = SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
if (routerData.isPresent()) {
Routers router = routerData.get();
Uuid networkId = router.getNetworkId();
if (networkId != null) {
if (natMode == NatMode.Conntrack) {
Uint64 naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, router.getRouterName());
if (naptSwitch == null || naptSwitch.equals(Uint64.ZERO)) {
LOG.warn("remove : NAPT switch is not selected.");
return;
}
// If it is for NAPT switch skip as the flows would be already programmed.
if (naptSwitch.equals(dpnId)) {
LOG.debug("Skipping the notification recived for NAPT switch {}", routerUuid);
return;
}
LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
natServiceManager.notify(confTx, router, null, naptSwitch, dpnId, SnatServiceManager.Action.CNT_ROUTER_DISBL);
if (router.isEnableSnat()) {
natServiceManager.notify(confTx, router, null, naptSwitch, naptSwitch, SnatServiceManager.Action.SNAT_ROUTER_DISBL);
}
}), LOG, "Error notifying NAT service manager");
} else {
coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerUuid, () -> {
LOG.debug("remove : Router {} is associated with ext nw {}", routerUuid, networkId);
Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerUuid);
return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
Uint32 vpnId;
if (vpnName == null) {
LOG.debug("remove : Internal vpn associated to router {}", routerUuid);
vpnId = routerId;
if (vpnId == NatConstants.INVALID_ID) {
LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
return;
}
LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
// Remove default entry in FIB
LOG.debug("remove : Removing default route in FIB on dpn {} ...", dpnId);
snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, confTx);
} else {
LOG.debug("remove : External vpn associated to router {}", routerUuid);
vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
if (vpnId == NatConstants.INVALID_ID) {
LOG.error("remove : Invalid vpnId returned for routerName {}", routerUuid);
return;
}
LOG.debug("remove : Retrieved vpnId {} for router {}", vpnId, routerUuid);
// Remove default entry in FIB
LOG.debug("remove : Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
snatDefaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId, routerId, confTx);
}
/* remove V6 internet default fallback rule in FIB_TABLE if router
* is having V6 subnet
*/
Uuid internetVpnId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
if (internetVpnId != null) {
nvpnManager.programV6InternetFallbackFlow(new Uuid(routerUuid), internetVpnId, NwConstants.DEL_FLOW);
}
if (router.isEnableSnat()) {
ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerUuid, networkId);
if (extNwProvType == null) {
return;
}
LOG.info("remove : SNAT enabled for router {}", routerUuid);
String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, routerData.get().getNetworkId());
NatUtil.removeSNATFromDPN(dataBroker, mdsalManager, idManager, naptSwitchHA, dpnId, router, routerId, vpnId, externalVpnName, extNwProvType, confTx);
} else {
LOG.info("remove : SNAT is not enabled for router {} to handle removeDPN event {}", routerUuid, dpnId);
}
}));
}, NatConstants.NAT_DJC_MAX_RETRIES);
}
// end of controller based SNAT
}
}
}
use of org.opendaylight.mdsal.binding.api.DataBroker in project netvirt by opendaylight.
the class NatVpnMapsChangeListener method onRouterDisassociatedFromVpn.
/**
* router disassociation from vpn.
*/
public void onRouterDisassociatedFromVpn(String vpnName, String routerName) {
// check router is associated to external network
String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
if (extNetwork != null) {
try {
LOG.debug("onRouterDisassociatedFromVpn : Router {} is associated with ext nw {}", routerName, extNetwork);
handleDNATConfigurationForRouterDisassociation(routerName, vpnName, extNetwork);
Uuid extNetworkUuid = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
if (extNetworkUuid == null) {
LOG.error("onRouterDisassociatedFromVpn : Unable to retrieve external network Uuid for router {}", routerName);
return;
}
ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, extNetworkUuid);
if (extNwProvType == null) {
LOG.error("onRouterDisassociatedFromVpn : External Network Provider Type missing");
return;
}
Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, routerId, extNetwork, vpnName, tx, extNwProvType)).get();
} catch (InterruptedException | ExecutionException e) {
LOG.error("Error changing BGP VPN identifier to local VPN identifier", e);
}
} else {
LOG.debug("onRouterDisassociatedFromVpn : Ignoring the Router {} association with VPN {} " + "since it is not external router", routerName, vpnName);
}
}
Aggregations