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.NetworkAttributes.NetworkType;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
107 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
108 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
109 import org.slf4j.Logger;
110 import org.slf4j.LoggerFactory;
113 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager> {
115 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
116 private static final short DJC_MAX_RETRIES = 3;
118 private final DataBroker dataBroker;
119 private final ManagedNewTransactionRunner txRunner;
120 private final IBgpManager bgpManager;
121 private final IFibManager fibManager;
122 private final IMdsalApiManager mdsalManager;
123 private final IdManagerService idManager;
124 private final OdlInterfaceRpcService ifaceMgrRpcService;
125 private final VpnFootprintService vpnFootprintService;
126 private final IInterfaceManager interfaceManager;
127 private final IVpnManager vpnManager;
128 private final ArpResponderHandler arpResponderHandler;
129 private final JobCoordinator jobCoordinator;
130 private final VpnUtil vpnUtil;
132 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
134 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
135 new ConcurrentHashMap<>();
137 private final InstanceIdDataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
140 public VpnInterfaceManager(final DataBroker dataBroker,
141 final IBgpManager bgpManager,
142 final IdManagerService idManager,
143 final IMdsalApiManager mdsalManager,
144 final IFibManager fibManager,
145 final OdlInterfaceRpcService ifaceMgrRpcService,
146 final VpnFootprintService vpnFootprintService,
147 final IInterfaceManager interfaceManager,
148 final IVpnManager vpnManager,
149 final ArpResponderHandler arpResponderHandler,
150 final JobCoordinator jobCoordinator,
151 final CacheProvider cacheProvider,
152 final VpnUtil vpnUtil) {
153 super(VpnInterface.class, VpnInterfaceManager.class);
155 this.dataBroker = dataBroker;
156 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
157 this.bgpManager = bgpManager;
158 this.idManager = idManager;
159 this.mdsalManager = mdsalManager;
160 this.fibManager = fibManager;
161 this.ifaceMgrRpcService = ifaceMgrRpcService;
162 this.vpnFootprintService = vpnFootprintService;
163 this.interfaceManager = interfaceManager;
164 this.vpnManager = vpnManager;
165 this.arpResponderHandler = arpResponderHandler;
166 this.jobCoordinator = jobCoordinator;
167 this.vpnUtil = vpnUtil;
169 vpnInstanceOpDataEntryCache = new InstanceIdDataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
170 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
171 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
174 public Runnable isNotifyTaskQueued(String intfName) {
175 return vpnIntfMap.remove(intfName);
179 public void start() {
180 LOG.info("{} start", getClass().getSimpleName());
181 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
186 public void close() {
188 vpnInstanceOpDataEntryCache.close();
192 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
193 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
197 protected VpnInterfaceManager getDataTreeChangeListener() {
198 return VpnInterfaceManager.this;
202 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
203 LOG.info("add: intfName {} onto vpnName {}",
204 vpnInterface.getName(),
205 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
206 addVpnInterface(identifier, vpnInterface, null, null);
209 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
210 final VpnInterface vpnInterface, String vpnName) {
211 synchronized (vpnName.intern()) {
212 if (isVpnInstanceReady(vpnName)) {
215 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
220 // TODO Clean up the exception handling
221 @SuppressWarnings("checkstyle:IllegalCatch")
222 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
223 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
224 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
225 String vpnName = vpnInterfaceVpnInstance.getVpnName();
226 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
230 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
231 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
232 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
233 final String interfaceName = key.getName();
235 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
236 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
237 vpnName, vpnInterface.getName());
240 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
241 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
242 List<Adjacency> copyOldAdjs = null;
243 if (oldAdjs != null) {
244 copyOldAdjs = new ArrayList<>();
245 copyOldAdjs.addAll(oldAdjs);
247 List<Adjacency> copyNewAdjs = null;
248 if (newAdjs != null) {
249 copyNewAdjs = new ArrayList<>();
250 copyNewAdjs.addAll(newAdjs);
252 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
255 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
256 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
257 final List<Adjacency> newAdjs,
258 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
259 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
260 final String interfaceName = key.getName();
261 String primaryRd = vpnUtil.getPrimaryRd(vpnName);
262 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
263 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
264 boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
265 if (interfaceState != null) {
267 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
268 final int ifIndex = interfaceState.getIfIndex();
269 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName, () -> {
270 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
271 // (the inventory tx goes in last)
272 List<ListenableFuture<Void>> futures = new ArrayList<>();
273 ListenableFuture<Void> confFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
274 confTx -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
275 operTx -> futures.add(
276 txRunner.callWithNewWriteOnlyTransactionAndSubmit(invTx -> {
278 "addVpnInterface: VPN Interface add event - intfName {} vpnName {}"
280 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
281 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false,
282 confTx, operTx, invTx, interfaceState, vpnName);
283 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
284 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
285 + " Update for swapping VPN {} case.", interfaceName, vpnName);
286 if (newAdjs != null) {
287 for (Adjacency adj : newAdjs) {
288 if (oldAdjs.contains(adj)) {
291 if (!isBgpVpnInternetVpn
292 || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
293 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier,
294 primaryRd, adj, dpnId, operTx, confTx);
299 for (Adjacency adj : oldAdjs) {
300 if (!isBgpVpnInternetVpn
301 || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
302 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
308 futures.add(confFuture);
309 Futures.addCallback(confFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"),
310 MoreExecutors.directExecutor());
311 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
312 + " processed successfully", interfaceName, vpnName, dpnId);
315 } catch (NumberFormatException | IllegalStateException e) {
316 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
317 + "interface {}. Interface addition on vpn {} failed", interfaceName,
321 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
322 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(),
324 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
325 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
327 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
328 vpnName, vpnInterface.getDpnId());
330 ListenableFutures.addErrorLogging(future, LOG,
331 "Error creating FIB entry for interface {} on VPN {}", vpnInterface.getName(), vpnName);
332 return Collections.singletonList(future);
335 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
336 + " is not available", interfaceName, vpnName);
339 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
340 + " as vpn is pending delete", interfaceName, vpnName,
341 vpnInterface.getDpnId());
345 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
346 // see comments below.
347 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
348 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
349 final int lportTag, boolean isInterfaceUp,
350 WriteTransaction writeConfigTxn,
351 WriteTransaction writeOperTxn,
352 WriteTransaction writeInvTxn,
353 Interface interfaceState,
354 final String vpnName) {
355 final String interfaceName = vpnInterface.getName();
356 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = vpnUtil.getVpnInterfaceOpDataEntry(interfaceName,
358 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
359 boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
360 if (!isInterfaceUp) {
361 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
362 interfaceName, dpId, vpnName);
363 long vpnId = vpnUtil.getVpnId(vpnName);
364 if (vpnId == VpnConstants.INVALID_ID) {
365 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
366 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
371 boolean waitForVpnInterfaceOpRemoval = false;
372 if (opVpnInterface != null) {
373 String opVpnName = opVpnInterface.getVpnInstanceName();
374 String primaryInterfaceIp = null;
375 if (opVpnName.equals(vpnName)) {
376 // Please check if the primary VRF Entry does not exist for VPNInterface
377 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
379 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
380 List<Adjacency> adjs = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(interfaceName);
382 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
383 + " for this vpn interface could not be obtained", interfaceName, dpId,
387 for (Adjacency adj : adjs) {
388 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
389 primaryInterfaceIp = adj.getIpAddress();
393 if (primaryInterfaceIp == null) {
394 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
395 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
399 // Get the rd of the vpn instance
400 VrfEntry vrf = vpnUtil.getVrfEntry(primaryRd, primaryInterfaceIp);
402 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
403 + " bailing out from here.", interfaceName, dpId, vpnName);
406 waitForVpnInterfaceOpRemoval = true;
408 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
409 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
412 if (!waitForVpnInterfaceOpRemoval) {
413 // Add the VPNInterface and quit
414 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
415 null/*ipAddressSourceValuePair*/,
417 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
418 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
419 if (!isBgpVpnInternetVpn) {
420 vpnUtil.bindService(vpnName, interfaceName, false /*isTunnelInterface*/);
422 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
424 if (interfaceManager.isExternalInterface(interfaceName)) {
425 processExternalVpnInterface(interfaceName, vpnName, dpId, lportTag,
426 NwConstants.ADD_FLOW);
431 // FIB didn't get a chance yet to clean up this VPNInterface
432 // Let us give it a chance here !
433 LOG.info("processVpnInterfaceUp: Trying to add VPN Interface {} on dpn {} for vpn {},"
434 + " but waiting for FIB to clean up! ", interfaceName, dpId, vpnName);
436 Runnable notifyTask = new VpnNotifyTask();
437 synchronized (notifyTask) {
438 // Per FB's "Unconditional wait" violation, the code should really verify that the condition it
439 // intends to wait for is not already satisfied before calling wait. However the VpnNotifyTask is
440 // published here while holding the lock on it so this path will hit the wait before notify can be
442 vpnIntfMap.put(interfaceName, notifyTask);
444 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
445 } catch (InterruptedException e) {
450 vpnIntfMap.remove(interfaceName);
453 if (opVpnInterface != null) {
454 LOG.warn("processVpnInterfaceUp: VPN Interface {} removal on dpn {} for vpn {}"
455 + " by FIB did not complete on time," + " bailing addition ...", interfaceName,
457 vpnUtil.unsetScheduledToRemoveForVpnInterface(interfaceName);
460 // VPNInterface got removed, proceed with Add
461 LOG.info("processVpnInterfaceUp: Continuing to plumb vpn interface {} onto dpn {} for vpn {}",
462 interfaceName, dpId, vpnName);
463 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
464 null/*ipAddressSourceValuePair*/,
466 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
467 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
468 if (!isBgpVpnInternetVpn) {
469 vpnUtil.bindService(vpnName, interfaceName, false/*isTunnelInterface*/);
471 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
472 + " FIB to clean up", interfaceName, dpId, vpnName);
473 if (interfaceManager.isExternalInterface(interfaceName)) {
474 processExternalVpnInterface(interfaceName, vpnName, dpId,
475 lportTag, NwConstants.ADD_FLOW);
479 // Interface is retained in the DPN, but its Link Up.
480 // Advertise prefixes again for this interface to BGP
481 InstanceIdentifier<VpnInterface> identifier =
482 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName());
483 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
484 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
485 advertiseAdjacenciesForVpnToBgp(primaryRd, dpId, vpnInterfaceOpIdentifier, vpnName, interfaceName);
486 // Perform similar operation as interface add event for extraroutes.
487 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
488 Optional<Adjacencies> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
489 LogicalDatastoreType.CONFIGURATION, path);
490 if (!optAdjacencies.isPresent()) {
491 LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
494 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
495 for (Adjacency adjacency : adjacencies) {
496 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
499 // if BGPVPN Internet, filter only IPv6 Adjacencies
500 if (isBgpVpnInternetVpn && !vpnUtil.isAdjacencyEligibleToVpnInternet(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, BigInteger dpId,
514 int lportTag, 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(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(routerName);
538 if (Objects.equals(primarySwitch, dpId)) {
539 Routers router = vpnUtil.getExternalRouter(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);
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(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(
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,
641 WriteTransaction writeOperTx) {
643 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
644 String rd = vpnUtil.getVpnRd(interfaceName);
646 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
647 interfaceName, vpnName);
650 if (rd.equals(vpnName)) {
652 "withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in "
653 + "internal vpn{} with rd {}", interfaceName, vpnName, rd);
657 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", interfaceName,
659 Optional<AdjacenciesOp> adjacencies = Optional.absent();
661 adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
663 } catch (ReadFailedException e) {
664 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to read data store for interface {} vpn {}",
665 interfaceName, vpnName);
667 if (adjacencies.isPresent()) {
668 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
670 if (!nextHops.isEmpty()) {
671 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
672 nextHops, interfaceName, vpnName, rd);
673 for (Adjacency nextHop : nextHops) {
675 if (nextHop.getAdjacencyType() != AdjacencyType.ExtraRoute) {
676 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removing Fib Entry rd {}"
677 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
678 interfaceName, vpnName);
679 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
680 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removed Fib Entry rd {}"
681 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
682 interfaceName, vpnName);
684 // Perform similar operation as interface delete event for extraroutes.
685 String allocatedRd = nextHop.getVrfId();
686 for (String nh : nextHop.getNextHopIpList()) {
687 deleteExtraRouteFromCurrentAndImportingVpns(
688 vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn,
692 } catch (Exception e) {
693 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
694 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
701 @SuppressWarnings("checkstyle:IllegalCatch")
702 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
703 String primaryRd, String interfaceName, final long vpnId,
704 WriteTransaction writeConfigTxn,
705 WriteTransaction writeOperTxn,
706 final WriteTransaction writeInvTxn,
707 Interface interfaceState) {
708 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
710 Optional<VpnInterface> vpnInteface = Optional.absent();
712 vpnInteface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
713 LogicalDatastoreType.CONFIGURATION, identifier);
714 } catch (ReadFailedException e) {
715 LOG.error("processVpnInterfaceAdjacencies: Failed to read data store for interface {} vpn {} rd {}"
716 + "dpn {}", interfaceName, vpnName, primaryRd, dpnId);
718 Uuid intfnetworkUuid = null;
719 NetworkType networkType = null;
720 Long segmentationId = Long.valueOf(-1);
721 Adjacencies adjacencies = null;
722 if (vpnInteface.isPresent()) {
723 intfnetworkUuid = vpnInteface.get().getNetworkId();
724 networkType = vpnInteface.get().getNetworkType();
725 segmentationId = vpnInteface.get().getSegmentationId();
726 adjacencies = vpnInteface.get().augmentation(Adjacencies.class);
727 if (adjacencies == null) {
728 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
729 null/*gwMac*/, writeOperTxn);
733 // Get the rd of the vpn instance
734 String nextHopIp = null;
736 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
737 } catch (Exception e) {
738 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
739 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
741 List<String> nhList = new ArrayList<>();
742 if (nextHopIp != null) {
743 nhList.add(nextHopIp);
744 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
745 interfaceName, dpnId, vpnName, nhList);
747 Optional<String> gwMac = Optional.absent();
748 String vpnInterfaceSubnetGwMacAddress = null;
749 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
750 Long l3vni = vpnInstanceOpData.getL3vni();
751 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
752 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
753 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
754 List<Adjacency> nextHops = (adjacencies != null) ? adjacencies.getAdjacency() : Collections.emptyList();
755 List<Adjacency> value = new ArrayList<>();
756 for (Adjacency nextHop : nextHops) {
757 String rd = primaryRd;
758 String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
759 if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
760 && NWUtil.isIpv4Address(nexthopIpValue)) {
761 String prefix = nextHop.getIpAddress() == null ? "null" :
762 VpnUtil.getIpPrefix(nextHop.getIpAddress());
763 LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
764 + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
767 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
768 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
769 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
770 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
771 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
772 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
774 Prefixes prefixes = (intfnetworkUuid != null)
775 ? VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, intfnetworkUuid ,networkType,
776 segmentationId, prefixCue) :
777 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, prefixCue);
779 LogicalDatastoreType.OPERATIONAL,
780 VpnUtil.getPrefixToInterfaceIdentifier(
781 vpnUtil.getVpnId(vpnName), prefix), prefixes, true);
782 final Uuid subnetId = nextHop.getSubnetId();
784 String gatewayIp = nextHop.getSubnetGatewayIp();
785 if (gatewayIp == null) {
786 Optional<String> gatewayIpOptional = vpnUtil.getVpnSubnetGatewayIp(subnetId);
787 if (gatewayIpOptional.isPresent()) {
788 gatewayIp = gatewayIpOptional.get();
792 if (gatewayIp != null) {
793 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
794 if (gwMac.isPresent()) {
795 // A valid mac-address is available for this subnet-gateway-ip
796 // Use this for programming ARP_RESPONDER table here. And save this
797 // info into vpnInterface operational, so it can used in VrfEntryProcessor
798 // to populate L3_GW_MAC_TABLE there.
799 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
800 gatewayIp, gwMac.get());
801 vpnInterfaceSubnetGwMacAddress = gwMac.get();
803 // A valid mac-address is not available for this subnet-gateway-ip
804 // Use the connected-mac-address to configure ARP_RESPONDER Table.
805 // Save this connected-mac-address as gateway-mac-address for the
806 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
807 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
808 if (gwMac.isPresent()) {
809 vpnUtil.setupGwMacIfExternalVpn(dpnId, interfaceName, vpnId, writeInvTxn,
810 NwConstants.ADD_FLOW, gwMac.get());
811 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
812 gatewayIp, gwMac.get());
814 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
815 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
817 subnetId, interfaceName, vpnName, gatewayIp);
821 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
822 + "cannot create ARP responder flow for interface name {}, vpnName {}",
823 subnetId, interfaceName, vpnName);
824 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
826 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
827 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
829 //Extra route adjacency
830 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
831 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
832 synchronized (vpnPrefixKey.intern()) {
833 java.util.Optional<String> rdToAllocate = vpnUtil
834 .allocateRdForExtraRouteAndUpdateUsedRdsMap(vpnId, null, prefix, vpnName,
835 nextHop.getNextHopIpList().get(0), dpnId);
836 if (rdToAllocate.isPresent()) {
837 rd = rdToAllocate.get();
838 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
841 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
845 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
846 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
847 interfaceName, dpnId);
849 // Please note that primary adjacency will use a subnet-gateway-mac-address that
850 // can be different from the gateway-mac-address within the VRFEntry as the
851 // gateway-mac-address is a superset.
852 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
853 : RouteOrigin.STATIC;
854 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
855 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
856 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
857 Adjacency operationalAdjacency = null;
859 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
860 } catch (NullPointerException e) {
861 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
862 input, e.getMessage());
865 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
866 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
867 vpnName, l3vni, origin,
868 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
870 value.add(operationalAdjacency);
873 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
874 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
875 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
877 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
878 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
879 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
881 for (Adjacency nextHop : aug.getAdjacency()) {
882 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
883 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
884 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
885 : RouteOrigin.STATIC;
886 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
887 registeredPopulator.populateFib(input, writeConfigTxn);
892 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
893 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
894 VpnInterfaceOpDataEntry opInterface =
895 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, lportTag, gwMac);
896 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
897 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
898 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
899 WriteTransaction.CREATE_MISSING_PARENTS);
900 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
901 interfaceName, dpnId, vpnName);
904 // TODO Clean up the exception handling
905 @SuppressWarnings("checkstyle:IllegalCatch")
906 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
907 StateTunnelList stateTunnelList,
908 WriteTransaction writeConfigTxn,
909 WriteTransaction writeOperTxn) {
911 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
912 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
913 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
914 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
915 if (adjList.isEmpty()) {
916 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
917 vpnInterface, srcDpnId);
920 String prefix = null;
922 List<Adjacency> value = new ArrayList<>();
923 boolean isNextHopAddReqd = false;
924 String vpnName = vpnInterface.getVpnInstanceName();
925 long vpnId = vpnUtil.getVpnId(vpnName);
926 String primaryRd = vpnUtil.getPrimaryRd(vpnName);
927 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
928 vpnInterface.getName(), vpnInterface.getDpnId(),
929 vpnInterface.getVpnInstanceName(), adjList);
930 for (Adjacency adj : adjList) {
931 String rd = adj.getVrfId();
932 rd = rd != null ? rd : vpnName;
933 prefix = adj.getIpAddress();
934 label = adj.getLabel();
935 List<String> nhList = Collections.singletonList(srcTepIp);
936 List<String> nextHopList = adj.getNextHopIpList();
937 // If TEP is added , update the nexthop of primary adjacency.
938 // Secondary adj nexthop is already pointing to primary adj IP address.
939 if (nextHopList != null && !nextHopList.isEmpty()) {
940 /* everything right already */
942 isNextHopAddReqd = true;
945 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
946 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
948 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
949 if (!vrfEntryOptional.isPresent()) {
952 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
953 if (!nhList.contains(srcTepIp)) {
954 nhList.add(srcTepIp);
955 isNextHopAddReqd = true;
960 if (isNextHopAddReqd) {
961 updateLabelMapper(label, nhList);
962 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
963 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
964 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
965 // Update the VRF entry with nextHop
966 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
967 label, true, writeConfigTxn);
969 //Get the list of VPN's importing this route(prefix) .
970 // Then update the VRF entry with nhList
971 List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
972 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
973 String vpnRd = vpn.getVrfId();
975 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
976 srcTepIp, label, true, writeConfigTxn);
977 LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
978 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
979 vpnInterface.getName(), srcDpnId, vpnName,
980 vpn.getVpnInstanceName(), vpnRd);
983 // Advertise the prefix to BGP only for external vpn
984 // since there is a nexthop change.
986 if (!rd.equalsIgnoreCase(vpnName)) {
987 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, nhList,
988 VrfEntry.EncapType.Mplsgre, (int)label, 0 /*evi*/, 0 /*l2vni*/,
989 null /*gatewayMacAddress*/);
991 LOG.info("updateVpnInterfaceOnTepAdd: Advertised rd {} prefix {} nhList {} label {}"
992 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label, vpnInterface.getName(),
994 } catch (Exception ex) {
995 LOG.error("updateVpnInterfaceOnTepAdd: Exception when advertising prefix {} nh {} label {}"
996 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
997 vpnInterface.getName(), srcDpnId, vpnName, ex);
1001 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1002 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1003 .withKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1004 .addAugmentation(AdjacenciesOp.class, aug).build();
1005 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1006 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1007 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1008 WriteTransaction.CREATE_MISSING_PARENTS);
1009 LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
1010 vpnInterface.getName(), srcDpnId, vpnName);
1014 // TODO Clean up the exception handling
1015 @SuppressWarnings("checkstyle:IllegalCatch")
1016 public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
1017 StateTunnelList stateTunnelList,
1018 WriteTransaction writeConfigTxn,
1019 WriteTransaction writeOperTxn) {
1021 AdjacenciesOp adjacencies = vpnInterface.augmentation(AdjacenciesOp.class);
1022 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
1023 String prefix = null;
1025 boolean isNextHopRemoveReqd = false;
1026 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
1027 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
1028 String vpnName = vpnInterface.getVpnInstanceName();
1029 long vpnId = vpnUtil.getVpnId(vpnName);
1030 String primaryRd = vpnUtil.getVpnRd(vpnName);
1031 if (adjList != null) {
1032 List<Adjacency> value = new ArrayList<>();
1033 LOG.info("updateVpnInterfaceOnTepDelete: AdjacencyList for interface {} on dpn {} vpn {} is {}",
1034 vpnInterface.getName(), vpnInterface.getDpnId(),
1035 vpnInterface.getVpnInstanceName(), adjList);
1036 for (Adjacency adj : adjList) {
1037 List<String> nhList = new ArrayList<>();
1038 String rd = adj.getVrfId();
1039 rd = rd != null ? rd : vpnName;
1040 prefix = adj.getIpAddress();
1041 List<String> nextHopList = adj.getNextHopIpList();
1042 label = adj.getLabel();
1043 if (nextHopList != null && !nextHopList.isEmpty()) {
1044 isNextHopRemoveReqd = true;
1046 // If TEP is deleted , remove the nexthop from primary adjacency.
1047 // Secondary adj nexthop will continue to point to primary adj IP address.
1048 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1049 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
1051 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
1052 if (!vrfEntryOptional.isPresent()) {
1055 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
1056 if (nhList.contains(srcTepIp)) {
1057 nhList.remove(srcTepIp);
1058 isNextHopRemoveReqd = true;
1063 if (isNextHopRemoveReqd) {
1064 updateLabelMapper(label, nhList);
1065 LOG.info("updateVpnInterfaceOnTepDelete: Updated label mapper : label {} dpn {} prefix {}"
1066 + " nexthoplist {} vpn {} vpnid {} rd {} interface {}", label, srcDpnId,
1067 prefix, nhList, vpnName,
1068 vpnId, rd, vpnInterface.getName());
1069 // Update the VRF entry with removed nextHop
1070 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
1071 label, false, writeConfigTxn);
1073 //Get the list of VPN's importing this route(prefix) .
1074 // Then update the VRF entry with nhList
1075 List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
1076 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1077 String vpnRd = vpn.getVrfId();
1078 if (vpnRd != null) {
1079 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1080 srcTepIp, label, false, writeConfigTxn);
1081 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1082 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1083 nhList, label, vpnInterface.getName(), srcDpnId,
1085 vpn.getVpnInstanceName(), vpnRd);
1089 // Withdraw prefix from BGP only for external vpn.
1091 if (!rd.equalsIgnoreCase(vpnName)) {
1092 bgpManager.withdrawPrefix(rd, prefix);
1094 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1095 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1096 vpnInterface.getName(), srcDpnId,
1098 } catch (Exception ex) {
1099 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1100 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
1101 vpnInterface.getName(), srcDpnId, vpnName, ex);
1105 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1106 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1107 .withKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1108 .addAugmentation(AdjacenciesOp.class, aug).build();
1109 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1110 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1111 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1112 WriteTransaction.CREATE_MISSING_PARENTS);
1113 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1114 vpnInterface.getName(), srcDpnId, vpnName);
1118 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1119 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1121 String vpnRd = vpnUtil.getVpnRd(vpnName);
1122 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(vpnRd);
1123 if (vpnInstanceOpDataEntry == null) {
1124 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1125 + " to check for vpns exporting the routes", vpnName);
1126 return vpnsToExportRoute;
1129 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1130 if (input.getVpnInstanceName() == null) {
1131 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1135 return !input.getVpnInstanceName().equals(vpnName);
1138 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1139 Iterable<String> commonRTs =
1140 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1141 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1142 return Iterators.size(commonRTs.iterator()) > 0;
1146 vpnUtil.getAllVpnInstanceOpData().stream().filter(excludeVpn).filter(matchRTs).collect(
1147 Collectors.toList());
1148 return vpnsToExportRoute;
1151 // TODO Clean up the exception handling
1152 @SuppressWarnings("checkstyle:IllegalCatch")
1153 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1154 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1155 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1156 List<VrfEntry> vrfEntries = vpnUtil.getAllVrfEntries(vpn.getVrfId());
1157 if (vrfEntries != null) {
1158 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1159 for (VrfEntry vrfEntry : vrfEntries) {
1161 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1162 RouteOrigin.value(vrfEntry.getOrigin()))) {
1163 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1164 + " is not a controller managed non intervpn link route. Ignoring.",
1165 vpn.getVrfId(), vrfEntry.getDestPrefix());
1168 String prefix = vrfEntry.getDestPrefix();
1169 String gwMac = vrfEntry.getGatewayMacAddress();
1170 vrfEntry.getRoutePaths().forEach(routePath -> {
1171 String nh = routePath.getNexthopAddress();
1172 int label = routePath.getLabel().intValue();
1173 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1174 vrfEntry.getOrigin()))) {
1175 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1176 + " nexthop {} label {} to vpn {} vpnRd {}",
1177 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1178 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1179 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1180 0 /*l3vni*/, gwMac, vpn.getVrfId(), RouteOrigin.SELF_IMPORTED,
1183 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} "
1184 + "prefix {} nexthop {} label {} to vpn {} vpnRd {}",
1185 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1186 SubnetRoute route = vrfEntry.augmentation(SubnetRoute.class);
1187 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, vpn.getVrfId(),
1191 } catch (RuntimeException e) {
1192 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1193 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1194 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1197 }), LOG, "Error handing VPN exporting routes");
1199 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1200 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1206 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1207 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1208 final String interfaceName = key.getName();
1209 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1210 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1211 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1215 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1216 final VpnInterface vpnInterface, final String vpnName,
1217 final String interfaceName) {
1218 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1219 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
1220 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1221 deleteFibEntryForRouterInterface(vpnInterface, confTx, vpnName);
1222 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1224 ListenableFutures.addErrorLogging(future, LOG, "Error removing call for interface {} on VPN {}",
1225 vpnInterface.getName(), vpnName);
1226 return Collections.singletonList(future);
1227 }, DJC_MAX_RETRIES);
1229 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName);
1233 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1234 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1235 final VpnInterface vpnInterface, final String vpnName,
1236 final String interfaceName) {
1237 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1238 vpnName, vpnInterface.getDpnId());
1239 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1240 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1242 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1243 ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1244 writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1245 writeOperTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1246 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1247 interfaceName, vpnName);
1248 BigInteger dpId = BigInteger.ZERO;
1250 String gwMacAddress = null;
1251 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1252 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1253 Optional<VpnInterfaceOpDataEntry> optVpnInterface = Optional.absent();
1255 optVpnInterface = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1256 LogicalDatastoreType.OPERATIONAL, interfaceId);
1257 } catch (ReadFailedException e) {
1258 LOG.error("remove: Failed to read data store for interface {} vpn {}", interfaceName,
1262 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,
1264 if (interfaceState != null) {
1266 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1267 } catch (NumberFormatException | IllegalStateException e) {
1268 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1269 + " data store for interface {} on dpn {} for vpn {} Fetching"
1270 + " from vpn interface op data store. ", interfaceName,
1271 vpnInterface.getDpnId(), vpnName, e);
1272 dpId = BigInteger.ZERO;
1274 ifIndex = interfaceState.getIfIndex();
1275 gwMacAddress = interfaceState.getPhysAddress().getValue();
1277 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1278 + " from vpn interface op.", interfaceName);
1279 if (optVpnInterface.isPresent()) {
1280 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1281 dpId = vpnOpInterface.getDpnId();
1282 ifIndex = vpnOpInterface.getLportTag().intValue();
1283 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1285 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1286 + " as interfaceState and vpn interface op is not"
1287 + " available", interfaceName, vpnName);
1291 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1292 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1293 writeConfigTxn, writeOperTxn, writeInvTxn);
1295 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1297 interfaceName, vpnInterface.getDpnId(), vpnName);
1299 futures.add(configFuture);
1300 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1302 }, DJC_MAX_RETRIES);
1305 protected void processVpnInterfaceDown(BigInteger dpId,
1306 String interfaceName,
1309 VpnInterfaceOpDataEntry vpnOpInterface,
1310 boolean isInterfaceStateDown,
1311 WriteTransaction writeConfigTxn,
1312 WriteTransaction writeOperTxn,
1313 WriteTransaction writeInvTxn) {
1314 if (vpnOpInterface == null) {
1315 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1316 + " as it is not available in operational data store", interfaceName, dpId);
1319 final String vpnName = vpnOpInterface.getVpnInstanceName();
1320 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1321 interfaceName, vpnName);
1322 if (!isInterfaceStateDown) {
1323 final long vpnId = vpnUtil.getVpnId(vpnName);
1324 vpnUtil.scheduleVpnInterfaceForRemoval(interfaceName, dpId, vpnName, null);
1325 final boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(vpnName);
1326 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1327 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1328 if (interfaceManager.isExternalInterface(interfaceName)) {
1329 processExternalVpnInterface(interfaceName, vpnName, dpId, lportTag,
1330 NwConstants.DEL_FLOW);
1332 if (!isBgpVpnInternetVpn) {
1333 vpnUtil.unbindService(interfaceName, isInterfaceStateDown);
1335 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1336 + " successful", interfaceName, dpId, vpnName);
1338 // Interface is retained in the DPN, but its Link Down.
1339 // Only withdraw the prefixes for this interface from BGP
1340 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
1344 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1345 final String vpnName, final long vpnId, String gwMac,
1346 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1347 final WriteTransaction writeInvTxn) {
1350 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1351 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1352 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1353 Optional<AdjacenciesOp> adjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1354 LogicalDatastoreType.OPERATIONAL, path);
1355 String primaryRd = vpnUtil.getVpnRd(vpnName);
1356 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1357 interfaceName, dpnId, vpnName, primaryRd);
1358 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1359 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1360 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1361 interfaceName, dpnId, vpnName, nextHops);
1362 for (Adjacency nextHop : nextHops) {
1363 if (nextHop.isPhysNetworkFunc()) {
1364 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1365 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1366 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1367 null/*writeCfgTxn*/);
1369 String rd = nextHop.getVrfId();
1370 List<String> nhList;
1371 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1372 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1374 // This is a primary adjacency
1375 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1376 : Collections.emptyList();
1377 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1378 interfaceName, writeInvTxn);
1380 if (!nhList.isEmpty()) {
1381 if (rd.equals(vpnName)) {
1382 //this is an internal vpn - the rd is assigned to the vpn instance name;
1383 //remove from FIB directly
1384 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1385 interfaceName, dpnId, writeConfigTxn, writeOperTxn));
1387 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
1388 interfaceName, writeConfigTxn, writeOperTxn);
1391 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1392 + " interface {}", nextHop.getIpAddress(), rd,
1393 nextHop.getAdjacencyType().toString(), interfaceName);
1394 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1395 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1398 String ip = nextHop.getIpAddress().split("/")[0];
1399 LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, ip);
1400 if (vpnVipToPort != null) {
1401 vpnUtil.removeLearntVpnVipToPort(vpnName, ip, null);
1402 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed LearntVpnVipToPort entry"
1403 + " for Interface {} ip {} on dpn {} for vpn {}",
1404 vpnVipToPort.getPortName(), ip, dpnId, vpnName);
1406 VpnPortipToPort vpnPortipToPort = vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnName, ip);
1407 if (vpnPortipToPort != null) {
1408 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip, null);
1409 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed vpnPortipToPort entry for "
1410 + "Interface {} ip {} on dpn {} for vpn {}",
1411 vpnPortipToPort.getPortName(), ip, dpnId, vpnName);
1415 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1416 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1417 + " Removing it.", interfaceName, vpnName, dpnId);
1418 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1420 } catch (ReadFailedException e) {
1421 LOG.error("removeAdjacenciesFromVpn: Failed to read data store for interface {} dpn {} vpn {}",
1422 interfaceName, dpnId, vpnName);
1426 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName, String interfaceName,
1427 BigInteger dpnId, WriteTransaction writeConfigTxn,
1428 WriteTransaction writeOperTx) {
1430 String primaryRd = vpnUtil.getVpnRd(vpnName);
1431 String prefix = nextHop.getIpAddress();
1432 String vpnNamePrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1433 LOG.info("remove adjacencies for nexthop {} vpnName {} interfaceName {} dpnId {}",
1434 nextHop, vpnName, interfaceName, dpnId);
1435 synchronized (vpnNamePrefixKey.intern()) {
1436 if (vpnUtil.removeOrUpdateDSForExtraRoute(vpnName, primaryRd, dpnId.toString(), interfaceName,
1437 prefix, nextHop.getNextHopIpList().get(0), nh, writeOperTx)) {
1438 //If extra-route is present behind at least one VM, then do not remove or update
1439 //fib entry for route-path representing that CSS nexthop, just update vpntoextraroute and
1440 //prefixtointerface DS
1443 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1446 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1447 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1448 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1452 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1453 BigInteger dpnId, String rd, String interfaceName,
1454 WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
1455 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1456 vpnUtil.getVpnsImportingMyRoute(vpnName);
1457 nhList.forEach((nh) -> {
1458 //IRT: remove routes from other vpns importing it
1459 vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
1460 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
1461 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1462 String vpnRd = vpn.getVrfId();
1463 if (vpnRd != null) {
1464 fibManager.removeOrUpdateFibEntry(vpnRd,
1465 nextHop.getIpAddress(), nh, writeConfigTxn);
1466 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1467 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1468 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1469 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1475 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1476 int lportTag, String gwMac, String interfaceName,
1477 WriteTransaction writeInvTxn) {
1478 final Uuid subnetId = nextHop.getSubnetId();
1479 if (nextHop.getSubnetGatewayMacAddress() == null) {
1480 // A valid mac-address was not available for this subnet-gateway-ip
1481 // So a connected-mac-address was used for this subnet and we need
1482 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1483 vpnUtil.setupGwMacIfExternalVpn(dpnId, interfaceName, vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1485 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1489 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1490 String interfaceName) {
1491 // This is either an extra-route (or) a learned IP via subnet-route
1492 List<String> nhList = null;
1493 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1494 if (nextHopIp == null || nextHopIp.isEmpty()) {
1495 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1496 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1497 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1499 nhList = Collections.emptyList();
1501 nhList = Collections.singletonList(nextHopIp);
1506 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1507 VpnPortipToPort gwPort = vpnUtil.getNeutronPortFromVpnPortFixedIp(vpnName, ipAddress);
1508 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1509 // else use connected interface
1510 if (gwPort != null && gwPort.isSubnetIp()) {
1511 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1512 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1513 return Optional.of(gwPort.getMacAddress());
1515 return Optional.absent();
1519 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1520 final VpnInterface update) {
1521 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1522 update.getDpnId(), original.getVpnInstanceNames(),
1523 update.getVpnInstanceNames());
1524 final String vpnInterfaceName = update.getName();
1525 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1526 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1527 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1528 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1529 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1530 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1531 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1533 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1534 //handles switching between <internal VPN - external VPN>
1535 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1536 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1537 LOG.info("update: handled VPNInterface {} on dpn {} update"
1538 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1539 original.getName(), dpnId,
1540 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1541 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1542 return Collections.emptyList();
1544 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1545 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1546 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1547 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1548 String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
1549 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
1550 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
1551 List<ListenableFuture<Void>> futures = new ArrayList<>();
1552 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1553 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(operTx -> {
1554 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1555 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1556 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1557 update.getName(), newVpnName);
1558 //handle both addition and removal of adjacencies
1559 //currently, new adjacency may be an extra route
1560 boolean isBgpVpnInternetVpn = vpnUtil.isBgpVpnInternet(newVpnName);
1561 if (!oldAdjs.equals(newAdjs)) {
1562 for (Adjacency adj : copyNewAdjs) {
1563 if (copyOldAdjs.contains(adj)) {
1564 copyOldAdjs.remove(adj);
1566 // add new adjacency - right now only extra route will hit this path
1567 if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
1568 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1569 dpnId, operTx, confTx);
1571 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
1572 + " vpn interface {} on vpn {} dpnId {}",
1573 adj.getIpAddress(), adj.getNextHopIpList(),
1574 adj.getLabel(), adj.getSubnetId(), update.getName(),
1578 for (Adjacency adj : copyOldAdjs) {
1579 if (!isBgpVpnInternetVpn || vpnUtil.isAdjacencyEligibleToVpnInternet(adj)) {
1580 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
1581 && !adj.isPhysNetworkFunc()) {
1582 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1584 Optional<VpnInterfaceOpDataEntry> optVpnInterface = operTx.read(
1585 LogicalDatastoreType.OPERATIONAL, vpnInterfaceOpIdentifier).get();
1586 if (optVpnInterface.isPresent()) {
1587 VpnInterfaceOpDataEntry vpnInterfaceOpDataEntry = optVpnInterface.get();
1588 long vpnId = vpnUtil.getVpnId(newVpnName);
1589 vpnUtil.removePrefixToInterfaceAdj(adj, vpnId,
1590 vpnInterfaceOpDataEntry, operTx);
1592 LOG.info("update: Vpninterface {} not present in Operational",
1596 String vpnRd = vpnUtil.getVpnRd(newVpnName);
1597 LOG.debug("update: remove prefix {} from the FIB and BGP entry "
1598 + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
1600 fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
1601 if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
1602 bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
1605 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1609 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1610 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
1611 .getNextHopIpList(),
1612 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1617 for (ListenableFuture<Void> future : futures) {
1618 ListenableFutures.addErrorLogging(future, LOG, "update: failed for interface {} on vpn {}",
1619 update.getName(), update.getVpnInstanceNames());
1623 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1624 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1627 return Collections.emptyList();
1631 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1632 VpnInterface original, VpnInterface update) {
1633 boolean isSwap = Boolean.FALSE;
1634 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1635 final String interfaceName = key.getName();
1636 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1637 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1638 List<String> oldVpnListCopy = new ArrayList<>();
1639 oldVpnListCopy.addAll(oldVpnList);
1640 List<String> newVpnList = update.getVpnInstanceNames().stream()
1641 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1642 oldVpnList.removeAll(newVpnList);
1643 newVpnList.removeAll(oldVpnListCopy);
1644 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1645 for (String oldVpnName: oldVpnList) {
1646 isSwap = Boolean.TRUE;
1647 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1648 + " running config-driven swap removal", interfaceName, oldVpnName);
1649 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1650 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1651 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1653 //Wait for previous interface bindings to be removed
1656 } catch (InterruptedException e) {
1660 final Adjacencies origAdjs = original.augmentation(Adjacencies.class);
1661 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1662 ? origAdjs.getAdjacency() : new ArrayList<>();
1663 final Adjacencies updateAdjs = update.augmentation(Adjacencies.class);
1664 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1665 ? updateAdjs.getAdjacency() : new ArrayList<>();
1667 for (String newVpnName: newVpnList) {
1668 String primaryRd = vpnUtil.getPrimaryRd(newVpnName);
1669 isSwap = Boolean.TRUE;
1670 if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
1671 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1672 + "running config-driven swap addition", interfaceName, newVpnName);
1673 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1674 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1675 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1676 interfaceName, oldVpnListCopy, newVpnName);
1683 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1685 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1686 synchronized (label.toString().intern()) {
1687 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1688 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1689 Optional<LabelRouteInfo> opResult = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1690 LogicalDatastoreType.OPERATIONAL, lriIid);
1691 if (opResult.isPresent()) {
1692 LabelRouteInfo labelRouteInfo =
1693 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1694 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid,
1695 labelRouteInfo, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
1698 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label,
1700 } catch (ReadFailedException e) {
1701 LOG.error("updateLabelMapper: Failed to read data store for label {} nexthopList {}", label,
1703 } catch (TransactionCommitFailedException e) {
1704 LOG.error("updateLabelMapper: Failed to commit to data store for label {} nexthopList {}", label,
1709 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1710 SubnetRoute route, String parentVpnRd, WriteTransaction writeConfigTxn) {
1712 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1713 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, parentVpnRd)
1714 .addAugmentation(SubnetRoute.class, route).build();
1715 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1716 InstanceIdentifierBuilder<VrfTables> idBuilder =
1717 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1718 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1719 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1720 if (writeConfigTxn != null) {
1721 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1723 vpnUtil.syncUpdate(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1725 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1726 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1729 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1730 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1731 WriteTransaction writeConfigTxn) {
1732 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1733 String configVpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1735 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker
1736 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1737 if (optVpnInterface.isPresent()) {
1738 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1739 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1740 String vpnName = currVpnIntf.getVpnInstanceName();
1741 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
1742 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1743 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1744 LogicalDatastoreType.OPERATIONAL, adjPath);
1745 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1746 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1747 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1748 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1749 List<Adjacency> adjacencies;
1750 if (optAdjacencies.isPresent()) {
1751 adjacencies = optAdjacencies.get().getAdjacency();
1753 // This code will be hit in case of first PNF adjacency
1754 adjacencies = new ArrayList<>();
1756 long vpnId = vpnUtil.getVpnId(vpnName);
1757 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1758 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1759 Adjacency operationalAdjacency = null;
1760 //Handling dual stack neutron port primary adjacency
1761 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency && !adj.isPhysNetworkFunc()) {
1762 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to existing interface {} for vpn {}", prefix,
1763 currVpnIntf.getName(), vpnName);
1764 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,
1765 currVpnIntf.getName());
1766 if (interfaceState != null) {
1767 processVpnInterfaceAdjacencies(dpnId, currVpnIntf.getLportTag().intValue(), vpnName, primaryRd,
1768 currVpnIntf.getName(),
1769 vpnId, writeConfigTxn, writeOperTxn, null, interfaceState);
1772 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()
1773 && adj.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1774 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1775 : RouteOrigin.STATIC;
1776 String nh = adj.getNextHopIpList().get(0);
1777 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1778 synchronized (vpnPrefixKey.intern()) {
1779 java.util.Optional<String> rdToAllocate = vpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1780 vpnId, null, prefix, vpnName, nh, dpnId);
1781 if (rdToAllocate.isPresent()) {
1782 input.setRd(rdToAllocate.get());
1783 operationalAdjacency = populator.createOperationalAdjacency(input);
1784 int label = operationalAdjacency.getLabel().intValue();
1785 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1786 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1787 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1788 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1789 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1790 vpnName, label, currVpnIntf.getName(), dpnId);
1792 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}",
1796 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1797 // Keeping the MPLS check for now.
1798 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1799 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1800 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1801 vpnUtil.getVpnsImportingMyRoute(vpnName);
1802 vpnsToImportRoute.forEach(vpn -> {
1803 if (vpn.getVrfId() != null) {
1804 vpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(vpn.getVpnId(), vpnId, prefix,
1805 vpnUtil.getVpnName(vpn.getVpnId()), nh, dpnId)
1807 rds -> vpnManager.addExtraRoute(
1808 vpnUtil.getVpnName(vpn.getVpnId()),
1809 adj.getIpAddress(), nh, rds,
1810 currVpnIntf.getVpnInstanceName(), l3vni,
1811 RouteOrigin.SELF_IMPORTED, currVpnIntf.getName(),
1812 opAdjacency, encapType, writeConfigTxn));
1817 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1818 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1819 currVpnIntf.getName(), vpnName);
1821 InstanceIdentifier<VpnInterface> vpnIfaceConfigidentifier = VpnUtil
1822 .getVpnInterfaceIdentifier(currVpnIntf.getName());
1823 Optional<VpnInterface> vpnIntefaceConfig = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1824 LogicalDatastoreType.CONFIGURATION, vpnIfaceConfigidentifier);
1825 Prefixes pnfPrefix = VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1826 Prefixes.PrefixCue.PhysNetFunc);
1827 if (vpnIntefaceConfig.isPresent()) {
1828 pnfPrefix = VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1829 vpnIntefaceConfig.get().getNetworkId(), vpnIntefaceConfig.get().getNetworkType(),
1830 vpnIntefaceConfig.get().getSegmentationId(), Prefixes.PrefixCue.PhysNetFunc);
1833 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1836 LogicalDatastoreType.OPERATIONAL,
1837 VpnUtil.getPrefixToInterfaceIdentifier(vpnUtil.getVpnId(adj.getSubnetId().getValue()),
1838 prefix), pnfPrefix, true);
1840 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1841 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */,
1842 0 /*l3vni*/, null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1844 input.setRd(adj.getVrfId());
1846 if (operationalAdjacency == null) {
1847 operationalAdjacency = populator.createOperationalAdjacency(input);
1849 adjacencies.add(operationalAdjacency);
1850 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1851 VpnInterfaceOpDataEntry newVpnIntf =
1852 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1853 aug, dpnId, currVpnIntf.getLportTag(),
1854 currVpnIntf.getGatewayMacAddress());
1856 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1858 } catch (ReadFailedException e) {
1859 LOG.error("addNewAdjToVpnInterface: Failed to read data store for interface {} dpn {} vpn {} rd {} ip "
1860 + "{}", interfaceName, dpnId, configVpnName, primaryRd, adj.getIpAddress());
1864 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1865 Subnets subnets = vpnUtil.getExternalSubnet(adj.getSubnetId());
1866 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1869 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1870 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1871 String interfaceName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getName();
1872 String vpnName = identifier.firstKeyOf(VpnInterfaceOpDataEntry.class).getVpnInstanceName();
1874 Optional<VpnInterfaceOpDataEntry> optVpnInterface = SingleTransactionDataBroker.syncReadOptional(
1875 dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1876 if (optVpnInterface.isPresent()) {
1877 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1878 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1879 Optional<AdjacenciesOp> optAdjacencies = SingleTransactionDataBroker.syncReadOptional(dataBroker,
1880 LogicalDatastoreType.OPERATIONAL, path);
1881 if (optAdjacencies.isPresent()) {
1882 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1884 if (!adjacencies.isEmpty()) {
1885 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1886 Iterator<Adjacency> adjIt = adjacencies.iterator();
1887 while (adjIt.hasNext()) {
1888 Adjacency adjElem = adjIt.next();
1889 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1890 String rd = adjElem.getVrfId();
1891 if (adj.getNextHopIpList() != null) {
1892 for (String nh : adj.getNextHopIpList()) {
1893 deleteExtraRouteFromCurrentAndImportingVpns(
1894 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1895 currVpnIntf.getName(), writeConfigTxn, writeOperTxn);
1897 } else if (adj.isPhysNetworkFunc()) {
1898 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1899 adj.getIpAddress(), adj.getSubnetId());
1900 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1908 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1909 dpnId, adj.getVrfId());
1911 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1912 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1915 } catch (ReadFailedException e) {
1916 LOG.error("delAdjFromVpnInterface: Failed to read data store for ip {} interface {} dpn {} vpn {}",
1917 adj.getIpAddress(), interfaceName, dpnId, vpnName);
1921 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1922 String rd, String intfName, WriteTransaction writeConfigTxn, WriteTransaction writeOperTx) {
1923 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn, writeOperTx);
1924 List<VpnInstanceOpDataEntry> vpnsToImportRoute = vpnUtil.getVpnsImportingMyRoute(vpnName);
1925 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1926 String vpnRd = vpn.getVrfId();
1927 if (vpnRd != null) {
1928 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn,
1934 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1935 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1936 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1937 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1940 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1941 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1942 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1945 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1946 WriteTransaction writeConfigTxn, String vpnName) {
1947 if (vpnInterface == null) {
1950 List<Adjacency> adjs = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(interfaceName);
1952 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1953 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1956 for (Adjacency adj : adjs) {
1957 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1958 String primaryInterfaceIp = adj.getIpAddress();
1959 String macAddress = adj.getMacAddress();
1960 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1962 long label = vpnUtil.getUniqueId(VpnConstants.VPN_IDPOOL_NAME,
1963 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1965 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1966 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1967 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1968 routerInt, label, writeConfigTxn);
1969 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1970 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1975 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1976 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1977 primaryRd, vpnName);
1980 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1981 WriteTransaction writeConfigTxn, String vpnName) {
1982 Adjacencies adjs = vpnInterface.augmentation(Adjacencies.class);
1983 String rd = vpnUtil.getVpnRd(vpnName);
1985 List<Adjacency> adjsList = adjs.getAdjacency();
1986 for (Adjacency adj : adjsList) {
1987 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1988 String primaryInterfaceIp = adj.getIpAddress();
1989 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1990 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1991 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1992 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1997 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
1998 vpnInterface.getName(), rd);
2002 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
2003 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
2004 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
2005 vpnName, intefaceData.vpnInterface.getName());
2008 final VpnInterfaceKey key = intefaceData.identifier
2009 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
2010 final String interfaceName = key.getName();
2011 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
2012 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
2013 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
2014 intefaceData.identifier, vpnName);
2018 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
2019 VpnInterface vpnInterface, String vpnName) {
2020 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
2022 if (vpnInterfaces == null) {
2023 vpnInterfaces = new ConcurrentLinkedQueue<>();
2025 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2026 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2027 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2028 vpnInterface.getName(), vpnName);
2031 public boolean isVpnInstanceReady(String vpnInstanceName) {
2032 String vpnRd = vpnUtil.getVpnRd(vpnInstanceName);
2033 if (vpnRd == null) {
2036 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnUtil.getVpnInstanceOpData(vpnRd);
2038 return vpnInstanceOpDataEntry != null;
2041 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2042 synchronized (vpnInstanceName.intern()) {
2043 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2044 unprocessedVpnInterfaces.get(vpnInstanceName);
2045 if (vpnInterfaces != null) {
2046 while (!vpnInterfaces.isEmpty()) {
2047 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2048 if (hasVpnInstanceCreatedSuccessfully) {
2049 processSavedInterface(savedInterface, vpnInstanceName);
2050 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2051 savedInterface.vpnInterface.getName(), vpnInstanceName);
2053 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2054 savedInterface.vpnInterface.getName(), vpnInstanceName);
2058 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2063 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2064 VpnInterface vpnInterface) {
2065 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2066 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2067 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2068 if (vpnInterfaces != null) {
2069 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2070 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2071 + "unprocessed list", vpnInterface.getName(),
2072 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2075 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2076 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2081 public void vpnInstanceIsReady(String vpnInstanceName) {
2082 processSavedInterfaces(vpnInstanceName, true);
2085 public void vpnInstanceFailed(String vpnInstanceName) {
2086 processSavedInterfaces(vpnInstanceName, false);
2089 private static class UnprocessedVpnInterfaceData {
2090 InstanceIdentifier<VpnInterface> identifier;
2091 VpnInterface vpnInterface;
2093 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2094 this.identifier = identifier;
2095 this.vpnInterface = vpnInterface;
2099 public int hashCode() {
2100 final int prime = 31;
2102 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2103 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2108 public boolean equals(Object obj) {
2115 if (getClass() != obj.getClass()) {
2118 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2119 if (identifier == null) {
2120 if (other.identifier != null) {
2123 } else if (!identifier.equals(other.identifier)) {
2126 if (vpnInterface == null) {
2127 if (other.vpnInterface != null) {
2130 } else if (!vpnInterface.equals(other.vpnInterface)) {
2137 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2138 String primaryRd = vpnUtil.getVpnRd(vpnName);
2139 VpnInstanceOpDataEntry vpnInstanceOpData = vpnUtil.getVpnInstanceOpData(primaryRd);
2140 if (vpnInstanceOpData == null) {
2143 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2144 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2147 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2148 vpnToDpnLists.forEach(vpnToDpnList -> {
2149 if (vpnToDpnList.getVpnInterfaces() == null) {
2152 vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2154 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2155 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2156 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = SingleTransactionDataBroker
2157 .syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2158 if (!vpnInterfaceOptional.isPresent()) {
2161 List<Adjacency> configVpnAdjacencies = vpnUtil.getAdjacenciesForVpnInterfaceFromConfig(
2162 vpnInterface.getInterfaceName());
2163 if (configVpnAdjacencies == null) {
2164 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2167 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2168 .augmentation(AdjacenciesOp.class).getAdjacency();
2169 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2170 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2171 // in operational DS. These unprocessed adjacencies will be handled below.
2172 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in
2173 // operational DS are retrieved which is used to call addNewAdjToVpnInterface method.
2174 configVpnAdjacencies.stream()
2175 .filter(adjacency -> operationVpnAdjacencies.stream()
2176 .noneMatch(operationalAdjacency ->
2177 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2178 .forEach(adjacency -> {
2179 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2180 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2182 // TODO Deal with sequencing — the config tx must only submitted
2183 // if the oper tx goes in
2184 if (vpnUtil.isAdjacencyEligibleToVpn(adjacency, vpnName)) {
2185 List<ListenableFuture<Void>> futures = new ArrayList<>();
2186 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx ->
2187 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
2188 confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId,
2189 primaryRd, adjacency, vpnInterfaceOptional.get()
2190 .getDpnId(), confTx, operTx)))));
2193 return Collections.emptyList();
2197 } catch (ReadFailedException e) {
2198 LOG.error("updateVpnInterfacesForUnProcessAdjancencies: Failed to read data store for vpn {} rd {}",
2199 vpnName, primaryRd);
2205 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2206 private final String interfaceName;
2207 private final boolean add;
2208 private final String txnDestination;
2210 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2211 this.interfaceName = interfaceName;
2213 this.txnDestination = transactionDest;
2217 public void onSuccess(Void voidObj) {
2219 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2220 interfaceName, txnDestination);
2222 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2227 public void onFailure(Throwable throwable) {
2229 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2230 interfaceName, txnDestination, throwable);
2232 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2233 vpnUtil.unsetScheduledToRemoveForVpnInterface(interfaceName);