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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
17 import java.math.BigInteger;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Iterator;
21 import java.util.List;
23 import java.util.Objects;
24 import java.util.concurrent.ConcurrentHashMap;
25 import java.util.concurrent.ConcurrentLinkedQueue;
26 import java.util.concurrent.ExecutionException;
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.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
39 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
40 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
41 import org.opendaylight.genius.mdsalutil.MDSALUtil;
42 import org.opendaylight.genius.mdsalutil.NWUtil;
43 import org.opendaylight.genius.mdsalutil.NwConstants;
44 import org.opendaylight.genius.mdsalutil.cache.InstanceIdDataObjectCache;
45 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
46 import org.opendaylight.infrautils.caches.CacheProvider;
47 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
48 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
49 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
50 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
51 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
52 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
53 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
54 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
55 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
56 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderHandler;
57 import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput;
58 import org.opendaylight.netvirt.vpnmanager.populator.intfc.VpnPopulator;
59 import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry;
60 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
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.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
109 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
110 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
111 import org.slf4j.Logger;
112 import org.slf4j.LoggerFactory;
115 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager> {
117 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
118 private static final short DJC_MAX_RETRIES = 3;
120 private final DataBroker dataBroker;
121 private final ManagedNewTransactionRunner txRunner;
122 private final IBgpManager bgpManager;
123 private final IFibManager fibManager;
124 private final IMdsalApiManager mdsalManager;
125 private final IdManagerService idManager;
126 private final OdlInterfaceRpcService ifaceMgrRpcService;
127 private final VpnFootprintService vpnFootprintService;
128 private final IInterfaceManager interfaceManager;
129 private final IVpnManager vpnManager;
130 private final ArpResponderHandler arpResponderHandler;
131 private final JobCoordinator jobCoordinator;
133 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
135 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
136 new ConcurrentHashMap<>();
138 private final InstanceIdDataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
141 public VpnInterfaceManager(final DataBroker dataBroker,
142 final IBgpManager bgpManager,
143 final IdManagerService idManager,
144 final IMdsalApiManager mdsalManager,
145 final IFibManager fibManager,
146 final OdlInterfaceRpcService ifaceMgrRpcService,
147 final VpnFootprintService vpnFootprintService,
148 final IInterfaceManager interfaceManager,
149 final IVpnManager vpnManager,
150 final ArpResponderHandler arpResponderHandler,
151 final JobCoordinator jobCoordinator,
152 final CacheProvider cacheProvider) {
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;
168 vpnInstanceOpDataEntryCache = new InstanceIdDataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
169 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
170 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
173 public Runnable isNotifyTaskQueued(String intfName) {
174 return vpnIntfMap.remove(intfName);
178 public void start() {
179 LOG.info("{} start", getClass().getSimpleName());
180 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
185 public void close() {
187 vpnInstanceOpDataEntryCache.close();
191 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
192 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
196 protected VpnInterfaceManager getDataTreeChangeListener() {
197 return VpnInterfaceManager.this;
201 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
202 LOG.info("add: intfName {} onto vpnName {}",
203 vpnInterface.getName(),
204 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
205 addVpnInterface(identifier, vpnInterface, null, null);
208 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
209 final VpnInterface vpnInterface, String vpnName) {
210 synchronized (vpnName.intern()) {
211 if (isVpnInstanceReady(vpnName)) {
214 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
219 // TODO Clean up the exception handling
220 @SuppressWarnings("checkstyle:IllegalCatch")
221 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
222 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
223 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
224 String vpnName = vpnInterfaceVpnInstance.getVpnName();
225 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
229 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
230 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
231 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
232 final String interfaceName = key.getName();
234 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
235 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
236 vpnName, vpnInterface.getName());
239 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
240 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
241 List<Adjacency> copyOldAdjs = null;
242 if (oldAdjs != null) {
243 copyOldAdjs = new ArrayList<>();
244 copyOldAdjs.addAll(oldAdjs);
246 List<Adjacency> copyNewAdjs = null;
247 if (newAdjs != null) {
248 copyNewAdjs = new ArrayList<>();
249 copyNewAdjs.addAll(newAdjs);
251 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
254 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
255 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
256 final List<Adjacency> newAdjs,
257 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
258 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
259 final String interfaceName = key.getName();
260 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
261 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
262 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
263 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
264 if (interfaceState != null) {
266 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
267 final int ifIndex = interfaceState.getIfIndex();
268 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName, () -> {
269 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
270 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
271 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
272 LOG.info("addVpnInterface: VPN Interface add event - intfName {} vpnName {} on dpn {}" ,
273 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
274 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false, writeConfigTxn,
275 writeOperTxn, writeInvTxn, interfaceState, vpnName);
276 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
277 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
278 + " Update for swapping VPN {} case.", interfaceName, vpnName);
279 if (newAdjs != null) {
280 for (Adjacency adj : newAdjs) {
281 if (oldAdjs.contains(adj)) {
284 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
286 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd,
287 adj, dpnId, writeOperTxn, writeConfigTxn);
292 for (Adjacency adj : oldAdjs) {
293 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
295 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
296 writeOperTxn, writeConfigTxn);
300 ListenableFuture<Void> operFuture = writeOperTxn.submit();
303 } catch (ExecutionException e) {
304 LOG.error("addVpnInterface: Exception encountered while submitting operational future for"
305 + " addVpnInterface {} on vpn {}", vpnInterface.getName(), vpnName, e);
308 List<ListenableFuture<Void>> futures = new ArrayList<>();
309 ListenableFuture<Void> configFuture = writeConfigTxn.submit();
310 futures.add(configFuture);
311 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"));
312 futures.add(writeInvTxn.submit());
313 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
314 + " processed successfully", interfaceName, vpnName, dpnId);
317 } catch (NumberFormatException | IllegalStateException e) {
318 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
319 + "interface {}. Interface addition on vpn {} failed", interfaceName,
323 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
324 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(),
326 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
327 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
328 writeConfigTxn, vpnName);
329 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
330 vpnName, vpnInterface.getDpnId());
331 ListenableFuture<Void> futures = writeConfigTxn.submit();
332 String errorText = "addVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
333 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
334 ListenableFutures.addErrorLogging(futures, LOG, errorText);
335 return Collections.singletonList(futures);
338 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
339 + " is not available", interfaceName, vpnName);
342 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
343 + " as vpn is pending delete", interfaceName, vpnName,
344 vpnInterface.getDpnId());
348 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
349 // see comments below.
350 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
351 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
352 final int lportTag, boolean isInterfaceUp,
353 WriteTransaction writeConfigTxn,
354 WriteTransaction writeOperTxn,
355 WriteTransaction writeInvTxn,
356 Interface interfaceState,
357 final String vpnName) {
358 final String interfaceName = vpnInterface.getName();
359 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
360 interfaceName, vpnName);
361 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
362 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
363 if (!isInterfaceUp) {
364 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
365 interfaceName, dpId, vpnName);
366 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
367 if (vpnId == VpnConstants.INVALID_ID) {
368 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
369 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
374 boolean waitForVpnInterfaceOpRemoval = false;
375 if (opVpnInterface != null && !opVpnInterface.isScheduledForRemove()) {
376 String opVpnName = opVpnInterface.getVpnInstanceName();
377 String primaryInterfaceIp = null;
378 if (opVpnName.equals(vpnName)) {
379 // Please check if the primary VRF Entry does not exist for VPNInterface
380 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
382 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
383 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
385 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
386 + " for this vpn interface could not be obtained", interfaceName, dpId,
390 for (Adjacency adj : adjs) {
391 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
392 primaryInterfaceIp = adj.getIpAddress();
396 if (primaryInterfaceIp == null) {
397 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
398 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
402 // Get the rd of the vpn instance
403 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, primaryRd, primaryInterfaceIp);
405 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
406 + " bailing out from here.", interfaceName, dpId, vpnName);
409 waitForVpnInterfaceOpRemoval = true;
411 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
412 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
415 if (!waitForVpnInterfaceOpRemoval) {
416 // Add the VPNInterface and quit
417 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
418 null/*ipAddressSourceValuePair*/,
420 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
421 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
422 if (!isBgpVpnInternetVpn) {
423 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false /*isTunnelInterface*/,
426 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
428 if (interfaceManager.isExternalInterface(interfaceName)) {
429 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
430 NwConstants.ADD_FLOW);
435 // FIB didn't get a chance yet to clean up this VPNInterface
436 // Let us give it a chance here !
437 LOG.info("processVpnInterfaceUp: Trying to add VPN Interface {} on dpn {} for vpn {},"
438 + " but waiting for FIB to clean up! ", interfaceName, dpId, vpnName);
440 Runnable notifyTask = new VpnNotifyTask();
441 synchronized (notifyTask) {
442 // Per FB's "Unconditional wait" violation, the code should really verify that the condition it
443 // intends to wait for is not already satisfied before calling wait. However the VpnNotifyTask is
444 // published here while holding the lock on it so this path will hit the wait before notify can be
446 vpnIntfMap.put(interfaceName, notifyTask);
448 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
449 } catch (InterruptedException e) {
454 vpnIntfMap.remove(interfaceName);
457 if (opVpnInterface != null) {
458 LOG.warn("processVpnInterfaceUp: VPN Interface {} removal on dpn {} for vpn {}"
459 + " by FIB did not complete on time," + " bailing addition ...", interfaceName,
461 VpnUtil.unsetScheduledToRemoveForVpnInterface(txRunner, interfaceName);
464 // VPNInterface got removed, proceed with Add
465 LOG.info("processVpnInterfaceUp: Continuing to plumb vpn interface {} onto dpn {} for vpn {}",
466 interfaceName, dpId, vpnName);
467 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
468 null/*ipAddressSourceValuePair*/,
470 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
471 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
472 if (!isBgpVpnInternetVpn) {
473 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false/*isTunnelInterface*/, jobCoordinator);
475 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
476 + " FIB to clean up", interfaceName, dpId, vpnName);
477 if (interfaceManager.isExternalInterface(interfaceName)) {
478 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId,
479 lportTag, writeInvTxn, NwConstants.ADD_FLOW);
482 // Interface is retained in the DPN, but its Link Up.
483 // Advertise prefixes again for this interface to BGP
484 InstanceIdentifier<VpnInterface> identifier =
485 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName());
486 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
487 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
488 advertiseAdjacenciesForVpnToBgp(primaryRd, dpId, vpnInterfaceOpIdentifier, vpnName, interfaceName);
489 // Perform similar operation as interface add event for extraroutes.
490 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
491 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
492 if (!optAdjacencies.isPresent()) {
493 LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
496 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
497 for (Adjacency adjacency : adjacencies) {
498 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
501 // if BGPVPN Internet, filter only IPv6 Adjacencies
502 if (isBgpVpnInternetVpn && !VpnUtil.isAdjacencyEligibleToVpnInternet(
503 dataBroker, adjacency)) {
506 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
507 dpId, writeOperTxn, writeConfigTxn);
512 private void processExternalVpnInterface(String interfaceName, String vpnName, long vpnId, BigInteger dpId,
513 int lportTag, WriteTransaction writeInvTxn, int addOrRemove) {
516 // vpn instance of ext-net interface is the network-id
517 extNetworkId = new Uuid(vpnName);
518 } catch (IllegalArgumentException e) {
519 LOG.error("processExternalVpnInterface: VPN instance {} is not Uuid. Processing external vpn interface {}"
520 + " on dpn {} failed", vpnName, interfaceName, dpId);
524 List<Uuid> routerIds = VpnUtil.getExternalNetworkRouterIds(dataBroker, extNetworkId);
525 if (routerIds == null || routerIds.isEmpty()) {
526 LOG.info("processExternalVpnInterface: No router is associated with {}."
527 + " Bailing out of processing external vpn interface {} on dpn {} for vpn {}",
528 extNetworkId.getValue(), interfaceName, dpId, vpnName);
532 LOG.info("processExternalVpnInterface: Router-ids {} associated with exernal vpn-interface {} on dpn {}"
533 + " for vpn {}", routerIds, interfaceName, dpId, vpnName);
534 for (Uuid routerId : routerIds) {
535 String routerName = routerId.getValue();
536 BigInteger primarySwitch = VpnUtil.getPrimarySwitchForRouter(dataBroker, routerName);
537 if (Objects.equals(primarySwitch, dpId)) {
538 Routers router = VpnUtil.getExternalRouter(dataBroker, routerName);
539 if (router != null) {
540 if (addOrRemove == NwConstants.ADD_FLOW) {
541 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
542 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
543 dpId, interfaceName, lportTag, writeInvTxn);
545 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
546 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
547 dpId, interfaceName, lportTag);
550 LOG.error("processExternalVpnInterface: No external-router found for router-id {}. Bailing out of"
551 + " processing external vpn-interface {} on dpn {} for vpn {}", routerName,
552 interfaceName, dpId, vpnName);
558 // TODO Clean up the exception handling
559 @SuppressWarnings("checkstyle:IllegalCatch")
560 private void advertiseAdjacenciesForVpnToBgp(final String rd, BigInteger dpnId,
561 final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
562 String vpnName, String interfaceName) {
564 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} on dpn {} in vpn {}",
565 interfaceName, dpnId, vpnName);
568 if (rd.equals(vpnName)) {
569 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} on dpn {}"
570 + " as it is in internal vpn{} with rd {}", interfaceName, dpnId, vpnName, rd);
574 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} on dpn {} in vpn {} with rd {} ",
575 interfaceName, dpnId, vpnName, rd);
577 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
578 if (nextHopIp == null) {
579 LOG.error("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} on dpn {} is null,"
580 + " returning from advertising route with rd {} vpn {} to bgp", interfaceName, dpnId,
586 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
587 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
588 if (adjacencies.isPresent()) {
589 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
591 if (!nextHops.isEmpty()) {
592 LOG.debug("advertiseAdjacenciesForVpnToBgp: NextHops are {} for interface {} on dpn {} for vpn {}"
593 + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
594 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
595 long l3vni = vpnInstanceOpData.getL3vni();
596 VrfEntry.EncapType encapType = VpnUtil.isL3VpnOverVxLan(l3vni)
597 ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
598 for (Adjacency nextHop : nextHops) {
599 if (nextHop.getAdjacencyType() == AdjacencyType.ExtraRoute) {
602 String gatewayMac = null;
604 if (VpnUtil.isL3VpnOverVxLan(l3vni)) {
605 final VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
606 vpnInstanceOpData.getVpnInstanceName(), nextHop.getIpAddress());
607 gatewayMac = arpResponderHandler.getGatewayMacAddressForInterface(gwPort, interfaceName).get();
609 label = nextHop.getLabel();
612 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Adding Fib Entry rd {} prefix {}"
613 + " nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
614 bgpManager.advertisePrefix(rd, nextHop.getMacAddress(), nextHop.getIpAddress(), nextHopIp,
615 encapType, (int)label, l3vni, 0 /*l2vni*/,
617 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Added Fib Entry rd {} prefix {}"
618 + " nexthop {} label {} for interface {} on dpn {} for vpn {}", rd,
619 nextHop.getIpAddress(), nextHopIp, label, interfaceName, dpnId, vpnName);
620 } catch (Exception e) {
621 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to advertise prefix {} in vpn {} with rd {}"
622 + " for interface {} on dpn {}", nextHop.getIpAddress(),
623 vpnName, rd, interfaceName, dpnId, e);
630 // TODO Clean up the exception handling
631 @SuppressWarnings("checkstyle:IllegalCatch")
632 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
633 String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
635 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
636 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
638 String rd = VpnUtil.getVpnRd(dataBroker, interfaceName);
640 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
641 interfaceName, vpnName);
644 if (rd.equals(vpnName)) {
646 "withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in "
647 + "internal vpn{} with rd {}", interfaceName, vpnName, rd);
651 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", interfaceName,
653 if (adjacencies.isPresent()) {
654 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
656 if (!nextHops.isEmpty()) {
657 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
658 nextHops, interfaceName, vpnName, rd);
659 for (Adjacency nextHop : nextHops) {
661 if (nextHop.getAdjacencyType() != AdjacencyType.ExtraRoute) {
662 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removing Fib Entry rd {}"
663 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
664 interfaceName, vpnName);
665 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
666 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removed Fib Entry rd {}"
667 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
668 interfaceName, vpnName);
670 // Perform similar operation as interface delete event for extraroutes.
671 String allocatedRd = nextHop.getVrfId();
672 for (String nh : nextHop.getNextHopIpList()) {
673 deleteExtraRouteFromCurrentAndImportingVpns(
674 vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn);
677 } catch (Exception e) {
678 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
679 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
686 @SuppressWarnings("checkstyle:IllegalCatch")
687 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
688 String primaryRd, String interfaceName, final long vpnId,
689 WriteTransaction writeConfigTxn,
690 WriteTransaction writeOperTxn,
691 final WriteTransaction writeInvTxn,
692 Interface interfaceState) {
693 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
695 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
696 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
697 if (!adjacencies.isPresent()) {
698 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
699 null/*gwMac*/, writeOperTxn);
703 // Get the rd of the vpn instance
704 String nextHopIp = null;
706 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
707 } catch (Exception e) {
708 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
709 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
711 List<String> nhList = new ArrayList<>();
712 if (nextHopIp != null) {
713 nhList.add(nextHopIp);
714 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
715 interfaceName, dpnId, vpnName, nhList);
717 Optional<String> gwMac = Optional.absent();
718 String vpnInterfaceSubnetGwMacAddress = null;
719 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
720 Long l3vni = vpnInstanceOpData.getL3vni();
721 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
722 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
723 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
724 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
725 List<Adjacency> value = new ArrayList<>();
726 for (Adjacency nextHop : nextHops) {
727 String rd = primaryRd;
728 String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
729 if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
730 && NWUtil.isIpv4Address(nexthopIpValue)) {
731 String prefix = nextHop.getIpAddress() == null ? "null" :
732 VpnUtil.getIpPrefix(nextHop.getIpAddress());
733 LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
734 + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
737 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
738 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
739 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
740 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
741 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
742 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
744 LogicalDatastoreType.OPERATIONAL,
745 VpnUtil.getPrefixToInterfaceIdentifier(
746 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
747 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
749 final Uuid subnetId = nextHop.getSubnetId();
751 String gatewayIp = nextHop.getSubnetGatewayIp();
752 if (gatewayIp == null) {
753 Optional<String> gatewayIpOptional = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
754 if (gatewayIpOptional.isPresent()) {
755 gatewayIp = gatewayIpOptional.get();
759 if (gatewayIp != null) {
760 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
761 if (gwMac.isPresent()) {
762 // A valid mac-address is available for this subnet-gateway-ip
763 // Use this for programming ARP_RESPONDER table here. And save this
764 // info into vpnInterface operational, so it can used in VrfEntryProcessor
765 // to populate L3_GW_MAC_TABLE there.
766 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
767 gatewayIp, gwMac.get());
768 vpnInterfaceSubnetGwMacAddress = gwMac.get();
770 // A valid mac-address is not available for this subnet-gateway-ip
771 // Use the connected-mac-address to configure ARP_RESPONDER Table.
772 // Save this connected-mac-address as gateway-mac-address for the
773 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
774 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
775 if (gwMac.isPresent()) {
776 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
777 vpnId, writeInvTxn, NwConstants.ADD_FLOW, gwMac.get());
778 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
779 gatewayIp, gwMac.get());
781 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
782 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
784 subnetId, interfaceName, vpnName, gatewayIp);
788 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
789 + "cannot create ARP responder flow for interface name {}, vpnName {}",
790 subnetId, interfaceName, vpnName);
791 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
793 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
794 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
796 //Extra route adjacency
797 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
798 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
799 synchronized (vpnPrefixKey.intern()) {
800 java.util.Optional<String> rdToAllocate = VpnUtil
801 .allocateRdForExtraRouteAndUpdateUsedRdsMap(dataBroker, vpnId, null,
802 prefix, vpnName, nextHop.getNextHopIpList().get(0), dpnId);
803 if (rdToAllocate.isPresent()) {
804 rd = rdToAllocate.get();
805 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
808 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
812 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
813 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
814 interfaceName, dpnId);
816 // Please note that primary adjacency will use a subnet-gateway-mac-address that
817 // can be different from the gateway-mac-address within the VRFEntry as the
818 // gateway-mac-address is a superset.
819 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
820 : RouteOrigin.STATIC;
821 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
822 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
823 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
824 Adjacency operationalAdjacency = null;
826 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
827 } catch (NullPointerException e) {
828 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
829 input, e.getMessage());
832 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
833 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
834 vpnName, l3vni, origin,
835 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
837 value.add(operationalAdjacency);
840 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
841 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
842 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
844 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
845 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
846 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
848 for (Adjacency nextHop : aug.getAdjacency()) {
849 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
850 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
851 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
852 : RouteOrigin.STATIC;
853 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
854 registeredPopulator.populateFib(input, writeConfigTxn);
859 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
860 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
861 VpnInterfaceOpDataEntry opInterface =
862 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, Boolean.FALSE, lportTag, gwMac);
863 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
864 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
865 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
866 WriteTransaction.CREATE_MISSING_PARENTS);
867 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
868 interfaceName, dpnId, vpnName);
871 // TODO Clean up the exception handling
872 @SuppressWarnings("checkstyle:IllegalCatch")
873 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
874 StateTunnelList stateTunnelList,
875 WriteTransaction writeConfigTxn,
876 WriteTransaction writeOperTxn) {
878 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
879 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
880 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
881 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
882 if (adjList.isEmpty()) {
883 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
884 vpnInterface, srcDpnId);
887 String prefix = null;
889 List<Adjacency> value = new ArrayList<>();
890 boolean isNextHopAddReqd = false;
891 String vpnName = vpnInterface.getVpnInstanceName();
892 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
893 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
894 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
895 vpnInterface.getName(), vpnInterface.getDpnId(),
896 vpnInterface.getVpnInstanceName(), adjList);
897 for (Adjacency adj : adjList) {
898 String rd = adj.getVrfId();
899 rd = rd != null ? rd : vpnName;
900 prefix = adj.getIpAddress();
901 label = adj.getLabel();
902 List<String> nhList = Collections.singletonList(srcTepIp);
903 List<String> nextHopList = adj.getNextHopIpList();
904 // If TEP is added , update the nexthop of primary adjacency.
905 // Secondary adj nexthop is already pointing to primary adj IP address.
906 if (nextHopList != null && !nextHopList.isEmpty() && nextHopList.get(0).equalsIgnoreCase(srcTepIp)) {
907 /* everything right already */
909 isNextHopAddReqd = true;
912 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
913 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
915 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
916 if (!vrfEntryOptional.isPresent()) {
919 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
920 if (!nhList.contains(srcTepIp)) {
921 nhList.add(srcTepIp);
922 isNextHopAddReqd = true;
927 if (isNextHopAddReqd) {
928 updateLabelMapper(label, nhList);
929 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
930 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
931 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
932 // Update the VRF entry with nextHop
933 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
934 label, true, writeConfigTxn);
936 //Get the list of VPN's importing this route(prefix) .
937 // Then update the VRF entry with nhList
938 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
939 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
940 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
941 String vpnRd = vpn.getVrfId();
943 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
944 srcTepIp, label, true, writeConfigTxn);
945 LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
946 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
947 vpnInterface.getName(), srcDpnId, vpnName,
948 vpn.getVpnInstanceName(), vpnRd);
951 // Advertise the prefix to BGP only for external vpn
952 // since there is a nexthop change.
954 if (!rd.equalsIgnoreCase(vpnName)) {
955 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, nhList,
956 VrfEntry.EncapType.Mplsgre, (int)label, 0 /*evi*/, 0 /*l2vni*/,
957 null /*gatewayMacAddress*/);
959 LOG.info("updateVpnInterfaceOnTepAdd: Advertised rd {} prefix {} nhList {} label {}"
960 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label, vpnInterface.getName(),
962 } catch (Exception ex) {
963 LOG.error("updateVpnInterfaceOnTepAdd: Exception when advertising prefix {} nh {} label {}"
964 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
965 vpnInterface.getName(), srcDpnId, vpnName, ex);
969 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
970 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
971 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
972 .addAugmentation(AdjacenciesOp.class, aug).build();
973 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
974 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
975 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
976 WriteTransaction.CREATE_MISSING_PARENTS);
977 LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
978 vpnInterface.getName(), srcDpnId, vpnName);
982 // TODO Clean up the exception handling
983 @SuppressWarnings("checkstyle:IllegalCatch")
984 public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
985 StateTunnelList stateTunnelList,
986 WriteTransaction writeConfigTxn,
987 WriteTransaction writeOperTxn) {
989 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
990 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
991 String prefix = null;
993 boolean isNextHopRemoveReqd = false;
994 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
995 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
996 String vpnName = vpnInterface.getVpnInstanceName();
997 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
998 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
999 if (adjList != null) {
1000 List<Adjacency> value = new ArrayList<>();
1001 LOG.info("updateVpnInterfaceOnTepDelete: AdjacencyList for interface {} on dpn {} vpn {} is {}",
1002 vpnInterface.getName(), vpnInterface.getDpnId(),
1003 vpnInterface.getVpnInstanceName(), adjList);
1004 for (Adjacency adj : adjList) {
1005 List<String> nhList = new ArrayList<>();
1006 String rd = adj.getVrfId();
1007 rd = rd != null ? rd : vpnName;
1008 prefix = adj.getIpAddress();
1009 List<String> nextHopList = adj.getNextHopIpList();
1010 label = adj.getLabel();
1011 if (nextHopList != null && !nextHopList.isEmpty()) {
1012 isNextHopRemoveReqd = true;
1014 // If TEP is deleted , remove the nexthop from primary adjacency.
1015 // Secondary adj nexthop will continue to point to primary adj IP address.
1016 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1017 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
1019 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
1020 if (!vrfEntryOptional.isPresent()) {
1023 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
1024 if (nhList.contains(srcTepIp)) {
1025 nhList.remove(srcTepIp);
1026 isNextHopRemoveReqd = true;
1031 if (isNextHopRemoveReqd) {
1032 updateLabelMapper(label, nhList);
1033 LOG.info("updateVpnInterfaceOnTepDelete: Updated label mapper : label {} dpn {} prefix {}"
1034 + " nexthoplist {} vpn {} vpnid {} rd {} interface {}", label, srcDpnId,
1035 prefix, nhList, vpnName,
1036 vpnId, rd, vpnInterface.getName());
1037 // Update the VRF entry with removed nextHop
1038 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
1039 label, false, writeConfigTxn);
1041 //Get the list of VPN's importing this route(prefix) .
1042 // Then update the VRF entry with nhList
1043 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1044 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1045 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1046 String vpnRd = vpn.getVrfId();
1047 if (vpnRd != null) {
1048 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1049 srcTepIp, label, false, writeConfigTxn);
1050 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1051 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1052 nhList, label, vpnInterface.getName(), srcDpnId,
1054 vpn.getVpnInstanceName(), vpnRd);
1058 // Withdraw prefix from BGP only for external vpn.
1060 if (!rd.equalsIgnoreCase(vpnName)) {
1061 bgpManager.withdrawPrefix(rd, prefix);
1063 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1064 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1065 vpnInterface.getName(), srcDpnId,
1067 } catch (Exception ex) {
1068 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1069 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
1070 vpnInterface.getName(), srcDpnId, vpnName, ex);
1074 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1075 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1076 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1077 .addAugmentation(AdjacenciesOp.class, aug).build();
1078 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1079 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1080 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1081 WriteTransaction.CREATE_MISSING_PARENTS);
1082 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1083 vpnInterface.getName(), srcDpnId, vpnName);
1087 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1088 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1090 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1091 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
1092 if (vpnInstanceOpDataEntry == null) {
1093 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1094 + " to check for vpns exporting the routes", vpnName);
1095 return vpnsToExportRoute;
1098 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1099 if (input.getVpnInstanceName() == null) {
1100 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1104 return !input.getVpnInstanceName().equals(vpnName);
1107 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1108 Iterable<String> commonRTs =
1109 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1110 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1111 return Iterators.size(commonRTs.iterator()) > 0;
1115 VpnUtil.getAllVpnInstanceOpData(dataBroker).stream().filter(excludeVpn).filter(matchRTs).collect(
1116 Collectors.toList());
1117 return vpnsToExportRoute;
1120 // TODO Clean up the exception handling
1121 @SuppressWarnings("checkstyle:IllegalCatch")
1122 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1123 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1124 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1125 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getVrfId());
1126 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1127 if (vrfEntries != null) {
1128 for (VrfEntry vrfEntry : vrfEntries) {
1130 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1131 RouteOrigin.value(vrfEntry.getOrigin()))) {
1132 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1133 + " is not a controller managed non intervpn link route. Ignoring.",
1134 vpn.getVrfId(), vrfEntry.getDestPrefix());
1137 String prefix = vrfEntry.getDestPrefix();
1138 String gwMac = vrfEntry.getGatewayMacAddress();
1139 vrfEntry.getRoutePaths().forEach(routePath -> {
1140 String nh = routePath.getNexthopAddress();
1141 int label = routePath.getLabel().intValue();
1142 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1143 vrfEntry.getOrigin()))) {
1144 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1145 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1147 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1148 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1149 0 /*l3vni*/, gwMac, null /*parentVpnRd*/, RouteOrigin.SELF_IMPORTED,
1152 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} prefix {}"
1153 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1155 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1156 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, writeConfigTxn);
1159 } catch (RuntimeException e) {
1160 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1161 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1162 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1165 writeConfigTxn.submit();
1167 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1168 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1173 @SuppressWarnings("checkstyle:IllegalCatch")
1175 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1176 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1177 final String interfaceName = key.getName();
1178 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1179 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1180 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1184 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1185 final VpnInterface vpnInterface, final String vpnName,
1186 final String interfaceName) {
1187 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1188 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
1189 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1190 deleteFibEntryForRouterInterface(vpnInterface, writeConfigTxn, vpnName);
1191 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1192 ListenableFuture<Void> futures = writeConfigTxn.submit();
1193 String errorText = "removeVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
1194 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
1195 ListenableFutures.addErrorLogging(futures, LOG, errorText);
1196 return Collections.singletonList(futures);
1197 }, DJC_MAX_RETRIES);
1199 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1200 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1204 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1205 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1206 final VpnInterface vpnInterface, final String vpnName,
1207 final String interfaceName, final Interface interfaceState) {
1208 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1209 vpnName, vpnInterface.getDpnId());
1210 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1211 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1213 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1214 ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1215 writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1216 writeOperTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1217 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1218 interfaceName, vpnName);
1219 BigInteger dpId = BigInteger.ZERO;
1221 String gwMacAddress = null;
1222 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1223 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1224 final Optional<VpnInterfaceOpDataEntry> optVpnInterface =
1225 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1226 if (interfaceState != null) {
1228 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1229 } catch (NumberFormatException | IllegalStateException e) {
1230 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1231 + " data store for interface {} on dpn {} for vpn {} Fetching"
1232 + " from vpn interface op data store. ", interfaceName,
1233 vpnInterface.getDpnId(), vpnName, e);
1234 dpId = BigInteger.ZERO;
1236 ifIndex = interfaceState.getIfIndex();
1237 gwMacAddress = interfaceState.getPhysAddress().getValue();
1239 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1240 + " from vpn interface op.", interfaceName);
1241 if (optVpnInterface.isPresent()) {
1242 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1243 dpId = vpnOpInterface.getDpnId();
1244 ifIndex = vpnOpInterface.getLportTag().intValue();
1245 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1247 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1248 + " as interfaceState and vpn interface op is not"
1249 + " available", interfaceName, vpnName);
1253 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1254 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1255 writeConfigTxn, writeOperTxn, writeInvTxn);
1257 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1259 interfaceName, vpnInterface.getDpnId(), vpnName);
1261 futures.add(configFuture);
1262 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1264 }, DJC_MAX_RETRIES);
1267 protected void processVpnInterfaceDown(BigInteger dpId,
1268 String interfaceName,
1271 VpnInterfaceOpDataEntry vpnOpInterface,
1272 boolean isInterfaceStateDown,
1273 WriteTransaction writeConfigTxn,
1274 WriteTransaction writeOperTxn,
1275 WriteTransaction writeInvTxn) {
1276 if (vpnOpInterface == null) {
1277 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1278 + " as it is not available in operational data store", interfaceName, dpId);
1281 final String vpnName = vpnOpInterface.getVpnInstanceName();
1282 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1283 interfaceName, vpnName);
1284 if (!isInterfaceStateDown) {
1285 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1286 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1288 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1289 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1290 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1291 if (interfaceManager.isExternalInterface(interfaceName)) {
1292 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1293 NwConstants.DEL_FLOW);
1295 if (!isBgpVpnInternetVpn) {
1296 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1298 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1299 + " successful", interfaceName, dpId, vpnName);
1301 // Interface is retained in the DPN, but its Link Down.
1302 // Only withdraw the prefixes for this interface from BGP
1303 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1307 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1308 final String vpnName, final long vpnId, String gwMac,
1309 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1310 final WriteTransaction writeInvTxn) {
1312 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1313 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1314 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1315 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1317 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1318 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1319 interfaceName, dpnId, vpnName, primaryRd);
1320 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1321 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1322 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1323 interfaceName, dpnId, vpnName, nextHops);
1324 for (Adjacency nextHop : nextHops) {
1325 if (nextHop.isPhysNetworkFunc()) {
1326 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1327 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1328 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1329 null/*writeCfgTxn*/);
1331 String rd = nextHop.getVrfId();
1332 List<String> nhList;
1333 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1334 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1336 // This is a primary adjacency
1337 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1338 : Collections.emptyList();
1339 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1340 interfaceName, writeInvTxn);
1342 if (!nhList.isEmpty()) {
1343 if (rd.equals(vpnName)) {
1344 //this is an internal vpn - the rd is assigned to the vpn instance name;
1345 //remove from FIB directly
1346 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1347 interfaceName, dpnId, writeConfigTxn));
1349 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd, interfaceName,
1353 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1354 + " interface {}", nextHop.getIpAddress(), rd,
1355 nextHop.getAdjacencyType().toString(), interfaceName);
1356 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1357 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1360 String ip = nextHop.getIpAddress().split("/")[0];
1361 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1362 if (vpnVipToPort != null) {
1363 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip);
1364 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed adjacency for Interface {}"
1365 + " ip {} on dpn {} for vpn {} from VpnPortData Entry", vpnVipToPort.getPortName(),
1366 ip, dpnId, vpnName);
1370 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1371 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1372 + " Removing it.", interfaceName, vpnName, dpnId);
1373 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1377 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1378 String interfaceName, BigInteger dpnId,
1379 WriteTransaction writeConfigTxn) {
1381 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1383 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1384 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1385 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1389 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1390 BigInteger dpnId, String rd, String interfaceName,
1391 WriteTransaction writeConfigTxn) {
1392 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1393 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1394 nhList.forEach((nh) -> {
1395 //IRT: remove routes from other vpns importing it
1396 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1397 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1398 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1399 String vpnRd = vpn.getVrfId();
1400 if (vpnRd != null) {
1401 fibManager.removeOrUpdateFibEntry(vpnRd,
1402 nextHop.getIpAddress(), nh, writeConfigTxn);
1403 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1404 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1405 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1406 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1412 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1413 int lportTag, String gwMac, String interfaceName,
1414 WriteTransaction writeInvTxn) {
1415 final Uuid subnetId = nextHop.getSubnetId();
1416 if (nextHop.getSubnetGatewayMacAddress() == null) {
1417 // A valid mac-address was not available for this subnet-gateway-ip
1418 // So a connected-mac-address was used for this subnet and we need
1419 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1420 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1421 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1423 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1427 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1428 String interfaceName) {
1429 // This is either an extra-route (or) a learned IP via subnet-route
1430 List<String> nhList = null;
1431 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1432 if (nextHopIp == null || nextHopIp.isEmpty()) {
1433 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1434 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1435 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1437 nhList = Collections.emptyList();
1439 nhList = Collections.singletonList(nextHopIp);
1444 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1445 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1446 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1447 // else use connected interface
1448 if (gwPort != null && gwPort.isSubnetIp()) {
1449 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1450 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1451 return Optional.of(gwPort.getMacAddress());
1453 return Optional.absent();
1457 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1458 final VpnInterface update) {
1459 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1460 update.getDpnId(), original.getVpnInstanceNames(),
1461 update.getVpnInstanceNames());
1462 final String vpnInterfaceName = update.getName();
1463 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1464 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1465 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1466 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1467 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1468 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1469 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1471 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1472 //handles switching between <internal VPN - external VPN>
1473 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1474 LOG.info("update: handled VPNInterface {} on dpn {} update"
1475 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1476 original.getName(), dpnId,
1477 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1478 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1481 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1482 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1483 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1484 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1485 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1486 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1487 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1488 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1489 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1490 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1491 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1492 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1493 update.getName(), newVpnName);
1494 //handle both addition and removal of adjacencies
1495 //currently, new adjacency may be an extra route
1496 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1497 if (!oldAdjs.equals(newAdjs)) {
1498 for (Adjacency adj : copyNewAdjs) {
1499 if (copyOldAdjs.contains(adj)) {
1500 copyOldAdjs.remove(adj);
1502 // add new adjacency - right now only extra route will hit this path
1503 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1504 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1505 dpnId, writeOperTxn, writeConfigTxn);
1507 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to vpn "
1508 + "interface {} on vpn {} dpnId {}",
1509 adj.getIpAddress(), adj.getNextHopIpList(),
1510 adj.getLabel(), adj.getSubnetId(), update.getName(),
1514 for (Adjacency adj : copyOldAdjs) {
1515 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1516 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1517 writeOperTxn, writeConfigTxn);
1519 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1520 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj.getNextHopIpList(),
1521 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1524 ListenableFuture<Void> operFuture = writeOperTxn.submit();
1527 } catch (ExecutionException e) {
1528 LOG.error("Exception encountered while submitting operational future for update"
1529 + " VpnInterface {} on vpn {}", vpnInterfaceName, newVpnName, e);
1532 List<ListenableFuture<Void>> futures = new ArrayList<>();
1533 futures.add(writeConfigTxn.submit());
1534 LOG.info("update: vpn interface updated for interface {} oldVpn(s) {} newVpn {}"
1535 + "processed successfully", update.getName(),
1536 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()), newVpnName);
1540 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1541 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1546 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1547 VpnInterface original, VpnInterface update) {
1548 boolean isSwap = Boolean.FALSE;
1549 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1550 final String interfaceName = key.getName();
1551 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1552 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1553 List<String> oldVpnListCopy = new ArrayList<>();
1554 oldVpnListCopy.addAll(oldVpnList);
1555 List<String> newVpnList = update.getVpnInstanceNames().stream()
1556 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1557 oldVpnList.removeAll(newVpnList);
1558 newVpnList.removeAll(oldVpnListCopy);
1559 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1560 for (String oldVpnName: oldVpnList) {
1561 isSwap = Boolean.TRUE;
1562 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1563 + " running config-driven swap removal", interfaceName, oldVpnName);
1564 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1565 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1566 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1568 //Wait for previous interface bindings to be removed
1571 } catch (InterruptedException e) {
1574 for (String newVpnName: newVpnList) {
1575 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1576 isSwap = Boolean.TRUE;
1577 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1578 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1579 + "running config-driven swap addition", interfaceName, newVpnName);
1580 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1581 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1582 ? origAdjs.getAdjacency() : new ArrayList<>();
1583 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1584 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1585 ? updateAdjs.getAdjacency() : new ArrayList<>();
1587 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1588 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1589 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1590 interfaceName, oldVpnListCopy, newVpnName);
1597 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1598 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1599 synchronized (label.toString().intern()) {
1600 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1601 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1602 Optional<LabelRouteInfo> opResult = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
1603 if (opResult.isPresent()) {
1604 LabelRouteInfo labelRouteInfo =
1605 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1606 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, labelRouteInfo);
1609 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label, nextHopIpList);
1612 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1613 SubnetRoute route, WriteTransaction writeConfigTxn) {
1615 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1616 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, null /* parentVpnRd */)
1617 .addAugmentation(SubnetRoute.class, route).build();
1618 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1619 InstanceIdentifierBuilder<VrfTables> idBuilder =
1620 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1621 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1622 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1623 if (writeConfigTxn != null) {
1624 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1626 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1628 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1629 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1632 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1633 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1634 WriteTransaction writeConfigTxn) {
1636 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1637 LogicalDatastoreType.OPERATIONAL, identifier);
1639 if (optVpnInterface.isPresent()) {
1640 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1641 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1642 String vpnName = currVpnIntf.getVpnInstanceName();
1643 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1644 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1645 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker,
1646 LogicalDatastoreType.OPERATIONAL, adjPath);
1647 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1648 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1649 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1650 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1651 List<Adjacency> adjacencies;
1652 if (optAdjacencies.isPresent()) {
1653 adjacencies = optAdjacencies.get().getAdjacency();
1655 // This code will be hit in case of first PNF adjacency
1656 adjacencies = new ArrayList<>();
1658 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1659 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1660 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1661 Adjacency operationalAdjacency = null;
1662 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()) {
1663 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1664 : RouteOrigin.STATIC;
1665 String nh = adj.getNextHopIpList().get(0);
1666 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1667 synchronized (vpnPrefixKey.intern()) {
1668 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1669 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1670 if (rdToAllocate.isPresent()) {
1671 input.setRd(rdToAllocate.get());
1672 operationalAdjacency = populator.createOperationalAdjacency(input);
1673 int label = operationalAdjacency.getLabel().intValue();
1674 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1675 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1676 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1677 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1678 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1679 vpnName, label, currVpnIntf.getName(), dpnId);
1681 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}", vpnName,
1685 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1686 // Keeping the MPLS check for now.
1687 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1688 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1689 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1690 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1691 vpnsToImportRoute.forEach(vpn -> {
1692 if (vpn.getVrfId() != null) {
1693 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1694 dataBroker, vpn.getVpnId(), vpnId, prefix,
1695 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1697 rds -> vpnManager.addExtraRoute(
1698 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1699 adj.getIpAddress(), nh, rds,
1700 currVpnIntf.getVpnInstanceName(),
1701 l3vni, RouteOrigin.SELF_IMPORTED,
1702 currVpnIntf.getName(), opAdjacency, encapType, writeConfigTxn));
1707 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1708 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1709 currVpnIntf.getName(), vpnName);
1711 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1714 LogicalDatastoreType.OPERATIONAL,
1715 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1716 adj.getSubnetId().getValue()), prefix),
1717 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1718 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1720 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1721 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */, 0 /*l3vni*/,
1722 null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1724 input.setRd(adj.getVrfId());
1726 if (operationalAdjacency == null) {
1727 operationalAdjacency = populator.createOperationalAdjacency(input);
1729 adjacencies.add(operationalAdjacency);
1730 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1731 VpnInterfaceOpDataEntry newVpnIntf =
1732 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1733 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1734 currVpnIntf.getGatewayMacAddress());
1736 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1740 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1741 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1742 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1745 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1746 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1747 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1748 LogicalDatastoreType.OPERATIONAL, identifier);
1750 if (optVpnInterface.isPresent()) {
1751 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1753 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1754 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1755 if (optAdjacencies.isPresent()) {
1756 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1758 if (!adjacencies.isEmpty()) {
1759 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1760 Iterator<Adjacency> adjIt = adjacencies.iterator();
1761 while (adjIt.hasNext()) {
1762 Adjacency adjElem = adjIt.next();
1763 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1764 String rd = adjElem.getVrfId();
1767 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1768 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1769 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1770 currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove(),
1771 currVpnIntf.getLportTag(), currVpnIntf.getGatewayMacAddress());
1773 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1774 if (adj.getNextHopIpList() != null) {
1775 for (String nh : adj.getNextHopIpList()) {
1776 deleteExtraRouteFromCurrentAndImportingVpns(
1777 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1778 currVpnIntf.getName(), writeConfigTxn);
1780 } else if (adj.isPhysNetworkFunc()) {
1781 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1782 adj.getIpAddress(), adj.getSubnetId());
1783 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1791 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1792 dpnId, adj.getVrfId());
1794 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1795 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1800 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1801 String rd, String intfName, WriteTransaction writeConfigTxn) {
1802 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1803 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1804 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1805 String vpnRd = vpn.getVrfId();
1806 if (vpnRd != null) {
1807 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
1812 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1813 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1814 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1815 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1818 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1819 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1820 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1823 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1824 WriteTransaction writeOperTxn) {
1825 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1826 if (dpId.equals(BigInteger.ZERO)) {
1827 LOG.error("addToNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1828 + " association model", vpnInterfaceName, routerName);
1832 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1834 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1835 .OPERATIONAL, routerDpnListIdentifier);
1836 RouterInterfaces routerInterface =
1837 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1838 vpnInterfaceName).build();
1839 if (optionalRouterDpnList.isPresent()) {
1840 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1841 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1843 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1844 builder.setRouterId(routerName);
1845 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1846 builder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1847 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1848 getRouterId(routerName),
1849 builder.build(), true);
1853 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1854 WriteTransaction writeOperTxn) {
1855 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1856 if (dpId.equals(BigInteger.ZERO)) {
1857 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1858 + " dissociation model", vpnInterfaceName, routerName);
1862 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1863 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1864 .OPERATIONAL, routerDpnListIdentifier);
1865 if (optionalRouterDpnList.isPresent()) {
1866 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1867 RouterInterfaces routerInterface =
1868 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1869 vpnInterfaceName).build();
1871 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1872 if (routerInterfaces.isEmpty()) {
1873 if (writeOperTxn != null) {
1874 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1876 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1879 if (writeOperTxn != null) {
1880 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1881 RouterInterfaces.class,
1882 new RouterInterfacesKey(vpnInterfaceName)));
1884 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL,
1885 routerDpnListIdentifier.child(
1886 RouterInterfaces.class,
1887 new RouterInterfacesKey(vpnInterfaceName)));
1894 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1895 WriteTransaction writeOperTxn) {
1896 if (dpId.equals(BigInteger.ZERO)) {
1897 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1898 + " dissociation model", vpnInterfaceName, routerName);
1902 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1903 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1904 .OPERATIONAL, routerDpnListIdentifier);
1905 if (optionalRouterDpnList.isPresent()) {
1906 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1907 RouterInterfaces routerInterface =
1908 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1909 vpnInterfaceName).build();
1910 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1911 if (routerInterfaces.isEmpty()) {
1912 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1914 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1915 RouterInterfaces.class,
1916 new RouterInterfacesKey(vpnInterfaceName)));
1922 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1923 WriteTransaction writeConfigTxn, String vpnName) {
1924 if (vpnInterface == null) {
1927 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
1929 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1930 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1933 for (Adjacency adj : adjs) {
1934 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1935 String primaryInterfaceIp = adj.getIpAddress();
1936 String macAddress = adj.getMacAddress();
1937 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1939 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1940 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1942 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1943 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1944 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1945 routerInt, label, writeConfigTxn);
1946 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1947 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1952 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1953 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1954 primaryRd, vpnName);
1957 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1958 WriteTransaction writeConfigTxn, String vpnName) {
1959 Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
1960 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1962 List<Adjacency> adjsList = adjs.getAdjacency();
1963 for (Adjacency adj : adjsList) {
1964 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1965 String primaryInterfaceIp = adj.getIpAddress();
1966 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1967 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1968 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1969 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1974 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
1975 vpnInterface.getName(), rd);
1979 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
1980 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
1981 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
1982 vpnName, intefaceData.vpnInterface.getName());
1985 final VpnInterfaceKey key = intefaceData.identifier
1986 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1987 final String interfaceName = key.getName();
1988 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
1989 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1990 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
1991 intefaceData.identifier, vpnName);
1995 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
1996 VpnInterface vpnInterface, String vpnName) {
1997 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
1999 if (vpnInterfaces == null) {
2000 vpnInterfaces = new ConcurrentLinkedQueue<>();
2002 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2003 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2004 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2005 vpnInterface.getName(), vpnName);
2008 public boolean isVpnInstanceReady(String vpnInstanceName) {
2009 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnInstanceName);
2010 if (vpnRd == null) {
2013 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
2015 return vpnInstanceOpDataEntry != null;
2018 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2019 synchronized (vpnInstanceName.intern()) {
2020 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2021 unprocessedVpnInterfaces.get(vpnInstanceName);
2022 if (vpnInterfaces != null) {
2023 while (!vpnInterfaces.isEmpty()) {
2024 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2025 if (hasVpnInstanceCreatedSuccessfully) {
2026 processSavedInterface(savedInterface, vpnInstanceName);
2027 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2028 savedInterface.vpnInterface.getName(), vpnInstanceName);
2030 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2031 savedInterface.vpnInterface.getName(), vpnInstanceName);
2035 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2040 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2041 VpnInterface vpnInterface) {
2042 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2043 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2044 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2045 if (vpnInterfaces != null) {
2046 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2047 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2048 + "unprocessed list", vpnInterface.getName(),
2049 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2052 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2053 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2058 public void vpnInstanceIsReady(String vpnInstanceName) {
2059 processSavedInterfaces(vpnInstanceName, true);
2062 public void vpnInstanceFailed(String vpnInstanceName) {
2063 processSavedInterfaces(vpnInstanceName, false);
2066 private static class UnprocessedVpnInterfaceData {
2067 InstanceIdentifier<VpnInterface> identifier;
2068 VpnInterface vpnInterface;
2070 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2071 this.identifier = identifier;
2072 this.vpnInterface = vpnInterface;
2076 public int hashCode() {
2077 final int prime = 31;
2079 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2080 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2085 public boolean equals(Object obj) {
2092 if (getClass() != obj.getClass()) {
2095 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2096 if (identifier == null) {
2097 if (other.identifier != null) {
2100 } else if (!identifier.equals(other.identifier)) {
2103 if (vpnInterface == null) {
2104 if (other.vpnInterface != null) {
2107 } else if (!vpnInterface.equals(other.vpnInterface)) {
2114 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2115 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
2116 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
2117 if (vpnInstanceOpData == null) {
2120 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2121 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2124 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2125 vpnToDpnLists.forEach(vpnToDpnList -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2126 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2127 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2128 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = VpnUtil.read(dataBroker,
2129 LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2130 if (!vpnInterfaceOptional.isPresent()) {
2133 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2134 vpnInterface.getInterfaceName());
2135 if (configVpnAdjacencies == null) {
2136 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2139 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2140 .getAugmentation(AdjacenciesOp.class).getAdjacency();
2141 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2142 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2143 // in operational DS. These unprocessed adjacencies will be handled below.
2144 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2145 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2146 configVpnAdjacencies.stream()
2147 .filter(adjacency -> operationVpnAdjacencies.stream()
2148 .noneMatch(operationalAdjacency ->
2149 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2150 .forEach(adjacency -> {
2151 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2152 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2154 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
2155 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
2156 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2157 addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd, adjacency,
2158 vpnInterfaceOptional.get().getDpnId(), writeConfigTxn, writeOperTxn);
2159 ListenableFuture<Void> operFuture = writeOperTxn.submit();
2162 } catch (ExecutionException | InterruptedException e) {
2163 LOG.error("Exception encountered while submitting operational"
2164 + " future for vpnInterface {}", vpnInterface, e);
2166 List<ListenableFuture<Void>> futures = new ArrayList<>();
2167 futures.add(writeConfigTxn.submit());
2170 return Collections.emptyList();
2177 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2178 private final String interfaceName;
2179 private final boolean add;
2180 private final String txnDestination;
2182 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2183 this.interfaceName = interfaceName;
2185 this.txnDestination = transactionDest;
2189 public void onSuccess(Void voidObj) {
2191 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2192 interfaceName, txnDestination);
2194 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2199 public void onFailure(Throwable throwable) {
2201 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2202 interfaceName, txnDestination, throwable);
2204 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2205 VpnUtil.unsetScheduledToRemoveForVpnInterface(txRunner, interfaceName);