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 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1217 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1221 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1222 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1223 final VpnInterface vpnInterface, final String vpnName,
1224 final String interfaceName, final Interface interfaceState) {
1225 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1226 vpnName, vpnInterface.getDpnId());
1227 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1228 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1230 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1231 ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1232 writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1233 writeOperTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1234 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1235 interfaceName, vpnName);
1236 BigInteger dpId = BigInteger.ZERO;
1238 String gwMacAddress = null;
1239 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1240 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1241 Optional<VpnInterfaceOpDataEntry> optVpnInterface = Optional.absent();
1243 optVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1244 LogicalDatastoreType.OPERATIONAL, interfaceId);
1245 } catch (ReadFailedException e) {
1246 LOG.error("remove: Failed to read data store for interface {} vpn {}", interfaceName,
1250 if (interfaceState != null) {
1252 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1253 } catch (NumberFormatException | IllegalStateException e) {
1254 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1255 + " data store for interface {} on dpn {} for vpn {} Fetching"
1256 + " from vpn interface op data store. ", interfaceName,
1257 vpnInterface.getDpnId(), vpnName, e);
1258 dpId = BigInteger.ZERO;
1260 ifIndex = interfaceState.getIfIndex();
1261 gwMacAddress = interfaceState.getPhysAddress().getValue();
1263 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1264 + " from vpn interface op.", interfaceName);
1265 if (optVpnInterface.isPresent()) {
1266 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1267 dpId = vpnOpInterface.getDpnId();
1268 ifIndex = vpnOpInterface.getLportTag().intValue();
1269 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1271 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1272 + " as interfaceState and vpn interface op is not"
1273 + " available", interfaceName, vpnName);
1277 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1278 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1279 writeConfigTxn, writeOperTxn, writeInvTxn);
1281 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1283 interfaceName, vpnInterface.getDpnId(), vpnName);
1285 futures.add(configFuture);
1286 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1288 }, DJC_MAX_RETRIES);
1291 protected void processVpnInterfaceDown(BigInteger dpId,
1292 String interfaceName,
1295 VpnInterfaceOpDataEntry vpnOpInterface,
1296 boolean isInterfaceStateDown,
1297 WriteTransaction writeConfigTxn,
1298 WriteTransaction writeOperTxn,
1299 WriteTransaction writeInvTxn) {
1300 if (vpnOpInterface == null) {
1301 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1302 + " as it is not available in operational data store", interfaceName, dpId);
1305 final String vpnName = vpnOpInterface.getVpnInstanceName();
1306 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1307 interfaceName, vpnName);
1308 if (!isInterfaceStateDown) {
1309 final long vpnId = vpnUtil.getVpnId(vpnName);
1310 vpnUtil.scheduleVpnInterfaceForRemoval(interfaceName, dpId, vpnName, null);
1311 final boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
1312 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1313 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1314 if (interfaceManager.isExternalInterface(interfaceName)) {
1315 processExternalVpnInterface(interfaceName, vpnName, dpId, lportTag,
1316 NwConstants.DEL_FLOW);
1318 if (!isBgpVpnInternetVpn) {
1319 vpnUtil.unbindService(interfaceName, isInterfaceStateDown);
1321 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1322 + " successful", interfaceName, dpId, vpnName);
1324 // Interface is retained in the DPN, but its Link Down.
1325 // Only withdraw the prefixes for this interface from BGP
1326 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
1330 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1331 final String vpnName, final long vpnId, String gwMac,
1332 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1333 final WriteTransaction writeInvTxn) {
1336 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1337 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1338 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1339 Optional<AdjacenciesOp> adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1340 LogicalDatastoreType.OPERATIONAL, path);
1341 String primaryRd = vpnUtil.getVpnRd(vpnName);
1342 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1343 interfaceName, dpnId, vpnName, primaryRd);
1344 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1345 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1346 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1347 interfaceName, dpnId, vpnName, nextHops);
1348 for (Adjacency nextHop : nextHops) {
1349 if (nextHop.isPhysNetworkFunc()) {
1350 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1351 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1352 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1353 null/*writeCfgTxn*/);
1355 String rd = nextHop.getVrfId();
1356 List<String> nhList;
1357 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1358 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1360 // This is a primary adjacency
1361 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1362 : Collections.emptyList();
1363 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1364 interfaceName, writeInvTxn);
1366 if (!nhList.isEmpty()) {
1367 if (rd.equals(vpnName)) {
1368 //this is an internal vpn - the rd is assigned to the vpn instance name;
1369 //remove from FIB directly
1370 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1371 interfaceName, dpnId, writeConfigTxn, writeOperTxn));
1373 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
1374 interfaceName, writeConfigTxn, writeOperTxn);
1377 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1378 + " interface {}", nextHop.getIpAddress(), rd,
1379 nextHop.getAdjacencyType().toString(), interfaceName);
1380 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1381 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1384 String ip = nextHop.getIpAddress().split("/")[0];
1385 LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, ip);
1386 if (vpnVipToPort != null) {
1387 vpnUtil.removeLearntVpnVipToPort(vpnName, ip, null);
1388 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed LearntVpnVipToPort entry"
1389 + " for Interface {} ip {} on dpn {} for vpn {}",
1390 vpnVipToPort.getPortName(), ip, dpnId, vpnName);
1392 VpnPortipToPort vpnPortipToPort = vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnName, ip);
1393 if (vpnPortipToPort != null) {
1394 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip, null);
1395 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed vpnPortipToPort entry for "
1396 + "Interface {} ip {} on dpn {} for vpn {}",
1397 vpnPortipToPort.getPortName(), ip, dpnId, vpnName);
1401 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1402 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1403 + " Removing it.", interfaceName, vpnName, dpnId);
1404 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1406 } catch (ReadFailedException e) {
1407 LOG.error("removeAdjacenciesFromVpn: Failed to read data store for interface {} dpn {} vpn {}",
1408 interfaceName, dpnId, vpnName);
1412 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName, String interfaceName,
1413 BigInteger dpnId, WriteTransaction writeConfigTxn,
1414 WriteTransaction writeOperTx) {
1416 String primaryRd = vpnUtil.getVpnRd(vpnName);
1417 String prefix = nextHop.getIpAddress();
1418 String vpnNamePrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1419 LOG.info("remove adjacencies for nexthop {} vpnName {} interfaceName {} dpnId {}",
1420 nextHop, vpnName, interfaceName, dpnId);
1421 synchronized (vpnNamePrefixKey.intern()) {
1422 if (vpnUtil.removeOrUpdateDSForExtraRoute(vpnName, primaryRd, dpnId.toString(), interfaceName,
1423 prefix, nextHop.getNextHopIpList().get(0), nh, writeOperTx)) {
1424 //If extra-route is present behind at least one VM, then do not remove or update
1425 //fib entry for route-path representing that CSS nexthop, just update vpntoextraroute and
1426 //prefixtointerface DS
1429 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1432 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1433 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1434 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1438 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1439 BigInteger dpnId, String rd, String interfaceName,
1440 WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
1441 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1442 vpnUtil.getVpnsImportingMyRoute(vpnName);
1443 nhList.forEach((nh) -> {
1444 //IRT: remove routes from other vpns importing it
1445 vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
1446 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
1447 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1448 String vpnRd = vpn.getVrfId();
1449 if (vpnRd != null) {
1450 fibManager.removeOrUpdateFibEntry(vpnRd,
1451 nextHop.getIpAddress(), nh, writeConfigTxn);
1452 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1453 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1454 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1455 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1461 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1462 int lportTag, String gwMac, String interfaceName,
1463 WriteTransaction writeInvTxn) {
1464 final Uuid subnetId = nextHop.getSubnetId();
1465 if (nextHop.getSubnetGatewayMacAddress() == null) {
1466 // A valid mac-address was not available for this subnet-gateway-ip
1467 // So a connected-mac-address was used for this subnet and we need
1468 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1469 vpnUtil.setupGwMacIfExternalVpn(dpnId, interfaceName, vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1471 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1475 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1476 String interfaceName) {
1477 // This is either an extra-route (or) a learned IP via subnet-route
1478 List<String> nhList = null;
1479 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1480 if (nextHopIp == null || nextHopIp.isEmpty()) {
1481 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1482 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1483 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1485 nhList = Collections.emptyList();
1487 nhList = Collections.singletonList(nextHopIp);
1492 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1493 VpnPortipToPort gwPort = vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnName, ipAddress);
1494 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1495 // else use connected interface
1496 if (gwPort != null && gwPort.isSubnetIp()) {
1497 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1498 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1499 return Optional.of(gwPort.getMacAddress());
1501 return Optional.absent();
1505 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1506 final VpnInterface update) {
1507 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1508 update.getDpnId(), original.getVpnInstanceNames(),
1509 update.getVpnInstanceNames());
1510 final String vpnInterfaceName = update.getName();
1511 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1512 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1513 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1514 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1515 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1516 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1517 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1519 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1520 //handles switching between <internal VPN - external VPN>
1521 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1522 LOG.info("update: handled VPNInterface {} on dpn {} update"
1523 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1524 original.getName(), dpnId,
1525 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1526 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1529 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1530 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1531 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1532 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1533 String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
1534 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
1535 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1536 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
1537 List<ListenableFuture<Void>> futures = new ArrayList<>();
1538 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1539 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(operTx -> {
1540 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1541 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1542 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1543 update.getName(), newVpnName);
1544 //handle both addition and removal of adjacencies
1545 //currently, new adjacency may be an extra route
1546 boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
1547 if (!oldAdjs.equals(newAdjs)) {
1548 for (Adjacency adj : copyNewAdjs) {
1549 if (copyOldAdjs.contains(adj)) {
1550 copyOldAdjs.remove(adj);
1552 // add new adjacency - right now only extra route will hit this path
1553 if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
1554 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1555 dpnId, operTx, confTx);
1557 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
1558 + " vpn interface {} on vpn {} dpnId {}",
1559 adj.getIpAddress(), adj.getNextHopIpList(),
1560 adj.getLabel(), adj.getSubnetId(), update.getName(),
1564 for (Adjacency adj : copyOldAdjs) {
1565 if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
1566 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
1567 && !adj.isPhysNetworkFunc()) {
1568 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1570 Optional<VpnInterfaceOpDataEntry> optVpnInterface = operTx.read(
1571 LogicalDatastoreType.OPERATIONAL, vpnInterfaceOpIdentifier).get();
1572 if (optVpnInterface.isPresent()) {
1573 VpnInterfaceOpDataEntry vpnInterfaceOpDataEntry = optVpnInterface.get();
1574 long vpnId = vpnUtil.getVpnId(newVpnName);
1575 vpnUtil.removePrefixToInterfaceAdj(adj, vpnId,
1576 vpnInterfaceOpDataEntry, operTx);
1578 LOG.info("update: Vpninterface {} not present in Operational",
1582 String vpnRd = vpnUtil.getVpnRd(newVpnName);
1583 LOG.debug("update: remove prefix {} from the FIB and BGP entry "
1584 + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
1586 fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
1587 if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
1588 bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
1591 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1595 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1596 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
1597 .getNextHopIpList(),
1598 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1603 for (ListenableFuture<Void> future : futures) {
1604 ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
1605 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);
1616 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1617 VpnInterface original, VpnInterface update) {
1618 boolean isSwap = Boolean.FALSE;
1619 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1620 final String interfaceName = key.getName();
1621 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1622 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1623 List<String> oldVpnListCopy = new ArrayList<>();
1624 oldVpnListCopy.addAll(oldVpnList);
1625 List<String> newVpnList = update.getVpnInstanceNames().stream()
1626 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1627 oldVpnList.removeAll(newVpnList);
1628 newVpnList.removeAll(oldVpnListCopy);
1629 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1630 for (String oldVpnName: oldVpnList) {
1631 isSwap = Boolean.TRUE;
1632 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1633 + " running config-driven swap removal", interfaceName, oldVpnName);
1634 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1635 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1636 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1638 //Wait for previous interface bindings to be removed
1641 } catch (InterruptedException e) {
1644 for (String newVpnName: newVpnList) {
1645 String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
1646 isSwap = Boolean.TRUE;
1647 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
1648 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1649 + "running config-driven swap addition", interfaceName, newVpnName);
1650 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1651 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1652 ? origAdjs.getAdjacency() : new ArrayList<>();
1653 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1654 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1655 ? updateAdjs.getAdjacency() : new ArrayList<>();
1657 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1658 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1659 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1660 interfaceName, oldVpnListCopy, newVpnName);
1667 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1669 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1670 synchronized (label.toString().intern()) {
1671 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1672 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1673 Optional<LabelRouteInfo> opResult = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1674 LogicalDatastoreType.OPERATIONAL, lriIid);
1675 if (opResult.isPresent()) {
1676 LabelRouteInfo labelRouteInfo =
1677 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1678 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid,
1679 labelRouteInfo, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
1682 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label,
1684 } catch (ReadFailedException e) {
1685 LOG.error("updateLabelMapper: Failed to read data store for label {} nexthopList {}", label,
1687 } catch (TransactionCommitFailedException e) {
1688 LOG.error("updateLabelMapper: Failed to commit to data store for label {} nexthopList {}", label,
1693 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1694 SubnetRoute route, String parentVpnRd, WriteTransaction writeConfigTxn) {
1696 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1697 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, parentVpnRd)
1698 .addAugmentation(SubnetRoute.class, route).build();
1699 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1700 InstanceIdentifierBuilder<VrfTables> idBuilder =
1701 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1702 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1703 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1704 if (writeConfigTxn != null) {
1705 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1707 vpnUtil.syncUpdate(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1709 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1710 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1713 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1714 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1715 WriteTransaction writeConfigTxn) {
1716 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1717 String configVpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1719 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker
1720 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1721 if (optVpnInterface.isPresent()) {
1722 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1723 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1724 String vpnName = currVpnIntf.getVpnInstanceName();
1725 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
1726 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1727 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1728 LogicalDatastoreType.OPERATIONAL, adjPath);
1729 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1730 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1731 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1732 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1733 List<Adjacency> adjacencies;
1734 if (optAdjacencies.isPresent()) {
1735 adjacencies = optAdjacencies.get().getAdjacency();
1737 // This code will be hit in case of first PNF adjacency
1738 adjacencies = new ArrayList<>();
1740 long vpnId = vpnUtil.getVpnId(vpnName);
1741 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1742 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1743 Adjacency operationalAdjacency = null;
1744 //Handling dual stack neutron port primary adjacency
1745 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency && !adj.isPhysNetworkFunc()) {
1746 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to existing interface {} for vpn {}", prefix,
1747 currVpnIntf.getName(), vpnName);
1748 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,
1749 currVpnIntf.getName());
1750 if (interfaceState != null) {
1751 processVpnInterfaceAdjacencies(dpnId, currVpnIntf.getLportTag().intValue(), vpnName, primaryRd,
1752 currVpnIntf.getName(),
1753 vpnId, writeConfigTxn, writeOperTxn, null, interfaceState);
1756 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()
1757 && adj.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1758 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1759 : RouteOrigin.STATIC;
1760 String nh = adj.getNextHopIpList().get(0);
1761 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1762 synchronized (vpnPrefixKey.intern()) {
1763 java.util.Optional<String> rdToAllocate = vpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1764 vpnId, null, prefix, vpnName, nh, dpnId);
1765 if (rdToAllocate.isPresent()) {
1766 input.setRd(rdToAllocate.get());
1767 operationalAdjacency = populator.createOperationalAdjacency(input);
1768 int label = operationalAdjacency.getLabel().intValue();
1769 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1770 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1771 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1772 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1773 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1774 vpnName, label, currVpnIntf.getName(), dpnId);
1776 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}",
1780 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1781 // Keeping the MPLS check for now.
1782 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1783 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1784 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1785 vpnUtil.getVpnsImportingMyRoute(vpnName);
1786 vpnsToImportRoute.forEach(vpn -> {
1787 if (vpn.getVrfId() != null) {
1788 vpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(vpn.getVpnId(), vpnId, prefix,
1789 vpnUtil.getVpnName(vpn.getVpnId()), nh, dpnId)
1791 rds -> vpnManager.addExtraRoute(
1792 vpnUtil.getVpnName(vpn.getVpnId()),
1793 adj.getIpAddress(), nh, rds,
1794 currVpnIntf.getVpnInstanceName(), l3vni,
1795 RouteOrigin.SELF_IMPORTED, currVpnIntf.getName(),
1796 opAdjacency, encapType, writeConfigTxn));
1801 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1802 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1803 currVpnIntf.getName(), vpnName);
1805 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1808 LogicalDatastoreType.OPERATIONAL,
1809 VpnUtil.getPrefixToInterfaceIdentifier(vpnUtil.getVpnId(adj.getSubnetId().getValue()),
1810 prefix), VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(),
1811 prefix, adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1813 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1814 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */,
1815 0 /*l3vni*/, null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1817 input.setRd(adj.getVrfId());
1819 if (operationalAdjacency == null) {
1820 operationalAdjacency = populator.createOperationalAdjacency(input);
1822 adjacencies.add(operationalAdjacency);
1823 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1824 VpnInterfaceOpDataEntry newVpnIntf =
1825 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1826 aug, dpnId, currVpnIntf.getLportTag(),
1827 currVpnIntf.getGatewayMacAddress());
1829 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1831 } catch (ReadFailedException e) {
1832 LOG.error("addNewAdjToVpnInterface: Failed to read data store for interface {} dpn {} vpn {} rd {} ip "
1833 + "{}", interfaceName, dpnId, configVpnName, primaryRd, adj.getIpAddress());
1837 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1838 Subnets subnets = vpnUtil.getExternalSubnet(adj.getSubnetId());
1839 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1842 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1843 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1844 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1845 String vpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1847 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker.syncReadOptional(
1848 dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1849 if (optVpnInterface.isPresent()) {
1850 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1851 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1852 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1853 LogicalDatastoreType.OPERATIONAL, path);
1854 if (optAdjacencies.isPresent()) {
1855 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1857 if (!adjacencies.isEmpty()) {
1858 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1859 Iterator<Adjacency> adjIt = adjacencies.iterator();
1860 while (adjIt.hasNext()) {
1861 Adjacency adjElem = adjIt.next();
1862 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1863 String rd = adjElem.getVrfId();
1864 if (adj.getNextHopIpList() != null) {
1865 for (String nh : adj.getNextHopIpList()) {
1866 deleteExtraRouteFromCurrentAndImportingVpns(
1867 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1868 currVpnIntf.getName(), writeConfigTxn, writeOperTxn);
1870 } else if (adj.isPhysNetworkFunc()) {
1871 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1872 adj.getIpAddress(), adj.getSubnetId());
1873 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1881 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1882 dpnId, adj.getVrfId());
1884 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1885 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1888 } catch (ReadFailedException e) {
1889 LOG.error("delAdjFromVpnInterface: Failed to read data store for ip {} interface {} dpn {} vpn {}",
1890 adj.getIpAddress(), interfaceName, dpnId, vpnName);
1894 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1895 String rd, String intfName, WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
1896 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn, writeOperTx);
1897 List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
1898 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1899 String vpnRd = vpn.getVrfId();
1900 if (vpnRd != null) {
1901 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn,
1907 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1908 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1909 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1910 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1913 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1914 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1915 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1918 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1919 WriteTransaction writeConfigTxn, String vpnName) {
1920 if (vpnInterface == null) {
1923 List<Adjacency> adjs = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(interfaceName);
1925 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1926 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1929 for (Adjacency adj : adjs) {
1930 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1931 String primaryInterfaceIp = adj.getIpAddress();
1932 String macAddress = adj.getMacAddress();
1933 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1935 long label = vpnUtil.getUniqueId(VpnConstants.VPN_IDPOOL_NAME,
1936 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1938 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1939 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1940 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1941 routerInt, label, writeConfigTxn);
1942 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1943 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1948 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1949 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1950 primaryRd, vpnName);
1953 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1954 WriteTransaction writeConfigTxn, String vpnName) {
1955 Adjacencies adjs = vpnInterface.augmentation(Adjacencies.class);
1956 String rd = vpnUtil.getVpnRd(vpnName);
1958 List<Adjacency> adjsList = adjs.getAdjacency();
1959 for (Adjacency adj : adjsList) {
1960 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1961 String primaryInterfaceIp = adj.getIpAddress();
1962 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1963 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1964 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1965 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1970 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
1971 vpnInterface.getName(), rd);
1975 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
1976 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
1977 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
1978 vpnName, intefaceData.vpnInterface.getName());
1981 final VpnInterfaceKey key = intefaceData.identifier
1982 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1983 final String interfaceName = key.getName();
1984 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
1985 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1986 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
1987 intefaceData.identifier, vpnName);
1991 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
1992 VpnInterface vpnInterface, String vpnName) {
1993 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
1995 if (vpnInterfaces == null) {
1996 vpnInterfaces = new ConcurrentLinkedQueue<>();
1998 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
1999 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2000 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2001 vpnInterface.getName(), vpnName);
2004 public boolean isVpnInstanceReady(String vpnInstanceName) {
2005 String vpnRd = vpnUtil.getVpnRd(vpnInstanceName);
2006 if (vpnRd == null) {
2009 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(vpnRd);
2011 return vpnInstanceOpDataEntry != null;
2014 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2015 synchronized (vpnInstanceName.intern()) {
2016 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2017 unprocessedVpnInterfaces.get(vpnInstanceName);
2018 if (vpnInterfaces != null) {
2019 while (!vpnInterfaces.isEmpty()) {
2020 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2021 if (hasVpnInstanceCreatedSuccessfully) {
2022 processSavedInterface(savedInterface, vpnInstanceName);
2023 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2024 savedInterface.vpnInterface.getName(), vpnInstanceName);
2026 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2027 savedInterface.vpnInterface.getName(), vpnInstanceName);
2031 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2036 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2037 VpnInterface vpnInterface) {
2038 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2039 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2040 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2041 if (vpnInterfaces != null) {
2042 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2043 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2044 + "unprocessed list", vpnInterface.getName(),
2045 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2048 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2049 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2054 public void vpnInstanceIsReady(String vpnInstanceName) {
2055 processSavedInterfaces(vpnInstanceName, true);
2058 public void vpnInstanceFailed(String vpnInstanceName) {
2059 processSavedInterfaces(vpnInstanceName, false);
2062 private static class UnprocessedVpnInterfaceData {
2063 InstanceIdentifier<VpnInterface> identifier;
2064 VpnInterface vpnInterface;
2066 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2067 this.identifier = identifier;
2068 this.vpnInterface = vpnInterface;
2072 public int hashCode() {
2073 final int prime = 31;
2075 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2076 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2081 public boolean equals(Object obj) {
2088 if (getClass() != obj.getClass()) {
2091 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2092 if (identifier == null) {
2093 if (other.identifier != null) {
2096 } else if (!identifier.equals(other.identifier)) {
2099 if (vpnInterface == null) {
2100 if (other.vpnInterface != null) {
2103 } else if (!vpnInterface.equals(other.vpnInterface)) {
2110 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2111 String primaryRd = vpnUtil.getVpnRd(vpnName);
2112 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
2113 if (vpnInstanceOpData == null) {
2116 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2117 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2120 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2121 vpnToDpnLists.forEach(vpnToDpnList -> {
2122 if (vpnToDpnList.getVpnInterfaces() == null) {
2125 vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2127 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2128 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2129 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = SingleTransactionDataBroker
2130 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2131 if (!vpnInterfaceOptional.isPresent()) {
2134 List<Adjacency> configVpnAdjacencies = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(
2135 vpnInterface.getInterfaceName());
2136 if (configVpnAdjacencies == null) {
2137 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2140 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2141 .augmentation(AdjacenciesOp.class).getAdjacency();
2142 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2143 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2144 // in operational DS. These unprocessed adjacencies will be handled below.
2145 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in
2146 // operational DS are retrieved which is used to call addNewAdjToVpnInterface method.
2147 configVpnAdjacencies.stream()
2148 .filter(adjacency -> operationVpnAdjacencies.stream()
2149 .noneMatch(operationalAdjacency ->
2150 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2151 .forEach(adjacency -> {
2152 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2153 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2155 // TODO Deal with sequencing — the config tx must only submitted
2156 // if the oper tx goes in
2157 if (vpnUtil.isAdjacencyEligibleToVpn(adjacency, vpnName)) {
2158 List<ListenableFuture<Void>> futures = new ArrayList<>();
2159 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx ->
2160 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
2161 confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId,
2162 primaryRd, adjacency, vpnInterfaceOptional.get()
2163 .getDpnId(), confTx, operTx)))));
2166 return Collections.emptyList();
2170 } catch (ReadFailedException e) {
2171 LOG.error("updateVpnInterfacesForUnProcessAdjancencies: Failed to read data store for vpn {} rd {}",
2172 vpnName, primaryRd);
2178 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2179 private final String interfaceName;
2180 private final boolean add;
2181 private final String txnDestination;
2183 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2184 this.interfaceName = interfaceName;
2186 this.txnDestination = transactionDest;
2190 public void onSuccess(Void voidObj) {
2192 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2193 interfaceName, txnDestination);
2195 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2200 public void onFailure(Throwable throwable) {
2202 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2203 interfaceName, txnDestination, throwable);
2205 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2206 vpnUtil.unsetScheduledToRemoveForVpnInterface(interfaceName);