2 * Copyright (c) 2016 - 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.vpnmanager;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Iterators;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.MoreExecutors;
17 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.List;
24 import java.util.Objects;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentLinkedQueue;
27 import java.util.function.Consumer;
28 import java.util.function.Predicate;
29 import java.util.stream.Collectors;
30 import javax.annotation.PostConstruct;
31 import javax.annotation.PreDestroy;
32 import javax.inject.Inject;
33 import javax.inject.Singleton;
34 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
35 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
36 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
37 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
38 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
39 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
40 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
41 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
42 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
43 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
44 import org.opendaylight.genius.mdsalutil.NWUtil;
45 import org.opendaylight.genius.mdsalutil.NwConstants;
46 import org.opendaylight.genius.mdsalutil.cache.InstanceIdDataObjectCache;
47 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
48 import org.opendaylight.infrautils.caches.CacheProvider;
49 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
50 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
51 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
52 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
53 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
54 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
55 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
56 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
57 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
58 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderHandler;
59 import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput;
60 import org.opendaylight.netvirt.vpnmanager.populator.intfc.VpnPopulator;
61 import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
106 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
107 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
108 import org.slf4j.Logger;
109 import org.slf4j.LoggerFactory;
112 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager> {
114 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
115 private static final short DJC_MAX_RETRIES = 3;
117 private final DataBroker dataBroker;
118 private final ManagedNewTransactionRunner txRunner;
119 private final IBgpManager bgpManager;
120 private final IFibManager fibManager;
121 private final IMdsalApiManager mdsalManager;
122 private final IdManagerService idManager;
123 private final OdlInterfaceRpcService ifaceMgrRpcService;
124 private final VpnFootprintService vpnFootprintService;
125 private final IInterfaceManager interfaceManager;
126 private final IVpnManager vpnManager;
127 private final ArpResponderHandler arpResponderHandler;
128 private final JobCoordinator jobCoordinator;
129 private final VpnUtil vpnUtil;
131 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
133 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
134 new ConcurrentHashMap<>();
136 private final InstanceIdDataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
139 public VpnInterfaceManager(final DataBroker dataBroker,
140 final IBgpManager bgpManager,
141 final IdManagerService idManager,
142 final IMdsalApiManager mdsalManager,
143 final IFibManager fibManager,
144 final OdlInterfaceRpcService ifaceMgrRpcService,
145 final VpnFootprintService vpnFootprintService,
146 final IInterfaceManager interfaceManager,
147 final IVpnManager vpnManager,
148 final ArpResponderHandler arpResponderHandler,
149 final JobCoordinator jobCoordinator,
150 final CacheProvider cacheProvider,
151 final VpnUtil vpnUtil) {
152 super(VpnInterface.class, VpnInterfaceManager.class);
154 this.dataBroker = dataBroker;
155 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
156 this.bgpManager = bgpManager;
157 this.idManager = idManager;
158 this.mdsalManager = mdsalManager;
159 this.fibManager = fibManager;
160 this.ifaceMgrRpcService = ifaceMgrRpcService;
161 this.vpnFootprintService = vpnFootprintService;
162 this.interfaceManager = interfaceManager;
163 this.vpnManager = vpnManager;
164 this.arpResponderHandler = arpResponderHandler;
165 this.jobCoordinator = jobCoordinator;
166 this.vpnUtil = vpnUtil;
168 vpnInstanceOpDataEntryCache = new InstanceIdDataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
169 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
170 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
173 public Runnable isNotifyTaskQueued(String intfName) {
174 return vpnIntfMap.remove(intfName);
178 public void start() {
179 LOG.info("{} start", getClass().getSimpleName());
180 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
185 public void close() {
187 vpnInstanceOpDataEntryCache.close();
191 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
192 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
196 protected VpnInterfaceManager getDataTreeChangeListener() {
197 return VpnInterfaceManager.this;
201 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
202 LOG.info("add: intfName {} onto vpnName {}",
203 vpnInterface.getName(),
204 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
205 addVpnInterface(identifier, vpnInterface, null, null);
208 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
209 final VpnInterface vpnInterface, String vpnName) {
210 synchronized (vpnName.intern()) {
211 if (isVpnInstanceReady(vpnName)) {
214 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
219 // TODO Clean up the exception handling
220 @SuppressWarnings("checkstyle:IllegalCatch")
221 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
222 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
223 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
224 String vpnName = vpnInterfaceVpnInstance.getVpnName();
225 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
229 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
230 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
231 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
232 final String interfaceName = key.getName();
234 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
235 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
236 vpnName, vpnInterface.getName());
239 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
240 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
241 List<Adjacency> copyOldAdjs = null;
242 if (oldAdjs != null) {
243 copyOldAdjs = new ArrayList<>();
244 copyOldAdjs.addAll(oldAdjs);
246 List<Adjacency> copyNewAdjs = null;
247 if (newAdjs != null) {
248 copyNewAdjs = new ArrayList<>();
249 copyNewAdjs.addAll(newAdjs);
251 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
254 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
255 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
256 final List<Adjacency> newAdjs,
257 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
258 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
259 final String interfaceName = key.getName();
260 String primaryRd = vpnUtil.getPrimaryRd(vpnName);
261 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
262 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
263 boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
264 if (interfaceState != null) {
266 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
267 final int ifIndex = interfaceState.getIfIndex();
268 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName, () -> {
269 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
270 // (the inventory tx goes in last)
271 List<ListenableFuture<Void>> futures = new ArrayList<>();
272 ListenableFuture<Void> confFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
273 confTx -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
274 operTx -> futures.add(
275 txRunner.callWithNewWriteOnlyTransactionAndSubmit(invTx -> {
277 "addVpnInterface: VPN Interface add event - intfName {} vpnName {}"
279 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
280 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false,
281 confTx, operTx, invTx, interfaceState, vpnName);
282 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
283 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
284 + " Update for swapping VPN {} case.", interfaceName, vpnName);
285 if (newAdjs != null) {
286 for (Adjacency adj : newAdjs) {
287 if (oldAdjs.contains(adj)) {
290 if (!isBgpVpnInternetVpn
291 || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
292 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier,
293 primaryRd, adj, dpnId, operTx, confTx);
298 for (Adjacency adj : oldAdjs) {
299 if (!isBgpVpnInternetVpn
300 || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
301 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
307 futures.add(confFuture);
308 Futures.addCallback(confFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"),
309 MoreExecutors.directExecutor());
310 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
311 + " processed successfully", interfaceName, vpnName, dpnId);
314 } catch (NumberFormatException | IllegalStateException e) {
315 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
316 + "interface {}. Interface addition on vpn {} failed", interfaceName,
320 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
321 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(),
323 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
324 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
326 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
327 vpnName, vpnInterface.getDpnId());
329 ListenableFutures.addErrorLogging(future, LOG,
330 "Error creating FIB entry for interface {} on VPN {}", vpnInterface.getName(), vpnName);
331 return Collections.singletonList(future);
334 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
335 + " is not available", interfaceName, vpnName);
338 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
339 + " as vpn is pending delete", interfaceName, vpnName,
340 vpnInterface.getDpnId());
344 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
345 // see comments below.
346 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
347 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
348 final int lportTag, boolean isInterfaceUp,
349 WriteTransaction writeConfigTxn,
350 WriteTransaction writeOperTxn,
351 WriteTransaction writeInvTxn,
352 Interface interfaceState,
353 final String vpnName) {
354 final String interfaceName = vpnInterface.getName();
355 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(interfaceName,
357 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
358 boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
359 if (!isInterfaceUp) {
360 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
361 interfaceName, dpId, vpnName);
362 long vpnId = vpnUtil.getVpnId(vpnName);
363 if (vpnId == VpnConstants.INVALID_ID) {
364 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
365 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
370 boolean waitForVpnInterfaceOpRemoval = false;
371 if (opVpnInterface != null) {
372 String opVpnName = opVpnInterface.getVpnInstanceName();
373 String primaryInterfaceIp = null;
374 if (opVpnName.equals(vpnName)) {
375 // Please check if the primary VRF Entry does not exist for VPNInterface
376 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
378 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
379 List<Adjacency> adjs = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(interfaceName);
381 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
382 + " for this vpn interface could not be obtained", interfaceName, dpId,
386 for (Adjacency adj : adjs) {
387 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
388 primaryInterfaceIp = adj.getIpAddress();
392 if (primaryInterfaceIp == null) {
393 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
394 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
398 // Get the rd of the vpn instance
399 VrfEntry vrf = vpnUtil.getVrfEntry(primaryRd, primaryInterfaceIp);
401 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
402 + " bailing out from here.", interfaceName, dpId, vpnName);
405 waitForVpnInterfaceOpRemoval = true;
407 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
408 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
411 if (!waitForVpnInterfaceOpRemoval) {
412 // Add the VPNInterface and quit
413 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
414 null/*ipAddressSourceValuePair*/,
416 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
417 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
418 if (!isBgpVpnInternetVpn) {
419 vpnUtil.bindService(vpnName, interfaceName, false /*isTunnelInterface*/);
421 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
423 if (interfaceManager.isExternalInterface(interfaceName)) {
424 processExternalVpnInterface(interfaceName, vpnName, dpId, lportTag,
425 NwConstants.ADD_FLOW);
430 // FIB didn't get a chance yet to clean up this VPNInterface
431 // Let us give it a chance here !
432 LOG.info("processVpnInterfaceUp: Trying to add VPN Interface {} on dpn {} for vpn {},"
433 + " but waiting for FIB to clean up! ", interfaceName, dpId, vpnName);
435 Runnable notifyTask = new VpnNotifyTask();
436 synchronized (notifyTask) {
437 // Per FB's "Unconditional wait" violation, the code should really verify that the condition it
438 // intends to wait for is not already satisfied before calling wait. However the VpnNotifyTask is
439 // published here while holding the lock on it so this path will hit the wait before notify can be
441 vpnIntfMap.put(interfaceName, notifyTask);
443 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
444 } catch (InterruptedException e) {
449 vpnIntfMap.remove(interfaceName);
452 if (opVpnInterface != null) {
453 LOG.warn("processVpnInterfaceUp: VPN Interface {} removal on dpn {} for vpn {}"
454 + " by FIB did not complete on time," + " bailing addition ...", interfaceName,
456 vpnUtil.unsetScheduledToRemoveForVpnInterface(interfaceName);
459 // VPNInterface got removed, proceed with Add
460 LOG.info("processVpnInterfaceUp: Continuing to plumb vpn interface {} onto dpn {} for vpn {}",
461 interfaceName, dpId, vpnName);
462 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
463 null/*ipAddressSourceValuePair*/,
465 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
466 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
467 if (!isBgpVpnInternetVpn) {
468 vpnUtil.bindService(vpnName, interfaceName, false/*isTunnelInterface*/);
470 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
471 + " FIB to clean up", interfaceName, dpId, vpnName);
472 if (interfaceManager.isExternalInterface(interfaceName)) {
473 processExternalVpnInterface(interfaceName, vpnName, dpId,
474 lportTag, NwConstants.ADD_FLOW);
478 // Interface is retained in the DPN, but its Link Up.
479 // Advertise prefixes again for this interface to BGP
480 InstanceIdentifier<VpnInterface> identifier =
481 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName());
482 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
483 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
484 advertiseAdjacenciesForVpnToBgp(primaryRd, dpId, vpnInterfaceOpIdentifier, vpnName, interfaceName);
485 // Perform similar operation as interface add event for extraroutes.
486 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
487 Optional<Adjacencies> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
488 LogicalDatastoreType.CONFIGURATION, path);
489 if (!optAdjacencies.isPresent()) {
490 LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
493 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
494 for (Adjacency adjacency : adjacencies) {
495 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
498 // if BGPVPN Internet, filter only IPv6 Adjacencies
499 if (isBgpVpnInternetVpn && !vpnUtil.isAdjacencyEligibleToVpnInternet(adjacency)) {
502 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
503 dpId, writeOperTxn, writeConfigTxn);
505 } catch (ReadFailedException e) {
506 LOG.error("processVpnInterfaceUp: Failed to read data store for interface {} vpn {} rd {} dpn {}",
507 interfaceName, vpnName, primaryRd, dpId);
512 private void processExternalVpnInterface(String interfaceName, String vpnName, BigInteger dpId,
513 int lportTag, int addOrRemove) {
516 // vpn instance of ext-net interface is the network-id
517 extNetworkId = new Uuid(vpnName);
518 } catch (IllegalArgumentException e) {
519 LOG.error("processExternalVpnInterface: VPN instance {} is not Uuid. Processing external vpn interface {}"
520 + " on dpn {} failed", vpnName, interfaceName, dpId);
524 List<Uuid> routerIds = vpnUtil.getExternalNetworkRouterIds(extNetworkId);
525 if (routerIds == null || routerIds.isEmpty()) {
526 LOG.info("processExternalVpnInterface: No router is associated with {}."
527 + " Bailing out of processing external vpn interface {} on dpn {} for vpn {}",
528 extNetworkId.getValue(), interfaceName, dpId, vpnName);
532 LOG.info("processExternalVpnInterface: Router-ids {} associated with exernal vpn-interface {} on dpn {}"
533 + " for vpn {}", routerIds, interfaceName, dpId, vpnName);
534 for (Uuid routerId : routerIds) {
535 String routerName = routerId.getValue();
536 BigInteger primarySwitch = vpnUtil.getPrimarySwitchForRouter(routerName);
537 if (Objects.equals(primarySwitch, dpId)) {
538 Routers router = vpnUtil.getExternalRouter(routerName);
539 if (router != null) {
540 if (addOrRemove == NwConstants.ADD_FLOW) {
541 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
542 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
543 dpId, interfaceName, lportTag);
545 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
546 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
547 dpId, interfaceName, lportTag);
550 LOG.error("processExternalVpnInterface: No external-router found for router-id {}. Bailing out of"
551 + " processing external vpn-interface {} on dpn {} for vpn {}", routerName,
552 interfaceName, dpId, vpnName);
558 // TODO Clean up the exception handling
559 @SuppressWarnings("checkstyle:IllegalCatch")
560 private void advertiseAdjacenciesForVpnToBgp(final String rd, BigInteger dpnId,
561 final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
562 String vpnName, String interfaceName) {
564 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} on dpn {} in vpn {}",
565 interfaceName, dpnId, vpnName);
568 if (rd.equals(vpnName)) {
569 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} on dpn {}"
570 + " as it is in internal vpn{} with rd {}", interfaceName, dpnId, vpnName, rd);
574 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} on dpn {} in vpn {} with rd {} ",
575 interfaceName, dpnId, vpnName, rd);
577 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
578 if (nextHopIp == null) {
579 LOG.error("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} on dpn {} is null,"
580 + " returning from advertising route with rd {} vpn {} to bgp", interfaceName, dpnId,
587 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
588 Optional<AdjacenciesOp> adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
589 LogicalDatastoreType.OPERATIONAL, path);
590 if (adjacencies.isPresent()) {
591 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
592 if (!nextHops.isEmpty()) {
593 LOG.debug("advertiseAdjacenciesForVpnToBgp: NextHops are {} for interface {} on dpn {} for vpn {}"
594 + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
595 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(rd);
596 long l3vni = vpnInstanceOpData.getL3vni();
597 VrfEntry.EncapType encapType = VpnUtil.isL3VpnOverVxLan(l3vni)
598 ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
599 for (Adjacency nextHop : nextHops) {
600 if (nextHop.getAdjacencyType() == AdjacencyType.ExtraRoute) {
603 String gatewayMac = null;
605 if (VpnUtil.isL3VpnOverVxLan(l3vni)) {
606 final VpnPortipToPort gwPort = vpnUtil.getNeutronPortFromVpnPortFixedIp(
607 vpnInstanceOpData.getVpnInstanceName(), nextHop.getIpAddress());
608 gatewayMac = arpResponderHandler.getGatewayMacAddressForInterface(gwPort, interfaceName)
611 label = nextHop.getLabel();
614 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Adding Fib Entry rd {} prefix {}"
615 + " nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
616 bgpManager.advertisePrefix(rd, nextHop.getMacAddress(), nextHop.getIpAddress(), nextHopIp,
617 encapType, (int)label, l3vni, 0 /*l2vni*/,
619 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Added Fib Entry rd {} prefix {}"
620 + " nexthop {} label {} for interface {} on dpn {} for vpn {}", rd,
621 nextHop.getIpAddress(), nextHopIp, label, interfaceName, dpnId, vpnName);
622 } catch (Exception e) {
623 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to advertise prefix {} in vpn {}"
624 + " with rd {} for interface {} on dpn {}", nextHop.getIpAddress(), vpnName, rd,
625 interfaceName, dpnId, e);
630 } catch (ReadFailedException e) {
631 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to read data store for interface {} dpn {} nexthop {}"
632 + "vpn {} rd {}", interfaceName, dpnId, nextHopIp, vpnName, rd);
636 // TODO Clean up the exception handling
637 @SuppressWarnings("checkstyle:IllegalCatch")
638 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
639 String vpnName, String interfaceName, WriteTransaction writeConfigTxn,
640 WriteTransaction writeOperTx) {
642 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
643 String rd = vpnUtil.getVpnRd(interfaceName);
645 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
646 interfaceName, vpnName);
649 if (rd.equals(vpnName)) {
651 "withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in "
652 + "internal vpn{} with rd {}", interfaceName, vpnName, rd);
656 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", interfaceName,
658 Optional<AdjacenciesOp> adjacencies = Optional.absent();
660 adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
662 } catch (ReadFailedException e) {
663 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to read data store for interface {} vpn {}",
664 interfaceName, vpnName);
666 if (adjacencies.isPresent()) {
667 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
669 if (!nextHops.isEmpty()) {
670 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
671 nextHops, interfaceName, vpnName, rd);
672 for (Adjacency nextHop : nextHops) {
674 if (nextHop.getAdjacencyType() != AdjacencyType.ExtraRoute) {
675 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removing Fib Entry rd {}"
676 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
677 interfaceName, vpnName);
678 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
679 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removed Fib Entry rd {}"
680 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
681 interfaceName, vpnName);
683 // Perform similar operation as interface delete event for extraroutes.
684 String allocatedRd = nextHop.getVrfId();
685 for (String nh : nextHop.getNextHopIpList()) {
686 deleteExtraRouteFromCurrentAndImportingVpns(
687 vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn,
691 } catch (Exception e) {
692 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
693 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
700 @SuppressWarnings("checkstyle:IllegalCatch")
701 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
702 String primaryRd, String interfaceName, final long vpnId,
703 WriteTransaction writeConfigTxn,
704 WriteTransaction writeOperTxn,
705 final WriteTransaction writeInvTxn,
706 Interface interfaceState) {
707 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
709 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
710 Optional<Adjacencies> adjacencies = Optional.absent();
712 adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
714 } catch (ReadFailedException e) {
715 LOG.error("processVpnInterfaceAdjacencies: Failed to read data store for interface {} vpn {} rd {}"
716 + "dpn {}", interfaceName, vpnName, primaryRd, dpnId);
718 if (!adjacencies.isPresent()) {
719 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
720 null/*gwMac*/, writeOperTxn);
723 // Get the rd of the vpn instance
724 String nextHopIp = null;
726 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
727 } catch (Exception e) {
728 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
729 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
731 List<String> nhList = new ArrayList<>();
732 if (nextHopIp != null) {
733 nhList.add(nextHopIp);
734 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
735 interfaceName, dpnId, vpnName, nhList);
737 Optional<String> gwMac = Optional.absent();
738 String vpnInterfaceSubnetGwMacAddress = null;
739 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
740 Long l3vni = vpnInstanceOpData.getL3vni();
741 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
742 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
743 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
744 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
745 List<Adjacency> value = new ArrayList<>();
746 for (Adjacency nextHop : nextHops) {
747 String rd = primaryRd;
748 String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
749 if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
750 && NWUtil.isIpv4Address(nexthopIpValue)) {
751 String prefix = nextHop.getIpAddress() == null ? "null" :
752 VpnUtil.getIpPrefix(nextHop.getIpAddress());
753 LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
754 + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
757 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
758 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
759 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
760 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
761 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
762 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
764 LogicalDatastoreType.OPERATIONAL,
765 VpnUtil.getPrefixToInterfaceIdentifier(
766 vpnUtil.getVpnId(vpnName), prefix),
767 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
769 final Uuid subnetId = nextHop.getSubnetId();
771 String gatewayIp = nextHop.getSubnetGatewayIp();
772 if (gatewayIp == null) {
773 Optional<String> gatewayIpOptional = vpnUtil.getVpnSubnetGatewayIp(subnetId);
774 if (gatewayIpOptional.isPresent()) {
775 gatewayIp = gatewayIpOptional.get();
779 if (gatewayIp != null) {
780 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
781 if (gwMac.isPresent()) {
782 // A valid mac-address is available for this subnet-gateway-ip
783 // Use this for programming ARP_RESPONDER table here. And save this
784 // info into vpnInterface operational, so it can used in VrfEntryProcessor
785 // to populate L3_GW_MAC_TABLE there.
786 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
787 gatewayIp, gwMac.get());
788 vpnInterfaceSubnetGwMacAddress = gwMac.get();
790 // A valid mac-address is not available for this subnet-gateway-ip
791 // Use the connected-mac-address to configure ARP_RESPONDER Table.
792 // Save this connected-mac-address as gateway-mac-address for the
793 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
794 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
795 if (gwMac.isPresent()) {
796 vpnUtil.setupGwMacIfExternalVpn(dpnId, interfaceName, vpnId, writeInvTxn,
797 NwConstants.ADD_FLOW, gwMac.get());
798 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
799 gatewayIp, gwMac.get());
801 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
802 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
804 subnetId, interfaceName, vpnName, gatewayIp);
808 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
809 + "cannot create ARP responder flow for interface name {}, vpnName {}",
810 subnetId, interfaceName, vpnName);
811 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
813 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
814 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
816 //Extra route adjacency
817 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
818 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
819 synchronized (vpnPrefixKey.intern()) {
820 java.util.Optional<String> rdToAllocate = vpnUtil
821 .allocateRdForExtraRouteAndUpdateUsedRdsMap(vpnId, null, prefix, vpnName,
822 nextHop.getNextHopIpList().get(0), dpnId);
823 if (rdToAllocate.isPresent()) {
824 rd = rdToAllocate.get();
825 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
828 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
832 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
833 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
834 interfaceName, dpnId);
836 // Please note that primary adjacency will use a subnet-gateway-mac-address that
837 // can be different from the gateway-mac-address within the VRFEntry as the
838 // gateway-mac-address is a superset.
839 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
840 : RouteOrigin.STATIC;
841 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
842 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
843 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
844 Adjacency operationalAdjacency = null;
846 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
847 } catch (NullPointerException e) {
848 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
849 input, e.getMessage());
852 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
853 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
854 vpnName, l3vni, origin,
855 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
857 value.add(operationalAdjacency);
860 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
861 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
862 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
864 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
865 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
866 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
868 for (Adjacency nextHop : aug.getAdjacency()) {
869 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
870 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
871 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
872 : RouteOrigin.STATIC;
873 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
874 registeredPopulator.populateFib(input, writeConfigTxn);
879 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
880 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
881 VpnInterfaceOpDataEntry opInterface =
882 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, lportTag, gwMac);
883 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
884 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
885 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
886 WriteTransaction.CREATE_MISSING_PARENTS);
887 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
888 interfaceName, dpnId, vpnName);
891 // TODO Clean up the exception handling
892 @SuppressWarnings("checkstyle:IllegalCatch")
893 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
894 StateTunnelList stateTunnelList,
895 WriteTransaction writeConfigTxn,
896 WriteTransaction writeOperTxn) {
898 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
899 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
900 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
901 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
902 if (adjList.isEmpty()) {
903 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
904 vpnInterface, srcDpnId);
907 String prefix = null;
909 List<Adjacency> value = new ArrayList<>();
910 boolean isNextHopAddReqd = false;
911 String vpnName = vpnInterface.getVpnInstanceName();
912 long vpnId = vpnUtil.getVpnId(vpnName);
913 String primaryRd = vpnUtil.getPrimaryRd(vpnName);
914 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
915 vpnInterface.getName(), vpnInterface.getDpnId(),
916 vpnInterface.getVpnInstanceName(), adjList);
917 for (Adjacency adj : adjList) {
918 String rd = adj.getVrfId();
919 rd = rd != null ? rd : vpnName;
920 prefix = adj.getIpAddress();
921 label = adj.getLabel();
922 List<String> nhList = Collections.singletonList(srcTepIp);
923 List<String> nextHopList = adj.getNextHopIpList();
924 // If TEP is added , update the nexthop of primary adjacency.
925 // Secondary adj nexthop is already pointing to primary adj IP address.
926 if (nextHopList != null && !nextHopList.isEmpty()) {
927 /* everything right already */
929 isNextHopAddReqd = true;
932 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
933 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
935 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
936 if (!vrfEntryOptional.isPresent()) {
939 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
940 if (!nhList.contains(srcTepIp)) {
941 nhList.add(srcTepIp);
942 isNextHopAddReqd = true;
947 if (isNextHopAddReqd) {
948 updateLabelMapper(label, nhList);
949 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
950 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
951 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
952 // Update the VRF entry with nextHop
953 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
954 label, true, writeConfigTxn);
956 //Get the list of VPN's importing this route(prefix) .
957 // Then update the VRF entry with nhList
958 List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
959 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
960 String vpnRd = vpn.getVrfId();
962 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
963 srcTepIp, label, true, writeConfigTxn);
964 LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
965 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
966 vpnInterface.getName(), srcDpnId, vpnName,
967 vpn.getVpnInstanceName(), vpnRd);
970 // Advertise the prefix to BGP only for external vpn
971 // since there is a nexthop change.
973 if (!rd.equalsIgnoreCase(vpnName)) {
974 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, nhList,
975 VrfEntry.EncapType.Mplsgre, (int)label, 0 /*evi*/, 0 /*l2vni*/,
976 null /*gatewayMacAddress*/);
978 LOG.info("updateVpnInterfaceOnTepAdd: Advertised rd {} prefix {} nhList {} label {}"
979 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label, vpnInterface.getName(),
981 } catch (Exception ex) {
982 LOG.error("updateVpnInterfaceOnTepAdd: Exception when advertising prefix {} nh {} label {}"
983 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
984 vpnInterface.getName(), srcDpnId, vpnName, ex);
988 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
989 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
990 .withKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
991 .addAugmentation(AdjacenciesOp.class, aug).build();
992 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
993 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
994 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
995 WriteTransaction.CREATE_MISSING_PARENTS);
996 LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
997 vpnInterface.getName(), srcDpnId, vpnName);
1001 // TODO Clean up the exception handling
1002 @SuppressWarnings("checkstyle:IllegalCatch")
1003 public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
1004 StateTunnelList stateTunnelList,
1005 WriteTransaction writeConfigTxn,
1006 WriteTransaction writeOperTxn) {
1008 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
1009 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
1010 String prefix = null;
1012 boolean isNextHopRemoveReqd = false;
1013 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
1014 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
1015 String vpnName = vpnInterface.getVpnInstanceName();
1016 long vpnId = vpnUtil.getVpnId(vpnName);
1017 String primaryRd = vpnUtil.getVpnRd(vpnName);
1018 if (adjList != null) {
1019 List<Adjacency> value = new ArrayList<>();
1020 LOG.info("updateVpnInterfaceOnTepDelete: AdjacencyList for interface {} on dpn {} vpn {} is {}",
1021 vpnInterface.getName(), vpnInterface.getDpnId(),
1022 vpnInterface.getVpnInstanceName(), adjList);
1023 for (Adjacency adj : adjList) {
1024 List<String> nhList = new ArrayList<>();
1025 String rd = adj.getVrfId();
1026 rd = rd != null ? rd : vpnName;
1027 prefix = adj.getIpAddress();
1028 List<String> nextHopList = adj.getNextHopIpList();
1029 label = adj.getLabel();
1030 if (nextHopList != null && !nextHopList.isEmpty()) {
1031 isNextHopRemoveReqd = true;
1033 // If TEP is deleted , remove the nexthop from primary adjacency.
1034 // Secondary adj nexthop will continue to point to primary adj IP address.
1035 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1036 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
1038 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
1039 if (!vrfEntryOptional.isPresent()) {
1042 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
1043 if (nhList.contains(srcTepIp)) {
1044 nhList.remove(srcTepIp);
1045 isNextHopRemoveReqd = true;
1050 if (isNextHopRemoveReqd) {
1051 updateLabelMapper(label, nhList);
1052 LOG.info("updateVpnInterfaceOnTepDelete: Updated label mapper : label {} dpn {} prefix {}"
1053 + " nexthoplist {} vpn {} vpnid {} rd {} interface {}", label, srcDpnId,
1054 prefix, nhList, vpnName,
1055 vpnId, rd, vpnInterface.getName());
1056 // Update the VRF entry with removed nextHop
1057 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
1058 label, false, writeConfigTxn);
1060 //Get the list of VPN's importing this route(prefix) .
1061 // Then update the VRF entry with nhList
1062 List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
1063 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1064 String vpnRd = vpn.getVrfId();
1065 if (vpnRd != null) {
1066 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1067 srcTepIp, label, false, writeConfigTxn);
1068 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1069 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1070 nhList, label, vpnInterface.getName(), srcDpnId,
1072 vpn.getVpnInstanceName(), vpnRd);
1076 // Withdraw prefix from BGP only for external vpn.
1078 if (!rd.equalsIgnoreCase(vpnName)) {
1079 bgpManager.withdrawPrefix(rd, prefix);
1081 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1082 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1083 vpnInterface.getName(), srcDpnId,
1085 } catch (Exception ex) {
1086 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1087 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
1088 vpnInterface.getName(), srcDpnId, vpnName, ex);
1092 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1093 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1094 .withKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1095 .addAugmentation(AdjacenciesOp.class, aug).build();
1096 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1097 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1098 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1099 WriteTransaction.CREATE_MISSING_PARENTS);
1100 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1101 vpnInterface.getName(), srcDpnId, vpnName);
1105 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1106 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1108 String vpnRd = vpnUtil.getVpnRd(vpnName);
1109 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(vpnRd);
1110 if (vpnInstanceOpDataEntry == null) {
1111 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1112 + " to check for vpns exporting the routes", vpnName);
1113 return vpnsToExportRoute;
1116 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1117 if (input.getVpnInstanceName() == null) {
1118 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1122 return !input.getVpnInstanceName().equals(vpnName);
1125 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1126 Iterable<String> commonRTs =
1127 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1128 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1129 return Iterators.size(commonRTs.iterator()) > 0;
1133 vpnUtil.getAllVpnInstanceOpData().stream().filter(excludeVpn).filter(matchRTs).collect(
1134 Collectors.toList());
1135 return vpnsToExportRoute;
1138 // TODO Clean up the exception handling
1139 @SuppressWarnings("checkstyle:IllegalCatch")
1140 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1141 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1142 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1143 List<VrfEntry> vrfEntries = vpnUtil.getAllVrfEntries(vpn.getVrfId());
1144 if (vrfEntries != null) {
1145 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1146 for (VrfEntry vrfEntry : vrfEntries) {
1148 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1149 RouteOrigin.value(vrfEntry.getOrigin()))) {
1150 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1151 + " is not a controller managed non intervpn link route. Ignoring.",
1152 vpn.getVrfId(), vrfEntry.getDestPrefix());
1155 String prefix = vrfEntry.getDestPrefix();
1156 String gwMac = vrfEntry.getGatewayMacAddress();
1157 vrfEntry.getRoutePaths().forEach(routePath -> {
1158 String nh = routePath.getNexthopAddress();
1159 int label = routePath.getLabel().intValue();
1160 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1161 vrfEntry.getOrigin()))) {
1162 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1163 + " nexthop {} label {} to vpn {} vpnRd {}",
1164 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1165 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1166 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1167 0 /*l3vni*/, gwMac, vpn.getVrfId(), RouteOrigin.SELF_IMPORTED,
1170 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} "
1171 + "prefix {} nexthop {} label {} to vpn {} vpnRd {}",
1172 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1173 SubnetRoute route = vrfEntry.augmentation(SubnetRoute.class);
1174 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, vpn.getVrfId(),
1178 } catch (RuntimeException e) {
1179 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1180 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1181 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1184 }), LOG, "Error handing VPN exporting routes");
1186 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1187 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1193 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1194 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1195 final String interfaceName = key.getName();
1196 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1197 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1198 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1202 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1203 final VpnInterface vpnInterface, final String vpnName,
1204 final String interfaceName) {
1205 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1206 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
1207 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1208 deleteFibEntryForRouterInterface(vpnInterface, confTx, vpnName);
1209 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1211 ListenableFutures.addErrorLogging(future, LOG, "Error removing call for interface {} on VPN {}",
1212 vpnInterface.getName(), vpnName);
1213 return Collections.singletonList(future);
1214 }, DJC_MAX_RETRIES);
1216 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName);
1220 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1221 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1222 final VpnInterface vpnInterface, final String vpnName,
1223 final String interfaceName) {
1224 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1225 vpnName, vpnInterface.getDpnId());
1226 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1227 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1229 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1230 ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1231 writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1232 writeOperTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1233 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1234 interfaceName, vpnName);
1235 BigInteger dpId = BigInteger.ZERO;
1237 String gwMacAddress = null;
1238 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1239 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1240 Optional<VpnInterfaceOpDataEntry> optVpnInterface = Optional.absent();
1242 optVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1243 LogicalDatastoreType.OPERATIONAL, interfaceId);
1244 } catch (ReadFailedException e) {
1245 LOG.error("remove: Failed to read data store for interface {} vpn {}", interfaceName,
1249 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,
1251 if (interfaceState != null) {
1253 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1254 } catch (NumberFormatException | IllegalStateException e) {
1255 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1256 + " data store for interface {} on dpn {} for vpn {} Fetching"
1257 + " from vpn interface op data store. ", interfaceName,
1258 vpnInterface.getDpnId(), vpnName, e);
1259 dpId = BigInteger.ZERO;
1261 ifIndex = interfaceState.getIfIndex();
1262 gwMacAddress = interfaceState.getPhysAddress().getValue();
1264 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1265 + " from vpn interface op.", interfaceName);
1266 if (optVpnInterface.isPresent()) {
1267 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1268 dpId = vpnOpInterface.getDpnId();
1269 ifIndex = vpnOpInterface.getLportTag().intValue();
1270 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1272 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1273 + " as interfaceState and vpn interface op is not"
1274 + " available", interfaceName, vpnName);
1278 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1279 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1280 writeConfigTxn, writeOperTxn, writeInvTxn);
1282 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1284 interfaceName, vpnInterface.getDpnId(), vpnName);
1286 futures.add(configFuture);
1287 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1289 }, DJC_MAX_RETRIES);
1292 protected void processVpnInterfaceDown(BigInteger dpId,
1293 String interfaceName,
1296 VpnInterfaceOpDataEntry vpnOpInterface,
1297 boolean isInterfaceStateDown,
1298 WriteTransaction writeConfigTxn,
1299 WriteTransaction writeOperTxn,
1300 WriteTransaction writeInvTxn) {
1301 if (vpnOpInterface == null) {
1302 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1303 + " as it is not available in operational data store", interfaceName, dpId);
1306 final String vpnName = vpnOpInterface.getVpnInstanceName();
1307 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1308 interfaceName, vpnName);
1309 if (!isInterfaceStateDown) {
1310 final long vpnId = vpnUtil.getVpnId(vpnName);
1311 vpnUtil.scheduleVpnInterfaceForRemoval(interfaceName, dpId, vpnName, null);
1312 final boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
1313 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1314 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1315 if (interfaceManager.isExternalInterface(interfaceName)) {
1316 processExternalVpnInterface(interfaceName, vpnName, dpId, lportTag,
1317 NwConstants.DEL_FLOW);
1319 if (!isBgpVpnInternetVpn) {
1320 vpnUtil.unbindService(interfaceName, isInterfaceStateDown);
1322 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1323 + " successful", interfaceName, dpId, vpnName);
1325 // Interface is retained in the DPN, but its Link Down.
1326 // Only withdraw the prefixes for this interface from BGP
1327 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
1331 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1332 final String vpnName, final long vpnId, String gwMac,
1333 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1334 final WriteTransaction writeInvTxn) {
1337 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1338 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1339 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1340 Optional<AdjacenciesOp> adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1341 LogicalDatastoreType.OPERATIONAL, path);
1342 String primaryRd = vpnUtil.getVpnRd(vpnName);
1343 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1344 interfaceName, dpnId, vpnName, primaryRd);
1345 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1346 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1347 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1348 interfaceName, dpnId, vpnName, nextHops);
1349 for (Adjacency nextHop : nextHops) {
1350 if (nextHop.isPhysNetworkFunc()) {
1351 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1352 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1353 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1354 null/*writeCfgTxn*/);
1356 String rd = nextHop.getVrfId();
1357 List<String> nhList;
1358 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1359 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1361 // This is a primary adjacency
1362 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1363 : Collections.emptyList();
1364 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1365 interfaceName, writeInvTxn);
1367 if (!nhList.isEmpty()) {
1368 if (rd.equals(vpnName)) {
1369 //this is an internal vpn - the rd is assigned to the vpn instance name;
1370 //remove from FIB directly
1371 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1372 interfaceName, dpnId, writeConfigTxn, writeOperTxn));
1374 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
1375 interfaceName, writeConfigTxn, writeOperTxn);
1378 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1379 + " interface {}", nextHop.getIpAddress(), rd,
1380 nextHop.getAdjacencyType().toString(), interfaceName);
1381 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1382 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1385 String ip = nextHop.getIpAddress().split("/")[0];
1386 LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, ip);
1387 if (vpnVipToPort != null) {
1388 vpnUtil.removeLearntVpnVipToPort(vpnName, ip, null);
1389 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed LearntVpnVipToPort entry"
1390 + " for Interface {} ip {} on dpn {} for vpn {}",
1391 vpnVipToPort.getPortName(), ip, dpnId, vpnName);
1393 VpnPortipToPort vpnPortipToPort = vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnName, ip);
1394 if (vpnPortipToPort != null) {
1395 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip, null);
1396 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed vpnPortipToPort entry for "
1397 + "Interface {} ip {} on dpn {} for vpn {}",
1398 vpnPortipToPort.getPortName(), ip, dpnId, vpnName);
1402 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1403 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1404 + " Removing it.", interfaceName, vpnName, dpnId);
1405 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1407 } catch (ReadFailedException e) {
1408 LOG.error("removeAdjacenciesFromVpn: Failed to read data store for interface {} dpn {} vpn {}",
1409 interfaceName, dpnId, vpnName);
1413 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName, String interfaceName,
1414 BigInteger dpnId, WriteTransaction writeConfigTxn,
1415 WriteTransaction writeOperTx) {
1417 String primaryRd = vpnUtil.getVpnRd(vpnName);
1418 String prefix = nextHop.getIpAddress();
1419 String vpnNamePrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1420 LOG.info("remove adjacencies for nexthop {} vpnName {} interfaceName {} dpnId {}",
1421 nextHop, vpnName, interfaceName, dpnId);
1422 synchronized (vpnNamePrefixKey.intern()) {
1423 if (vpnUtil.removeOrUpdateDSForExtraRoute(vpnName, primaryRd, dpnId.toString(), interfaceName,
1424 prefix, nextHop.getNextHopIpList().get(0), nh, writeOperTx)) {
1425 //If extra-route is present behind at least one VM, then do not remove or update
1426 //fib entry for route-path representing that CSS nexthop, just update vpntoextraroute and
1427 //prefixtointerface DS
1430 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1433 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1434 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1435 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1439 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1440 BigInteger dpnId, String rd, String interfaceName,
1441 WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
1442 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1443 vpnUtil.getVpnsImportingMyRoute(vpnName);
1444 nhList.forEach((nh) -> {
1445 //IRT: remove routes from other vpns importing it
1446 vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
1447 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
1448 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1449 String vpnRd = vpn.getVrfId();
1450 if (vpnRd != null) {
1451 fibManager.removeOrUpdateFibEntry(vpnRd,
1452 nextHop.getIpAddress(), nh, writeConfigTxn);
1453 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1454 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1455 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1456 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1462 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1463 int lportTag, String gwMac, String interfaceName,
1464 WriteTransaction writeInvTxn) {
1465 final Uuid subnetId = nextHop.getSubnetId();
1466 if (nextHop.getSubnetGatewayMacAddress() == null) {
1467 // A valid mac-address was not available for this subnet-gateway-ip
1468 // So a connected-mac-address was used for this subnet and we need
1469 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1470 vpnUtil.setupGwMacIfExternalVpn(dpnId, interfaceName, vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1472 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1476 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1477 String interfaceName) {
1478 // This is either an extra-route (or) a learned IP via subnet-route
1479 List<String> nhList = null;
1480 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1481 if (nextHopIp == null || nextHopIp.isEmpty()) {
1482 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1483 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1484 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1486 nhList = Collections.emptyList();
1488 nhList = Collections.singletonList(nextHopIp);
1493 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1494 VpnPortipToPort gwPort = vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnName, ipAddress);
1495 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1496 // else use connected interface
1497 if (gwPort != null && gwPort.isSubnetIp()) {
1498 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1499 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1500 return Optional.of(gwPort.getMacAddress());
1502 return Optional.absent();
1506 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1507 final VpnInterface update) {
1508 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1509 update.getDpnId(), original.getVpnInstanceNames(),
1510 update.getVpnInstanceNames());
1511 final String vpnInterfaceName = update.getName();
1512 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1513 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1514 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1515 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1516 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1517 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1518 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1520 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1521 //handles switching between <internal VPN - external VPN>
1522 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1523 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1524 LOG.info("update: handled VPNInterface {} on dpn {} update"
1525 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1526 original.getName(), dpnId,
1527 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1528 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1529 return Collections.emptyList();
1531 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1532 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1533 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1534 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1535 String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
1536 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
1537 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
1538 List<ListenableFuture<Void>> futures = new ArrayList<>();
1539 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1540 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(operTx -> {
1541 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1542 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1543 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1544 update.getName(), newVpnName);
1545 //handle both addition and removal of adjacencies
1546 //currently, new adjacency may be an extra route
1547 boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
1548 if (!oldAdjs.equals(newAdjs)) {
1549 for (Adjacency adj : copyNewAdjs) {
1550 if (copyOldAdjs.contains(adj)) {
1551 copyOldAdjs.remove(adj);
1553 // add new adjacency - right now only extra route will hit this path
1554 if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
1555 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1556 dpnId, operTx, confTx);
1558 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
1559 + " vpn interface {} on vpn {} dpnId {}",
1560 adj.getIpAddress(), adj.getNextHopIpList(),
1561 adj.getLabel(), adj.getSubnetId(), update.getName(),
1565 for (Adjacency adj : copyOldAdjs) {
1566 if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
1567 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
1568 && !adj.isPhysNetworkFunc()) {
1569 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1571 Optional<VpnInterfaceOpDataEntry> optVpnInterface = operTx.read(
1572 LogicalDatastoreType.OPERATIONAL, vpnInterfaceOpIdentifier).get();
1573 if (optVpnInterface.isPresent()) {
1574 VpnInterfaceOpDataEntry vpnInterfaceOpDataEntry = optVpnInterface.get();
1575 long vpnId = vpnUtil.getVpnId(newVpnName);
1576 vpnUtil.removePrefixToInterfaceAdj(adj, vpnId,
1577 vpnInterfaceOpDataEntry, operTx);
1579 LOG.info("update: Vpninterface {} not present in Operational",
1583 String vpnRd = vpnUtil.getVpnRd(newVpnName);
1584 LOG.debug("update: remove prefix {} from the FIB and BGP entry "
1585 + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
1587 fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
1588 if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
1589 bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
1592 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1596 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1597 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
1598 .getNextHopIpList(),
1599 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1604 for (ListenableFuture<Void> future : futures) {
1605 ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
1606 update.getName(), update.getVpnInstanceNames());
1610 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1611 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1614 return Collections.emptyList();
1618 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1619 VpnInterface original, VpnInterface update) {
1620 boolean isSwap = Boolean.FALSE;
1621 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1622 final String interfaceName = key.getName();
1623 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1624 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1625 List<String> oldVpnListCopy = new ArrayList<>();
1626 oldVpnListCopy.addAll(oldVpnList);
1627 List<String> newVpnList = update.getVpnInstanceNames().stream()
1628 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1629 oldVpnList.removeAll(newVpnList);
1630 newVpnList.removeAll(oldVpnListCopy);
1631 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1632 for (String oldVpnName: oldVpnList) {
1633 isSwap = Boolean.TRUE;
1634 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1635 + " running config-driven swap removal", interfaceName, oldVpnName);
1636 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1637 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1638 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1640 //Wait for previous interface bindings to be removed
1643 } catch (InterruptedException e) {
1647 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1648 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1649 ? origAdjs.getAdjacency() : new ArrayList<>();
1650 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1651 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1652 ? updateAdjs.getAdjacency() : new ArrayList<>();
1654 for (String newVpnName: newVpnList) {
1655 String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
1656 isSwap = Boolean.TRUE;
1657 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
1658 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1659 + "running config-driven swap addition", interfaceName, newVpnName);
1660 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1661 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1662 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1663 interfaceName, oldVpnListCopy, newVpnName);
1670 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1672 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1673 synchronized (label.toString().intern()) {
1674 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1675 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1676 Optional<LabelRouteInfo> opResult = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1677 LogicalDatastoreType.OPERATIONAL, lriIid);
1678 if (opResult.isPresent()) {
1679 LabelRouteInfo labelRouteInfo =
1680 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1681 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid,
1682 labelRouteInfo, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
1685 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label,
1687 } catch (ReadFailedException e) {
1688 LOG.error("updateLabelMapper: Failed to read data store for label {} nexthopList {}", label,
1690 } catch (TransactionCommitFailedException e) {
1691 LOG.error("updateLabelMapper: Failed to commit to data store for label {} nexthopList {}", label,
1696 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1697 SubnetRoute route, String parentVpnRd, WriteTransaction writeConfigTxn) {
1699 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1700 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, parentVpnRd)
1701 .addAugmentation(SubnetRoute.class, route).build();
1702 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1703 InstanceIdentifierBuilder<VrfTables> idBuilder =
1704 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1705 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1706 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1707 if (writeConfigTxn != null) {
1708 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1710 vpnUtil.syncUpdate(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1712 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1713 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1716 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1717 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1718 WriteTransaction writeConfigTxn) {
1719 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1720 String configVpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1722 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker
1723 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1724 if (optVpnInterface.isPresent()) {
1725 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1726 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1727 String vpnName = currVpnIntf.getVpnInstanceName();
1728 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
1729 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1730 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1731 LogicalDatastoreType.OPERATIONAL, adjPath);
1732 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1733 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1734 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1735 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1736 List<Adjacency> adjacencies;
1737 if (optAdjacencies.isPresent()) {
1738 adjacencies = optAdjacencies.get().getAdjacency();
1740 // This code will be hit in case of first PNF adjacency
1741 adjacencies = new ArrayList<>();
1743 long vpnId = vpnUtil.getVpnId(vpnName);
1744 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1745 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1746 Adjacency operationalAdjacency = null;
1747 //Handling dual stack neutron port primary adjacency
1748 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency && !adj.isPhysNetworkFunc()) {
1749 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to existing interface {} for vpn {}", prefix,
1750 currVpnIntf.getName(), vpnName);
1751 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,
1752 currVpnIntf.getName());
1753 if (interfaceState != null) {
1754 processVpnInterfaceAdjacencies(dpnId, currVpnIntf.getLportTag().intValue(), vpnName, primaryRd,
1755 currVpnIntf.getName(),
1756 vpnId, writeConfigTxn, writeOperTxn, null, interfaceState);
1759 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()
1760 && adj.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1761 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1762 : RouteOrigin.STATIC;
1763 String nh = adj.getNextHopIpList().get(0);
1764 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1765 synchronized (vpnPrefixKey.intern()) {
1766 java.util.Optional<String> rdToAllocate = vpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1767 vpnId, null, prefix, vpnName, nh, dpnId);
1768 if (rdToAllocate.isPresent()) {
1769 input.setRd(rdToAllocate.get());
1770 operationalAdjacency = populator.createOperationalAdjacency(input);
1771 int label = operationalAdjacency.getLabel().intValue();
1772 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1773 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1774 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1775 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1776 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1777 vpnName, label, currVpnIntf.getName(), dpnId);
1779 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}",
1783 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1784 // Keeping the MPLS check for now.
1785 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1786 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1787 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1788 vpnUtil.getVpnsImportingMyRoute(vpnName);
1789 vpnsToImportRoute.forEach(vpn -> {
1790 if (vpn.getVrfId() != null) {
1791 vpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(vpn.getVpnId(), vpnId, prefix,
1792 vpnUtil.getVpnName(vpn.getVpnId()), nh, dpnId)
1794 rds -> vpnManager.addExtraRoute(
1795 vpnUtil.getVpnName(vpn.getVpnId()),
1796 adj.getIpAddress(), nh, rds,
1797 currVpnIntf.getVpnInstanceName(), l3vni,
1798 RouteOrigin.SELF_IMPORTED, currVpnIntf.getName(),
1799 opAdjacency, encapType, writeConfigTxn));
1804 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1805 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1806 currVpnIntf.getName(), vpnName);
1808 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1811 LogicalDatastoreType.OPERATIONAL,
1812 VpnUtil.getPrefixToInterfaceIdentifier(vpnUtil.getVpnId(adj.getSubnetId().getValue()),
1813 prefix), VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(),
1814 prefix, adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1816 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1817 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */,
1818 0 /*l3vni*/, null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1820 input.setRd(adj.getVrfId());
1822 if (operationalAdjacency == null) {
1823 operationalAdjacency = populator.createOperationalAdjacency(input);
1825 adjacencies.add(operationalAdjacency);
1826 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1827 VpnInterfaceOpDataEntry newVpnIntf =
1828 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1829 aug, dpnId, currVpnIntf.getLportTag(),
1830 currVpnIntf.getGatewayMacAddress());
1832 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1834 } catch (ReadFailedException e) {
1835 LOG.error("addNewAdjToVpnInterface: Failed to read data store for interface {} dpn {} vpn {} rd {} ip "
1836 + "{}", interfaceName, dpnId, configVpnName, primaryRd, adj.getIpAddress());
1840 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1841 Subnets subnets = vpnUtil.getExternalSubnet(adj.getSubnetId());
1842 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1845 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1846 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1847 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1848 String vpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1850 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker.syncReadOptional(
1851 dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1852 if (optVpnInterface.isPresent()) {
1853 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1854 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1855 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1856 LogicalDatastoreType.OPERATIONAL, path);
1857 if (optAdjacencies.isPresent()) {
1858 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1860 if (!adjacencies.isEmpty()) {
1861 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1862 Iterator<Adjacency> adjIt = adjacencies.iterator();
1863 while (adjIt.hasNext()) {
1864 Adjacency adjElem = adjIt.next();
1865 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1866 String rd = adjElem.getVrfId();
1867 if (adj.getNextHopIpList() != null) {
1868 for (String nh : adj.getNextHopIpList()) {
1869 deleteExtraRouteFromCurrentAndImportingVpns(
1870 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1871 currVpnIntf.getName(), writeConfigTxn, writeOperTxn);
1873 } else if (adj.isPhysNetworkFunc()) {
1874 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1875 adj.getIpAddress(), adj.getSubnetId());
1876 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1884 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1885 dpnId, adj.getVrfId());
1887 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1888 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1891 } catch (ReadFailedException e) {
1892 LOG.error("delAdjFromVpnInterface: Failed to read data store for ip {} interface {} dpn {} vpn {}",
1893 adj.getIpAddress(), interfaceName, dpnId, vpnName);
1897 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1898 String rd, String intfName, WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
1899 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn, writeOperTx);
1900 List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
1901 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1902 String vpnRd = vpn.getVrfId();
1903 if (vpnRd != null) {
1904 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn,
1910 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1911 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1912 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1913 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1916 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1917 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1918 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1921 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1922 WriteTransaction writeConfigTxn, String vpnName) {
1923 if (vpnInterface == null) {
1926 List<Adjacency> adjs = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(interfaceName);
1928 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1929 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1932 for (Adjacency adj : adjs) {
1933 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1934 String primaryInterfaceIp = adj.getIpAddress();
1935 String macAddress = adj.getMacAddress();
1936 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1938 long label = vpnUtil.getUniqueId(VpnConstants.VPN_IDPOOL_NAME,
1939 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1941 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1942 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1943 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1944 routerInt, label, writeConfigTxn);
1945 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1946 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1951 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1952 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1953 primaryRd, vpnName);
1956 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1957 WriteTransaction writeConfigTxn, String vpnName) {
1958 Adjacencies adjs = vpnInterface.augmentation(Adjacencies.class);
1959 String rd = vpnUtil.getVpnRd(vpnName);
1961 List<Adjacency> adjsList = adjs.getAdjacency();
1962 for (Adjacency adj : adjsList) {
1963 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1964 String primaryInterfaceIp = adj.getIpAddress();
1965 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1966 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1967 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1968 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1973 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
1974 vpnInterface.getName(), rd);
1978 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
1979 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
1980 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
1981 vpnName, intefaceData.vpnInterface.getName());
1984 final VpnInterfaceKey key = intefaceData.identifier
1985 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1986 final String interfaceName = key.getName();
1987 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
1988 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1989 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
1990 intefaceData.identifier, vpnName);
1994 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
1995 VpnInterface vpnInterface, String vpnName) {
1996 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
1998 if (vpnInterfaces == null) {
1999 vpnInterfaces = new ConcurrentLinkedQueue<>();
2001 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2002 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2003 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2004 vpnInterface.getName(), vpnName);
2007 public boolean isVpnInstanceReady(String vpnInstanceName) {
2008 String vpnRd = vpnUtil.getVpnRd(vpnInstanceName);
2009 if (vpnRd == null) {
2012 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(vpnRd);
2014 return vpnInstanceOpDataEntry != null;
2017 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2018 synchronized (vpnInstanceName.intern()) {
2019 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2020 unprocessedVpnInterfaces.get(vpnInstanceName);
2021 if (vpnInterfaces != null) {
2022 while (!vpnInterfaces.isEmpty()) {
2023 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2024 if (hasVpnInstanceCreatedSuccessfully) {
2025 processSavedInterface(savedInterface, vpnInstanceName);
2026 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2027 savedInterface.vpnInterface.getName(), vpnInstanceName);
2029 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2030 savedInterface.vpnInterface.getName(), vpnInstanceName);
2034 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2039 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2040 VpnInterface vpnInterface) {
2041 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2042 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2043 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2044 if (vpnInterfaces != null) {
2045 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2046 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2047 + "unprocessed list", vpnInterface.getName(),
2048 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2051 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2052 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2057 public void vpnInstanceIsReady(String vpnInstanceName) {
2058 processSavedInterfaces(vpnInstanceName, true);
2061 public void vpnInstanceFailed(String vpnInstanceName) {
2062 processSavedInterfaces(vpnInstanceName, false);
2065 private static class UnprocessedVpnInterfaceData {
2066 InstanceIdentifier<VpnInterface> identifier;
2067 VpnInterface vpnInterface;
2069 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2070 this.identifier = identifier;
2071 this.vpnInterface = vpnInterface;
2075 public int hashCode() {
2076 final int prime = 31;
2078 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2079 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2084 public boolean equals(Object obj) {
2091 if (getClass() != obj.getClass()) {
2094 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2095 if (identifier == null) {
2096 if (other.identifier != null) {
2099 } else if (!identifier.equals(other.identifier)) {
2102 if (vpnInterface == null) {
2103 if (other.vpnInterface != null) {
2106 } else if (!vpnInterface.equals(other.vpnInterface)) {
2113 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2114 String primaryRd = vpnUtil.getVpnRd(vpnName);
2115 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
2116 if (vpnInstanceOpData == null) {
2119 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2120 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2123 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2124 vpnToDpnLists.forEach(vpnToDpnList -> {
2125 if (vpnToDpnList.getVpnInterfaces() == null) {
2128 vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2130 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2131 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2132 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = SingleTransactionDataBroker
2133 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2134 if (!vpnInterfaceOptional.isPresent()) {
2137 List<Adjacency> configVpnAdjacencies = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(
2138 vpnInterface.getInterfaceName());
2139 if (configVpnAdjacencies == null) {
2140 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2143 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2144 .augmentation(AdjacenciesOp.class).getAdjacency();
2145 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2146 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2147 // in operational DS. These unprocessed adjacencies will be handled below.
2148 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in
2149 // operational DS are retrieved which is used to call addNewAdjToVpnInterface method.
2150 configVpnAdjacencies.stream()
2151 .filter(adjacency -> operationVpnAdjacencies.stream()
2152 .noneMatch(operationalAdjacency ->
2153 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2154 .forEach(adjacency -> {
2155 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2156 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2158 // TODO Deal with sequencing — the config tx must only submitted
2159 // if the oper tx goes in
2160 if (vpnUtil.isAdjacencyEligibleToVpn(adjacency, vpnName)) {
2161 List<ListenableFuture<Void>> futures = new ArrayList<>();
2162 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx ->
2163 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
2164 confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId,
2165 primaryRd, adjacency, vpnInterfaceOptional.get()
2166 .getDpnId(), confTx, operTx)))));
2169 return Collections.emptyList();
2173 } catch (ReadFailedException e) {
2174 LOG.error("updateVpnInterfacesForUnProcessAdjancencies: Failed to read data store for vpn {} rd {}",
2175 vpnName, primaryRd);
2181 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2182 private final String interfaceName;
2183 private final boolean add;
2184 private final String txnDestination;
2186 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2187 this.interfaceName = interfaceName;
2189 this.txnDestination = transactionDest;
2193 public void onSuccess(Void voidObj) {
2195 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2196 interfaceName, txnDestination);
2198 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2203 public void onFailure(Throwable throwable) {
2205 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2206 interfaceName, txnDestination, throwable);
2208 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2209 vpnUtil.unsetScheduledToRemoveForVpnInterface(interfaceName);