+ }
+
+ private List<ListenableFuture<Void>> updateVpnInstanceAdjChange(VpnInterface original, VpnInterface update,
+ String vpnInterfaceName,
+ List<ListenableFuture<Void>> futures) {
+ final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
+ final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
+ != null ? origAdjs.getAdjacency() : new ArrayList<>();
+ final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
+ final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
+ != null ? updateAdjs.getAdjacency() : new ArrayList<>();
+
+ final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
+ for (VpnInstanceNames vpnInterfaceVpnInstance : update.nonnullVpnInstanceNames()) {
+ String newVpnName = vpnInterfaceVpnInstance.getVpnName();
+ List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
+ List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
+ String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
+ if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
+ // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
+ //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<Void> configTxFuture = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+ confTx -> futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(OPERATIONAL,
+ operTx -> {
+ InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
+ VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
+ LOG.info("VPN Interface update event-intfName {} onto vpnName {} running config-driven",
+ update.getName(), newVpnName);
+ //handle both addition and removal of adjacencies
+ // currently, new adjacency may be an extra route
+ boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
+ if (!oldAdjs.equals(newAdjs)) {
+ for (Adjacency adj : copyNewAdjs) {
+ if (copyOldAdjs.contains(adj)) {
+ copyOldAdjs.remove(adj);
+ } else {
+ // add new adjacency
+ if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+ addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
+ dpnId, operTx, confTx, confTx, prefixListForRefreshFib);
+ }
+ LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} "
+ + " added to vpn interface {} on vpn {} dpnId {}",
+ adj.getIpAddress(), adj.getNextHopIpList(), adj.getLabel(),
+ adj.getSubnetId(), update.getName(), newVpnName, dpnId);
+ }
+ }
+ for (Adjacency adj : copyOldAdjs) {
+ if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
+ if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
+ && !adj.isPhysNetworkFunc()) {
+ delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId, operTx,
+ confTx);
+ //remove FIB entry
+ String vpnRd = vpnUtil.getVpnRd(newVpnName);
+ LOG.debug("update: remove prefix {} from the FIB and BGP entry "
+ + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
+ //remove BGP entry
+ fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
+ if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
+ bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
+ }
+ } else {
+ delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
+ operTx, confTx);
+ }
+ }
+ LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
+ + " vpn interface {} on vpn {}", adj.getIpAddress(), adj.getNextHopIpList(),
+ adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
+ }
+ }
+ })));
+ Futures.addCallback(configTxFuture, new VpnInterfaceCallBackHandler(primaryRd, prefixListForRefreshFib),
+ MoreExecutors.directExecutor());
+ futures.add(configTxFuture);
+ for (ListenableFuture<Void> future : futures) {
+ ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
+ update.getName(), update.getVpnInstanceNames());
+ }
+ } else {
+ LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
+ + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
+ }
+ }
+ return futures;