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;
130 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
132 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
133 new ConcurrentHashMap<>();
135 private final InstanceIdDataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
138 public VpnInterfaceManager(final DataBroker dataBroker,
139 final IBgpManager bgpManager,
140 final IdManagerService idManager,
141 final IMdsalApiManager mdsalManager,
142 final IFibManager fibManager,
143 final OdlInterfaceRpcService ifaceMgrRpcService,
144 final VpnFootprintService vpnFootprintService,
145 final IInterfaceManager interfaceManager,
146 final IVpnManager vpnManager,
147 final ArpResponderHandler arpResponderHandler,
148 final JobCoordinator jobCoordinator,
149 final CacheProvider cacheProvider) {
150 super(VpnInterface.class, VpnInterfaceManager.class);
152 this.dataBroker = dataBroker;
153 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
154 this.bgpManager = bgpManager;
155 this.idManager = idManager;
156 this.mdsalManager = mdsalManager;
157 this.fibManager = fibManager;
158 this.ifaceMgrRpcService = ifaceMgrRpcService;
159 this.vpnFootprintService = vpnFootprintService;
160 this.interfaceManager = interfaceManager;
161 this.vpnManager = vpnManager;
162 this.arpResponderHandler = arpResponderHandler;
163 this.jobCoordinator = jobCoordinator;
165 vpnInstanceOpDataEntryCache = new InstanceIdDataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
166 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
167 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
170 public Runnable isNotifyTaskQueued(String intfName) {
171 return vpnIntfMap.remove(intfName);
175 public void start() {
176 LOG.info("{} start", getClass().getSimpleName());
177 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
182 public void close() {
184 vpnInstanceOpDataEntryCache.close();
188 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
189 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
193 protected VpnInterfaceManager getDataTreeChangeListener() {
194 return VpnInterfaceManager.this;
198 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
199 LOG.info("add: intfName {} onto vpnName {}",
200 vpnInterface.getName(),
201 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
202 addVpnInterface(identifier, vpnInterface, null, null);
205 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
206 final VpnInterface vpnInterface, String vpnName) {
207 synchronized (vpnName.intern()) {
208 if (isVpnInstanceReady(vpnName)) {
211 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
216 // TODO Clean up the exception handling
217 @SuppressWarnings("checkstyle:IllegalCatch")
218 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
219 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
220 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
221 String vpnName = vpnInterfaceVpnInstance.getVpnName();
222 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
226 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
227 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
228 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
229 final String interfaceName = key.getName();
231 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
232 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
233 vpnName, vpnInterface.getName());
236 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
237 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
238 List<Adjacency> copyOldAdjs = null;
239 if (oldAdjs != null) {
240 copyOldAdjs = new ArrayList<>();
241 copyOldAdjs.addAll(oldAdjs);
243 List<Adjacency> copyNewAdjs = null;
244 if (newAdjs != null) {
245 copyNewAdjs = new ArrayList<>();
246 copyNewAdjs.addAll(newAdjs);
248 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
251 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
252 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
253 final List<Adjacency> newAdjs,
254 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
255 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
256 final String interfaceName = key.getName();
257 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
258 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
259 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
260 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
261 if (interfaceState != null) {
263 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
264 final int ifIndex = interfaceState.getIfIndex();
265 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName, () -> {
266 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
267 // (the inventory tx goes in last)
268 List<ListenableFuture<Void>> futures = new ArrayList<>();
269 ListenableFuture<Void> confFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
270 confTx -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
271 operTx -> futures.add(
272 txRunner.callWithNewWriteOnlyTransactionAndSubmit(invTx -> {
274 "addVpnInterface: VPN Interface add event - intfName {} vpnName {}"
276 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
277 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false,
278 confTx, operTx, invTx, interfaceState, vpnName);
279 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
280 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
281 + " Update for swapping VPN {} case.", interfaceName, vpnName);
282 if (newAdjs != null) {
283 for (Adjacency adj : newAdjs) {
284 if (oldAdjs.contains(adj)) {
287 if (!isBgpVpnInternetVpn
288 || VpnUtil.isAdjacencyEligibleToVpnInternet(
290 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier,
291 primaryRd, adj, dpnId, operTx, confTx);
296 for (Adjacency adj : oldAdjs) {
297 if (!isBgpVpnInternetVpn
298 || VpnUtil.isAdjacencyEligibleToVpnInternet(
300 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
306 futures.add(confFuture);
307 Futures.addCallback(confFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"),
308 MoreExecutors.directExecutor());
309 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
310 + " processed successfully", interfaceName, vpnName, dpnId);
313 } catch (NumberFormatException | IllegalStateException e) {
314 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
315 + "interface {}. Interface addition on vpn {} failed", interfaceName,
319 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
320 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(),
322 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
323 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
325 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
326 vpnName, vpnInterface.getDpnId());
328 ListenableFutures.addErrorLogging(future, LOG,
329 "Error creating FIB entry for interface {} on VPN {}", vpnInterface.getName(), vpnName);
330 return Collections.singletonList(future);
333 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
334 + " is not available", interfaceName, vpnName);
337 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
338 + " as vpn is pending delete", interfaceName, vpnName,
339 vpnInterface.getDpnId());
343 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
344 // see comments below.
345 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
346 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
347 final int lportTag, boolean isInterfaceUp,
348 WriteTransaction writeConfigTxn,
349 WriteTransaction writeOperTxn,
350 WriteTransaction writeInvTxn,
351 Interface interfaceState,
352 final String vpnName) {
353 final String interfaceName = vpnInterface.getName();
354 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
355 interfaceName, vpnName);
356 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
357 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
358 if (!isInterfaceUp) {
359 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
360 interfaceName, dpId, vpnName);
361 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
362 if (vpnId == VpnConstants.INVALID_ID) {
363 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
364 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
369 boolean waitForVpnInterfaceOpRemoval = false;
370 if (opVpnInterface != null && !opVpnInterface.isScheduledForRemove()) {
371 String opVpnName = opVpnInterface.getVpnInstanceName();
372 String primaryInterfaceIp = null;
373 if (opVpnName.equals(vpnName)) {
374 // Please check if the primary VRF Entry does not exist for VPNInterface
375 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
377 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
378 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
380 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
381 + " for this vpn interface could not be obtained", interfaceName, dpId,
385 for (Adjacency adj : adjs) {
386 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
387 primaryInterfaceIp = adj.getIpAddress();
391 if (primaryInterfaceIp == null) {
392 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
393 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
397 // Get the rd of the vpn instance
398 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, primaryRd, primaryInterfaceIp);
400 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
401 + " bailing out from here.", interfaceName, dpId, vpnName);
404 waitForVpnInterfaceOpRemoval = true;
406 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
407 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
410 if (!waitForVpnInterfaceOpRemoval) {
411 // Add the VPNInterface and quit
412 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
413 null/*ipAddressSourceValuePair*/,
415 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
416 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
417 if (!isBgpVpnInternetVpn) {
418 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false /*isTunnelInterface*/,
421 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
423 if (interfaceManager.isExternalInterface(interfaceName)) {
424 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
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(txRunner, 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, dataBroker, false/*isTunnelInterface*/, jobCoordinator);
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, vpnId, dpId,
474 lportTag, writeInvTxn, 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(
500 dataBroker, adjacency)) {
503 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
504 dpId, writeOperTxn, writeConfigTxn);
506 } catch (ReadFailedException e) {
507 LOG.error("processVpnInterfaceUp: Failed to read data store for interface {} vpn {} rd {} dpn {}",
508 interfaceName, vpnName, primaryRd, dpId);
513 private void processExternalVpnInterface(String interfaceName, String vpnName, long vpnId, BigInteger dpId,
514 int lportTag, WriteTransaction writeInvTxn, int addOrRemove) {
517 // vpn instance of ext-net interface is the network-id
518 extNetworkId = new Uuid(vpnName);
519 } catch (IllegalArgumentException e) {
520 LOG.error("processExternalVpnInterface: VPN instance {} is not Uuid. Processing external vpn interface {}"
521 + " on dpn {} failed", vpnName, interfaceName, dpId);
525 List<Uuid> routerIds = VpnUtil.getExternalNetworkRouterIds(dataBroker, extNetworkId);
526 if (routerIds == null || routerIds.isEmpty()) {
527 LOG.info("processExternalVpnInterface: No router is associated with {}."
528 + " Bailing out of processing external vpn interface {} on dpn {} for vpn {}",
529 extNetworkId.getValue(), interfaceName, dpId, vpnName);
533 LOG.info("processExternalVpnInterface: Router-ids {} associated with exernal vpn-interface {} on dpn {}"
534 + " for vpn {}", routerIds, interfaceName, dpId, vpnName);
535 for (Uuid routerId : routerIds) {
536 String routerName = routerId.getValue();
537 BigInteger primarySwitch = VpnUtil.getPrimarySwitchForRouter(dataBroker, routerName);
538 if (Objects.equals(primarySwitch, dpId)) {
539 Routers router = VpnUtil.getExternalRouter(dataBroker, routerName);
540 if (router != null) {
541 if (addOrRemove == NwConstants.ADD_FLOW) {
542 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
543 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
544 dpId, interfaceName, lportTag, writeInvTxn);
546 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
547 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
548 dpId, interfaceName, lportTag);
551 LOG.error("processExternalVpnInterface: No external-router found for router-id {}. Bailing out of"
552 + " processing external vpn-interface {} on dpn {} for vpn {}", routerName,
553 interfaceName, dpId, vpnName);
559 // TODO Clean up the exception handling
560 @SuppressWarnings("checkstyle:IllegalCatch")
561 private void advertiseAdjacenciesForVpnToBgp(final String rd, BigInteger dpnId,
562 final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
563 String vpnName, String interfaceName) {
565 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} on dpn {} in vpn {}",
566 interfaceName, dpnId, vpnName);
569 if (rd.equals(vpnName)) {
570 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} on dpn {}"
571 + " as it is in internal vpn{} with rd {}", interfaceName, dpnId, vpnName, rd);
575 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} on dpn {} in vpn {} with rd {} ",
576 interfaceName, dpnId, vpnName, rd);
578 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
579 if (nextHopIp == null) {
580 LOG.error("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} on dpn {} is null,"
581 + " returning from advertising route with rd {} vpn {} to bgp", interfaceName, dpnId,
588 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
589 Optional<AdjacenciesOp> adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
590 LogicalDatastoreType.OPERATIONAL, path);
591 if (adjacencies.isPresent()) {
592 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
593 if (!nextHops.isEmpty()) {
594 LOG.debug("advertiseAdjacenciesForVpnToBgp: NextHops are {} for interface {} on dpn {} for vpn {}"
595 + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
596 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
597 long l3vni = vpnInstanceOpData.getL3vni();
598 VrfEntry.EncapType encapType = VpnUtil.isL3VpnOverVxLan(l3vni)
599 ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
600 for (Adjacency nextHop : nextHops) {
601 if (nextHop.getAdjacencyType() == AdjacencyType.ExtraRoute) {
604 String gatewayMac = null;
606 if (VpnUtil.isL3VpnOverVxLan(l3vni)) {
607 final VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
608 vpnInstanceOpData.getVpnInstanceName(), nextHop.getIpAddress());
609 gatewayMac = arpResponderHandler.getGatewayMacAddressForInterface(gwPort, interfaceName)
612 label = nextHop.getLabel();
615 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Adding Fib Entry rd {} prefix {}"
616 + " nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
617 bgpManager.advertisePrefix(rd, nextHop.getMacAddress(), nextHop.getIpAddress(), nextHopIp,
618 encapType, (int)label, l3vni, 0 /*l2vni*/,
620 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Added Fib Entry rd {} prefix {}"
621 + " nexthop {} label {} for interface {} on dpn {} for vpn {}", rd,
622 nextHop.getIpAddress(), nextHopIp, label, interfaceName, dpnId, vpnName);
623 } catch (Exception e) {
624 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to advertise prefix {} in vpn {}"
625 + " with rd {} for interface {} on dpn {}", nextHop.getIpAddress(), vpnName, rd,
626 interfaceName, dpnId, e);
631 } catch (ReadFailedException e) {
632 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to read data store for interface {} dpn {} nexthop {}"
633 + "vpn {} rd {}", interfaceName, dpnId, nextHopIp, vpnName, rd);
637 // TODO Clean up the exception handling
638 @SuppressWarnings("checkstyle:IllegalCatch")
639 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
640 String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
642 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
643 String rd = VpnUtil.getVpnRd(dataBroker, 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);
690 } catch (Exception e) {
691 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
692 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
699 @SuppressWarnings("checkstyle:IllegalCatch")
700 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
701 String primaryRd, String interfaceName, final long vpnId,
702 WriteTransaction writeConfigTxn,
703 WriteTransaction writeOperTxn,
704 final WriteTransaction writeInvTxn,
705 Interface interfaceState) {
706 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
708 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
709 Optional<Adjacencies> adjacencies = Optional.absent();
711 adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
713 } catch (ReadFailedException e) {
714 LOG.error("processVpnInterfaceAdjacencies: Failed to read data store for interface {} vpn {} rd {}"
715 + "dpn {}", interfaceName, vpnName, primaryRd, dpnId);
717 if (!adjacencies.isPresent()) {
718 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
719 null/*gwMac*/, writeOperTxn);
722 // Get the rd of the vpn instance
723 String nextHopIp = null;
725 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
726 } catch (Exception e) {
727 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
728 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
730 List<String> nhList = new ArrayList<>();
731 if (nextHopIp != null) {
732 nhList.add(nextHopIp);
733 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
734 interfaceName, dpnId, vpnName, nhList);
736 Optional<String> gwMac = Optional.absent();
737 String vpnInterfaceSubnetGwMacAddress = null;
738 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
739 Long l3vni = vpnInstanceOpData.getL3vni();
740 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
741 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
742 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
743 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
744 List<Adjacency> value = new ArrayList<>();
745 for (Adjacency nextHop : nextHops) {
746 String rd = primaryRd;
747 String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
748 if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
749 && NWUtil.isIpv4Address(nexthopIpValue)) {
750 String prefix = nextHop.getIpAddress() == null ? "null" :
751 VpnUtil.getIpPrefix(nextHop.getIpAddress());
752 LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
753 + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
756 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
757 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
758 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
759 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
760 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
761 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
763 LogicalDatastoreType.OPERATIONAL,
764 VpnUtil.getPrefixToInterfaceIdentifier(
765 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
766 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
768 final Uuid subnetId = nextHop.getSubnetId();
770 String gatewayIp = nextHop.getSubnetGatewayIp();
771 if (gatewayIp == null) {
772 Optional<String> gatewayIpOptional = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
773 if (gatewayIpOptional.isPresent()) {
774 gatewayIp = gatewayIpOptional.get();
778 if (gatewayIp != null) {
779 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
780 if (gwMac.isPresent()) {
781 // A valid mac-address is available for this subnet-gateway-ip
782 // Use this for programming ARP_RESPONDER table here. And save this
783 // info into vpnInterface operational, so it can used in VrfEntryProcessor
784 // to populate L3_GW_MAC_TABLE there.
785 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
786 gatewayIp, gwMac.get());
787 vpnInterfaceSubnetGwMacAddress = gwMac.get();
789 // A valid mac-address is not available for this subnet-gateway-ip
790 // Use the connected-mac-address to configure ARP_RESPONDER Table.
791 // Save this connected-mac-address as gateway-mac-address for the
792 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
793 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
794 if (gwMac.isPresent()) {
795 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
796 vpnId, writeInvTxn, NwConstants.ADD_FLOW, gwMac.get());
797 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
798 gatewayIp, gwMac.get());
800 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
801 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
803 subnetId, interfaceName, vpnName, gatewayIp);
807 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
808 + "cannot create ARP responder flow for interface name {}, vpnName {}",
809 subnetId, interfaceName, vpnName);
810 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
812 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
813 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
815 //Extra route adjacency
816 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
817 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
818 synchronized (vpnPrefixKey.intern()) {
819 java.util.Optional<String> rdToAllocate = VpnUtil
820 .allocateRdForExtraRouteAndUpdateUsedRdsMap(dataBroker, vpnId, null,
821 prefix, vpnName, nextHop.getNextHopIpList().get(0), dpnId);
822 if (rdToAllocate.isPresent()) {
823 rd = rdToAllocate.get();
824 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
827 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
831 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
832 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
833 interfaceName, dpnId);
835 // Please note that primary adjacency will use a subnet-gateway-mac-address that
836 // can be different from the gateway-mac-address within the VRFEntry as the
837 // gateway-mac-address is a superset.
838 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
839 : RouteOrigin.STATIC;
840 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
841 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
842 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
843 Adjacency operationalAdjacency = null;
845 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
846 } catch (NullPointerException e) {
847 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
848 input, e.getMessage());
851 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
852 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
853 vpnName, l3vni, origin,
854 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
856 value.add(operationalAdjacency);
859 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
860 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
861 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
863 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
864 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
865 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
867 for (Adjacency nextHop : aug.getAdjacency()) {
868 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
869 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
870 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
871 : RouteOrigin.STATIC;
872 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
873 registeredPopulator.populateFib(input, writeConfigTxn);
878 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
879 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
880 VpnInterfaceOpDataEntry opInterface =
881 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, Boolean.FALSE, lportTag, gwMac);
882 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
883 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
884 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
885 WriteTransaction.CREATE_MISSING_PARENTS);
886 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
887 interfaceName, dpnId, vpnName);
890 // TODO Clean up the exception handling
891 @SuppressWarnings("checkstyle:IllegalCatch")
892 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
893 StateTunnelList stateTunnelList,
894 WriteTransaction writeConfigTxn,
895 WriteTransaction writeOperTxn) {
897 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
898 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
899 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
900 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
901 if (adjList.isEmpty()) {
902 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
903 vpnInterface, srcDpnId);
906 String prefix = null;
908 List<Adjacency> value = new ArrayList<>();
909 boolean isNextHopAddReqd = false;
910 String vpnName = vpnInterface.getVpnInstanceName();
911 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
912 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
913 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
914 vpnInterface.getName(), vpnInterface.getDpnId(),
915 vpnInterface.getVpnInstanceName(), adjList);
916 for (Adjacency adj : adjList) {
917 String rd = adj.getVrfId();
918 rd = rd != null ? rd : vpnName;
919 prefix = adj.getIpAddress();
920 label = adj.getLabel();
921 List<String> nhList = Collections.singletonList(srcTepIp);
922 List<String> nextHopList = adj.getNextHopIpList();
923 // If TEP is added , update the nexthop of primary adjacency.
924 // Secondary adj nexthop is already pointing to primary adj IP address.
925 if (nextHopList != null && !nextHopList.isEmpty()) {
926 /* everything right already */
928 isNextHopAddReqd = true;
931 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
932 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
934 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
935 if (!vrfEntryOptional.isPresent()) {
938 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
939 if (!nhList.contains(srcTepIp)) {
940 nhList.add(srcTepIp);
941 isNextHopAddReqd = true;
946 if (isNextHopAddReqd) {
947 updateLabelMapper(label, nhList);
948 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
949 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
950 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
951 // Update the VRF entry with nextHop
952 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
953 label, true, writeConfigTxn);
955 //Get the list of VPN's importing this route(prefix) .
956 // Then update the VRF entry with nhList
957 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
958 VpnUtil.getVpnsImportingMyRoute(dataBroker, 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(dataBroker, vpnName);
1017 String primaryRd = VpnUtil.getVpnRd(dataBroker, 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 =
1063 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1064 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1065 String vpnRd = vpn.getVrfId();
1066 if (vpnRd != null) {
1067 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1068 srcTepIp, label, false, writeConfigTxn);
1069 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1070 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1071 nhList, label, vpnInterface.getName(), srcDpnId,
1073 vpn.getVpnInstanceName(), vpnRd);
1077 // Withdraw prefix from BGP only for external vpn.
1079 if (!rd.equalsIgnoreCase(vpnName)) {
1080 bgpManager.withdrawPrefix(rd, prefix);
1082 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1083 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1084 vpnInterface.getName(), srcDpnId,
1086 } catch (Exception ex) {
1087 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1088 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
1089 vpnInterface.getName(), srcDpnId, vpnName, ex);
1093 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1094 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1095 .withKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1096 .addAugmentation(AdjacenciesOp.class, aug).build();
1097 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1098 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1099 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1100 WriteTransaction.CREATE_MISSING_PARENTS);
1101 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1102 vpnInterface.getName(), srcDpnId, vpnName);
1106 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1107 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1109 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1110 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
1111 if (vpnInstanceOpDataEntry == null) {
1112 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1113 + " to check for vpns exporting the routes", vpnName);
1114 return vpnsToExportRoute;
1117 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1118 if (input.getVpnInstanceName() == null) {
1119 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1123 return !input.getVpnInstanceName().equals(vpnName);
1126 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1127 Iterable<String> commonRTs =
1128 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1129 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1130 return Iterators.size(commonRTs.iterator()) > 0;
1134 VpnUtil.getAllVpnInstanceOpData(dataBroker).stream().filter(excludeVpn).filter(matchRTs).collect(
1135 Collectors.toList());
1136 return vpnsToExportRoute;
1139 // TODO Clean up the exception handling
1140 @SuppressWarnings("checkstyle:IllegalCatch")
1141 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1142 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1143 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1144 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getVrfId());
1145 if (vrfEntries != null) {
1146 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1147 for (VrfEntry vrfEntry : vrfEntries) {
1149 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1150 RouteOrigin.value(vrfEntry.getOrigin()))) {
1151 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1152 + " is not a controller managed non intervpn link route. Ignoring.",
1153 vpn.getVrfId(), vrfEntry.getDestPrefix());
1156 String prefix = vrfEntry.getDestPrefix();
1157 String gwMac = vrfEntry.getGatewayMacAddress();
1158 vrfEntry.getRoutePaths().forEach(routePath -> {
1159 String nh = routePath.getNexthopAddress();
1160 int label = routePath.getLabel().intValue();
1161 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1162 vrfEntry.getOrigin()))) {
1163 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1164 + " nexthop {} label {} to vpn {} vpnRd {}",
1165 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1166 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1167 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1168 0 /*l3vni*/, gwMac, vpn.getVrfId(), RouteOrigin.SELF_IMPORTED,
1171 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} "
1172 + "prefix {} nexthop {} label {} to vpn {} vpnRd {}",
1173 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1174 SubnetRoute route = vrfEntry.augmentation(SubnetRoute.class);
1175 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, vpn.getVrfId(),
1179 } catch (RuntimeException e) {
1180 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1181 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1182 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1185 }), LOG, "Error handing VPN exporting routes");
1187 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1188 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1194 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1195 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1196 final String interfaceName = key.getName();
1197 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1198 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1199 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1203 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1204 final VpnInterface vpnInterface, final String vpnName,
1205 final String interfaceName) {
1206 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1207 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
1208 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1209 deleteFibEntryForRouterInterface(vpnInterface, confTx, vpnName);
1210 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1212 ListenableFutures.addErrorLogging(future, LOG, "Error removing call for interface {} on VPN {}",
1213 vpnInterface.getName(), vpnName);
1214 return Collections.singletonList(future);
1215 }, DJC_MAX_RETRIES);
1217 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1218 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1222 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1223 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1224 final VpnInterface vpnInterface, final String vpnName,
1225 final String interfaceName, final Interface interfaceState) {
1226 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1227 vpnName, vpnInterface.getDpnId());
1228 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1229 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1231 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1232 ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1233 writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1234 writeOperTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1235 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1236 interfaceName, vpnName);
1237 BigInteger dpId = BigInteger.ZERO;
1239 String gwMacAddress = null;
1240 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1241 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1242 Optional<VpnInterfaceOpDataEntry> optVpnInterface = Optional.absent();
1244 optVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1245 LogicalDatastoreType.OPERATIONAL, interfaceId);
1246 } catch (ReadFailedException e) {
1247 LOG.error("remove: Failed to read data store for interface {} vpn {}", interfaceName,
1251 if (interfaceState != null) {
1253 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1254 } catch (NumberFormatException | IllegalStateException e) {
1255 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1256 + " data store for interface {} on dpn {} for vpn {} Fetching"
1257 + " from vpn interface op data store. ", interfaceName,
1258 vpnInterface.getDpnId(), vpnName, e);
1259 dpId = BigInteger.ZERO;
1261 ifIndex = interfaceState.getIfIndex();
1262 gwMacAddress = interfaceState.getPhysAddress().getValue();
1264 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1265 + " from vpn interface op.", interfaceName);
1266 if (optVpnInterface.isPresent()) {
1267 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1268 dpId = vpnOpInterface.getDpnId();
1269 ifIndex = vpnOpInterface.getLportTag().intValue();
1270 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1272 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1273 + " as interfaceState and vpn interface op is not"
1274 + " available", interfaceName, vpnName);
1278 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1279 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1280 writeConfigTxn, writeOperTxn, writeInvTxn);
1282 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1284 interfaceName, vpnInterface.getDpnId(), vpnName);
1286 futures.add(configFuture);
1287 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1289 }, DJC_MAX_RETRIES);
1292 protected void processVpnInterfaceDown(BigInteger dpId,
1293 String interfaceName,
1296 VpnInterfaceOpDataEntry vpnOpInterface,
1297 boolean isInterfaceStateDown,
1298 WriteTransaction writeConfigTxn,
1299 WriteTransaction writeOperTxn,
1300 WriteTransaction writeInvTxn) {
1301 if (vpnOpInterface == null) {
1302 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1303 + " as it is not available in operational data store", interfaceName, dpId);
1306 final String vpnName = vpnOpInterface.getVpnInstanceName();
1307 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1308 interfaceName, vpnName);
1309 if (!isInterfaceStateDown) {
1310 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1311 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1313 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1314 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1315 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1316 if (interfaceManager.isExternalInterface(interfaceName)) {
1317 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1318 NwConstants.DEL_FLOW);
1320 if (!isBgpVpnInternetVpn) {
1321 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1323 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1324 + " successful", interfaceName, dpId, vpnName);
1326 // Interface is retained in the DPN, but its Link Down.
1327 // Only withdraw the prefixes for this interface from BGP
1328 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1332 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1333 final String vpnName, final long vpnId, String gwMac,
1334 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1335 final WriteTransaction writeInvTxn) {
1338 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1339 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1340 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1341 Optional<AdjacenciesOp> adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1342 LogicalDatastoreType.OPERATIONAL, path);
1343 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1344 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1345 interfaceName, dpnId, vpnName, primaryRd);
1346 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1347 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1348 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1349 interfaceName, dpnId, vpnName, nextHops);
1350 for (Adjacency nextHop : nextHops) {
1351 if (nextHop.isPhysNetworkFunc()) {
1352 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1353 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1354 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1355 null/*writeCfgTxn*/);
1357 String rd = nextHop.getVrfId();
1358 List<String> nhList;
1359 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1360 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1362 // This is a primary adjacency
1363 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1364 : Collections.emptyList();
1365 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1366 interfaceName, writeInvTxn);
1368 if (!nhList.isEmpty()) {
1369 if (rd.equals(vpnName)) {
1370 //this is an internal vpn - the rd is assigned to the vpn instance name;
1371 //remove from FIB directly
1372 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1373 interfaceName, dpnId, writeConfigTxn));
1375 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
1376 interfaceName, writeConfigTxn);
1379 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1380 + " interface {}", nextHop.getIpAddress(), rd,
1381 nextHop.getAdjacencyType().toString(), interfaceName);
1382 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1383 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1386 String ip = nextHop.getIpAddress().split("/")[0];
1387 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1388 if (vpnVipToPort != null) {
1389 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip, null);
1390 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed LearntVpnVipToPort entry"
1391 + " for Interface {} ip {} on dpn {} for vpn {}",
1392 vpnVipToPort.getPortName(), ip, dpnId, vpnName);
1394 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ip);
1395 if (vpnPortipToPort != null) {
1396 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip, null);
1397 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed vpnPortipToPort entry for "
1398 + "Interface {} ip {} on dpn {} for vpn {}",
1399 vpnPortipToPort.getPortName(), ip, dpnId, vpnName);
1403 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1404 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1405 + " Removing it.", interfaceName, vpnName, dpnId);
1406 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1408 } catch (ReadFailedException e) {
1409 LOG.error("removeAdjacenciesFromVpn: Failed to read data store for interface {} dpn {} vpn {}",
1410 interfaceName, dpnId, vpnName);
1414 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1415 String interfaceName, BigInteger dpnId,
1416 WriteTransaction writeConfigTxn) {
1418 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1420 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1421 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1422 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1426 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1427 BigInteger dpnId, String rd, String interfaceName,
1428 WriteTransaction writeConfigTxn) {
1429 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1430 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1431 nhList.forEach((nh) -> {
1432 //IRT: remove routes from other vpns importing it
1433 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1434 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1435 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1436 String vpnRd = vpn.getVrfId();
1437 if (vpnRd != null) {
1438 fibManager.removeOrUpdateFibEntry(vpnRd,
1439 nextHop.getIpAddress(), nh, writeConfigTxn);
1440 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1441 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1442 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1443 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1449 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1450 int lportTag, String gwMac, String interfaceName,
1451 WriteTransaction writeInvTxn) {
1452 final Uuid subnetId = nextHop.getSubnetId();
1453 if (nextHop.getSubnetGatewayMacAddress() == null) {
1454 // A valid mac-address was not available for this subnet-gateway-ip
1455 // So a connected-mac-address was used for this subnet and we need
1456 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1457 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1458 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1460 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1464 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1465 String interfaceName) {
1466 // This is either an extra-route (or) a learned IP via subnet-route
1467 List<String> nhList = null;
1468 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1469 if (nextHopIp == null || nextHopIp.isEmpty()) {
1470 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1471 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1472 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1474 nhList = Collections.emptyList();
1476 nhList = Collections.singletonList(nextHopIp);
1481 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1482 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1483 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1484 // else use connected interface
1485 if (gwPort != null && gwPort.isSubnetIp()) {
1486 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1487 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1488 return Optional.of(gwPort.getMacAddress());
1490 return Optional.absent();
1494 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1495 final VpnInterface update) {
1496 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1497 update.getDpnId(), original.getVpnInstanceNames(),
1498 update.getVpnInstanceNames());
1499 final String vpnInterfaceName = update.getName();
1500 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1501 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1502 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1503 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1504 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1505 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1506 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1508 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1509 //handles switching between <internal VPN - external VPN>
1510 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1511 LOG.info("update: handled VPNInterface {} on dpn {} update"
1512 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1513 original.getName(), dpnId,
1514 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1515 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1518 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1519 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1520 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1521 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1522 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1523 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1524 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1525 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
1526 List<ListenableFuture<Void>> futures = new ArrayList<>();
1527 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1528 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(operTx -> {
1529 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1530 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1531 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1532 update.getName(), newVpnName);
1533 //handle both addition and removal of adjacencies
1534 //currently, new adjacency may be an extra route
1535 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1536 if (!oldAdjs.equals(newAdjs)) {
1537 for (Adjacency adj : copyNewAdjs) {
1538 if (copyOldAdjs.contains(adj)) {
1539 copyOldAdjs.remove(adj);
1541 // add new adjacency - right now only extra route will hit this path
1542 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker,
1544 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1545 dpnId, operTx, confTx);
1547 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
1548 + " vpn interface {} on vpn {} dpnId {}",
1549 adj.getIpAddress(), adj.getNextHopIpList(),
1550 adj.getLabel(), adj.getSubnetId(), update.getName(),
1554 for (Adjacency adj : copyOldAdjs) {
1555 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker,
1557 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
1558 && !adj.isPhysNetworkFunc()) {
1559 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1561 Optional<VpnInterfaceOpDataEntry> optVpnInterface = operTx.read(
1562 LogicalDatastoreType.OPERATIONAL, vpnInterfaceOpIdentifier).get();
1563 if (optVpnInterface.isPresent()) {
1564 VpnInterfaceOpDataEntry vpnInterfaceOpDataEntry = optVpnInterface.get();
1565 long vpnId = VpnUtil.getVpnId(dataBroker, newVpnName);
1566 VpnUtil.removePrefixToInterfaceAdj(dataBroker, adj, vpnId,
1567 vpnInterfaceOpDataEntry, operTx);
1569 LOG.info("Vpninterface {} not present in Operational",
1573 String vpnRd = VpnUtil.getVpnRd(dataBroker, newVpnName);
1574 LOG.debug("update: remove prefix {} from the FIB and BGP entry "
1575 + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
1577 fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
1578 if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
1579 bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
1582 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1586 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1587 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
1588 .getNextHopIpList(),
1589 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1594 for (ListenableFuture<Void> future : futures) {
1595 ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
1596 update.getName(), update.getVpnInstanceNames());
1601 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1602 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1607 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1608 VpnInterface original, VpnInterface update) {
1609 boolean isSwap = Boolean.FALSE;
1610 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1611 final String interfaceName = key.getName();
1612 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1613 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1614 List<String> oldVpnListCopy = new ArrayList<>();
1615 oldVpnListCopy.addAll(oldVpnList);
1616 List<String> newVpnList = update.getVpnInstanceNames().stream()
1617 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1618 oldVpnList.removeAll(newVpnList);
1619 newVpnList.removeAll(oldVpnListCopy);
1620 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1621 for (String oldVpnName: oldVpnList) {
1622 isSwap = Boolean.TRUE;
1623 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1624 + " running config-driven swap removal", interfaceName, oldVpnName);
1625 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1626 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1627 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1629 //Wait for previous interface bindings to be removed
1632 } catch (InterruptedException e) {
1635 for (String newVpnName: newVpnList) {
1636 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1637 isSwap = Boolean.TRUE;
1638 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1639 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1640 + "running config-driven swap addition", interfaceName, newVpnName);
1641 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1642 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1643 ? origAdjs.getAdjacency() : new ArrayList<>();
1644 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1645 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1646 ? updateAdjs.getAdjacency() : new ArrayList<>();
1648 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1649 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1650 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1651 interfaceName, oldVpnListCopy, newVpnName);
1658 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1660 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1661 synchronized (label.toString().intern()) {
1662 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1663 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1664 Optional<LabelRouteInfo> opResult = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1665 LogicalDatastoreType.OPERATIONAL, lriIid);
1666 if (opResult.isPresent()) {
1667 LabelRouteInfo labelRouteInfo =
1668 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1669 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid,
1670 labelRouteInfo, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
1673 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label,
1675 } catch (ReadFailedException e) {
1676 LOG.error("updateLabelMapper: Failed to read data store for label {} nexthopList {}", label,
1678 } catch (TransactionCommitFailedException e) {
1679 LOG.error("updateLabelMapper: Failed to commit to data store for label {} nexthopList {}", label,
1684 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1685 SubnetRoute route, String parentVpnRd, WriteTransaction writeConfigTxn) {
1687 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1688 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, parentVpnRd)
1689 .addAugmentation(SubnetRoute.class, route).build();
1690 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1691 InstanceIdentifierBuilder<VrfTables> idBuilder =
1692 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1693 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1694 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1695 if (writeConfigTxn != null) {
1696 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1698 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1700 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1701 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1704 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1705 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1706 WriteTransaction writeConfigTxn) {
1707 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1708 String configVpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1710 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker
1711 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1712 if (optVpnInterface.isPresent()) {
1713 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1714 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1715 String vpnName = currVpnIntf.getVpnInstanceName();
1716 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1717 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1718 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1719 LogicalDatastoreType.OPERATIONAL, adjPath);
1720 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1721 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1722 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1723 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1724 List<Adjacency> adjacencies;
1725 if (optAdjacencies.isPresent()) {
1726 adjacencies = optAdjacencies.get().getAdjacency();
1728 // This code will be hit in case of first PNF adjacency
1729 adjacencies = new ArrayList<>();
1731 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1732 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1733 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1734 Adjacency operationalAdjacency = null;
1735 //Handling dual stack neutron port primary adjacency
1736 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency && !adj.isPhysNetworkFunc()) {
1737 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to existing interface {} for vpn {}", prefix,
1738 currVpnIntf.getName(), vpnName);
1739 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,
1740 currVpnIntf.getName());
1741 if (interfaceState != null) {
1742 processVpnInterfaceAdjacencies(dpnId, currVpnIntf.getLportTag().intValue(), vpnName, primaryRd,
1743 currVpnIntf.getName(),
1744 vpnId, writeConfigTxn, writeOperTxn, null, interfaceState);
1747 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()
1748 && adj.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1749 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1750 : RouteOrigin.STATIC;
1751 String nh = adj.getNextHopIpList().get(0);
1752 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1753 synchronized (vpnPrefixKey.intern()) {
1754 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1755 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1756 if (rdToAllocate.isPresent()) {
1757 input.setRd(rdToAllocate.get());
1758 operationalAdjacency = populator.createOperationalAdjacency(input);
1759 int label = operationalAdjacency.getLabel().intValue();
1760 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1761 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1762 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1763 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1764 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1765 vpnName, label, currVpnIntf.getName(), dpnId);
1767 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}",
1771 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1772 // Keeping the MPLS check for now.
1773 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1774 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1775 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1776 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1777 vpnsToImportRoute.forEach(vpn -> {
1778 if (vpn.getVrfId() != null) {
1779 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1780 dataBroker, vpn.getVpnId(), vpnId, prefix,
1781 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1783 rds -> vpnManager.addExtraRoute(
1784 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1785 adj.getIpAddress(), nh, rds,
1786 currVpnIntf.getVpnInstanceName(), l3vni,
1787 RouteOrigin.SELF_IMPORTED, currVpnIntf.getName(),
1788 opAdjacency, encapType, writeConfigTxn));
1793 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1794 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1795 currVpnIntf.getName(), vpnName);
1797 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1800 LogicalDatastoreType.OPERATIONAL,
1801 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1802 adj.getSubnetId().getValue()), prefix),
1803 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1804 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1806 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1807 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */,
1808 0 /*l3vni*/, null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1810 input.setRd(adj.getVrfId());
1812 if (operationalAdjacency == null) {
1813 operationalAdjacency = populator.createOperationalAdjacency(input);
1815 adjacencies.add(operationalAdjacency);
1816 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1817 VpnInterfaceOpDataEntry newVpnIntf =
1818 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1819 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1820 currVpnIntf.getGatewayMacAddress());
1822 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1824 } catch (ReadFailedException e) {
1825 LOG.error("addNewAdjToVpnInterface: Failed to read data store for interface {} dpn {} vpn {} rd {} ip "
1826 + "{}", interfaceName, dpnId, configVpnName, primaryRd, adj.getIpAddress());
1830 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1831 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1832 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1835 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1836 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1837 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1838 String vpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1840 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker.syncReadOptional(
1841 dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1842 if (optVpnInterface.isPresent()) {
1843 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1844 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1845 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1846 LogicalDatastoreType.OPERATIONAL, path);
1847 if (optAdjacencies.isPresent()) {
1848 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1850 if (!adjacencies.isEmpty()) {
1851 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1852 Iterator<Adjacency> adjIt = adjacencies.iterator();
1853 while (adjIt.hasNext()) {
1854 Adjacency adjElem = adjIt.next();
1855 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1856 String rd = adjElem.getVrfId();
1858 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1859 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1860 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1861 currVpnIntf.getVpnInstanceName(), aug, dpnId,
1862 currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1863 currVpnIntf.getGatewayMacAddress());
1864 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1865 if (adj.getNextHopIpList() != null) {
1866 for (String nh : adj.getNextHopIpList()) {
1867 deleteExtraRouteFromCurrentAndImportingVpns(
1868 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1869 currVpnIntf.getName(), writeConfigTxn);
1871 } else if (adj.isPhysNetworkFunc()) {
1872 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1873 adj.getIpAddress(), adj.getSubnetId());
1874 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1882 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1883 dpnId, adj.getVrfId());
1885 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1886 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1889 } catch (ReadFailedException e) {
1890 LOG.error("delAdjFromVpnInterface: Failed to read data store for ip {} interface {} dpn {} vpn {}",
1891 adj.getIpAddress(), interfaceName, dpnId, vpnName);
1895 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1896 String rd, String intfName, WriteTransaction writeConfigTxn) {
1897 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1898 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1899 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1900 String vpnRd = vpn.getVrfId();
1901 if (vpnRd != null) {
1902 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(dataBroker, 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(idManager, 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(dataBroker, 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(dataBroker, vpnInstanceName);
2006 if (vpnRd == null) {
2009 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, 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(dataBroker, vpnName);
2112 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, 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 -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2123 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2124 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2125 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = SingleTransactionDataBroker.syncReadOptional(
2126 dataBroker, LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2127 if (!vpnInterfaceOptional.isPresent()) {
2130 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2131 vpnInterface.getInterfaceName());
2132 if (configVpnAdjacencies == null) {
2133 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2136 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2137 .augmentation(AdjacenciesOp.class).getAdjacency();
2138 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2139 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2140 // in operational DS. These unprocessed adjacencies will be handled below.
2141 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2142 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2143 configVpnAdjacencies.stream()
2144 .filter(adjacency -> operationVpnAdjacencies.stream()
2145 .noneMatch(operationalAdjacency ->
2146 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2147 .forEach(adjacency -> {
2148 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2149 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2151 // TODO Deal with sequencing — the config tx must only submitted
2152 // if the oper tx goes in
2153 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2154 List<ListenableFuture<Void>> futures = new ArrayList<>();
2155 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx ->
2156 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
2157 confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId,
2158 primaryRd, adjacency, vpnInterfaceOptional.get()
2159 .getDpnId(), confTx, operTx)))));
2162 return Collections.emptyList();
2166 } catch (ReadFailedException e) {
2167 LOG.error("updateVpnInterfacesForUnProcessAdjancencies: Failed to read data store for vpn {} rd {}",
2168 vpnName, primaryRd);
2173 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2174 private final String interfaceName;
2175 private final boolean add;
2176 private final String txnDestination;
2178 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2179 this.interfaceName = interfaceName;
2181 this.txnDestination = transactionDest;
2185 public void onSuccess(Void voidObj) {
2187 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2188 interfaceName, txnDestination);
2190 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2195 public void onFailure(Throwable throwable) {
2197 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2198 interfaceName, txnDestination, throwable);
2200 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2201 VpnUtil.unsetScheduledToRemoveForVpnInterface(txRunner, interfaceName);