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
1215 .callWithNewWriteOnlyTransactionAndSubmit(writeConfigTxn -> {
1216 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeOperTxn -> {
1217 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1218 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1219 interfaceName, vpnName);
1220 BigInteger dpId = BigInteger.ZERO;
1222 String gwMacAddress = null;
1223 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1224 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1225 final Optional<VpnInterfaceOpDataEntry> optVpnInterface =
1226 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1227 if (interfaceState != null) {
1229 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1230 } catch (NumberFormatException | IllegalStateException e) {
1231 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1232 + " data store for interface {} on dpn {} for vpn {} Fetching"
1233 + " from vpn interface op data store. ", interfaceName,
1234 vpnInterface.getDpnId(), vpnName, e);
1235 dpId = BigInteger.ZERO;
1237 ifIndex = interfaceState.getIfIndex();
1238 gwMacAddress = interfaceState.getPhysAddress().getValue();
1240 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1241 + " from vpn interface op.", interfaceName);
1242 if (optVpnInterface.isPresent()) {
1243 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1244 dpId = vpnOpInterface.getDpnId();
1245 ifIndex = vpnOpInterface.getLportTag().intValue();
1246 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1248 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1249 + " as interfaceState and vpn interface op is not"
1250 + " available", interfaceName, vpnName);
1254 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1255 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1256 writeConfigTxn, writeOperTxn, writeInvTxn);
1258 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1260 interfaceName, vpnInterface.getDpnId(), vpnName);
1264 futures.add(configFuture);
1265 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1267 }, DJC_MAX_RETRIES);
1270 protected void processVpnInterfaceDown(BigInteger dpId,
1271 String interfaceName,
1274 VpnInterfaceOpDataEntry vpnOpInterface,
1275 boolean isInterfaceStateDown,
1276 WriteTransaction writeConfigTxn,
1277 WriteTransaction writeOperTxn,
1278 WriteTransaction writeInvTxn) {
1279 if (vpnOpInterface == null) {
1280 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1281 + " as it is not available in operational data store", interfaceName, dpId);
1284 final String vpnName = vpnOpInterface.getVpnInstanceName();
1285 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1286 interfaceName, vpnName);
1287 if (!isInterfaceStateDown) {
1288 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1289 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1291 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1292 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1293 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1294 if (interfaceManager.isExternalInterface(interfaceName)) {
1295 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1296 NwConstants.DEL_FLOW);
1298 if (!isBgpVpnInternetVpn) {
1299 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1301 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1302 + " successful", interfaceName, dpId, vpnName);
1304 // Interface is retained in the DPN, but its Link Down.
1305 // Only withdraw the prefixes for this interface from BGP
1306 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1310 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1311 final String vpnName, final long vpnId, String gwMac,
1312 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1313 final WriteTransaction writeInvTxn) {
1315 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1316 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1317 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1318 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1320 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1321 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1322 interfaceName, dpnId, vpnName, primaryRd);
1323 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1324 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1325 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1326 interfaceName, dpnId, vpnName, nextHops);
1327 for (Adjacency nextHop : nextHops) {
1328 if (nextHop.isPhysNetworkFunc()) {
1329 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1330 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1331 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1332 null/*writeCfgTxn*/);
1334 String rd = nextHop.getVrfId();
1335 List<String> nhList;
1336 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1337 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1339 // This is a primary adjacency
1340 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1341 : Collections.emptyList();
1342 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1343 interfaceName, writeInvTxn);
1345 if (!nhList.isEmpty()) {
1346 if (rd.equals(vpnName)) {
1347 //this is an internal vpn - the rd is assigned to the vpn instance name;
1348 //remove from FIB directly
1349 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1350 interfaceName, dpnId, writeConfigTxn));
1352 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd, interfaceName,
1356 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1357 + " interface {}", nextHop.getIpAddress(), rd,
1358 nextHop.getAdjacencyType().toString(), interfaceName);
1359 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1360 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1363 String ip = nextHop.getIpAddress().split("/")[0];
1364 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1365 if (vpnVipToPort != null) {
1366 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip);
1367 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed adjacency for Interface {}"
1368 + " ip {} on dpn {} for vpn {} from VpnPortData Entry", vpnVipToPort.getPortName(),
1369 ip, dpnId, vpnName);
1373 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1374 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1375 + " Removing it.", interfaceName, vpnName, dpnId);
1376 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1380 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1381 String interfaceName, BigInteger dpnId,
1382 WriteTransaction writeConfigTxn) {
1384 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1386 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1387 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1388 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1392 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1393 BigInteger dpnId, String rd, String interfaceName,
1394 WriteTransaction writeConfigTxn) {
1395 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1396 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1397 nhList.forEach((nh) -> {
1398 //IRT: remove routes from other vpns importing it
1399 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1400 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1401 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1402 String vpnRd = vpn.getVrfId();
1403 if (vpnRd != null) {
1404 fibManager.removeOrUpdateFibEntry(vpnRd,
1405 nextHop.getIpAddress(), nh, writeConfigTxn);
1406 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1407 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1408 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1409 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1415 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1416 int lportTag, String gwMac, String interfaceName,
1417 WriteTransaction writeInvTxn) {
1418 final Uuid subnetId = nextHop.getSubnetId();
1419 if (nextHop.getSubnetGatewayMacAddress() == null) {
1420 // A valid mac-address was not available for this subnet-gateway-ip
1421 // So a connected-mac-address was used for this subnet and we need
1422 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1423 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1424 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1426 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1430 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1431 String interfaceName) {
1432 // This is either an extra-route (or) a learned IP via subnet-route
1433 List<String> nhList = null;
1434 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1435 if (nextHopIp == null || nextHopIp.isEmpty()) {
1436 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1437 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1438 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1440 nhList = Collections.emptyList();
1442 nhList = Collections.singletonList(nextHopIp);
1447 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1448 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1449 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1450 // else use connected interface
1451 if (gwPort != null && gwPort.isSubnetIp()) {
1452 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1453 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1454 return Optional.of(gwPort.getMacAddress());
1456 return Optional.absent();
1460 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1461 final VpnInterface update) {
1462 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1463 update.getDpnId(), original.getVpnInstanceNames(),
1464 update.getVpnInstanceNames());
1465 final String vpnInterfaceName = update.getName();
1466 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1467 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1468 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1469 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1470 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1471 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1472 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1474 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1475 //handles switching between <internal VPN - external VPN>
1476 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1477 LOG.info("update: handled VPNInterface {} on dpn {} update"
1478 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1479 original.getName(), dpnId,
1480 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1481 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1484 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1485 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1486 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1487 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1488 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1489 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1490 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1491 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1492 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1493 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1494 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1495 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1496 update.getName(), newVpnName);
1497 //handle both addition and removal of adjacencies
1498 //currently, new adjacency may be an extra route
1499 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1500 if (!oldAdjs.equals(newAdjs)) {
1501 for (Adjacency adj : copyNewAdjs) {
1502 if (copyOldAdjs.contains(adj)) {
1503 copyOldAdjs.remove(adj);
1505 // add new adjacency - right now only extra route will hit this path
1506 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1507 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1508 dpnId, writeOperTxn, writeConfigTxn);
1510 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to vpn "
1511 + "interface {} on vpn {} dpnId {}",
1512 adj.getIpAddress(), adj.getNextHopIpList(),
1513 adj.getLabel(), adj.getSubnetId(), update.getName(),
1517 for (Adjacency adj : copyOldAdjs) {
1518 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1519 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1520 writeOperTxn, writeConfigTxn);
1522 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1523 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj.getNextHopIpList(),
1524 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1527 ListenableFuture<Void> operFuture = writeOperTxn.submit();
1530 } catch (ExecutionException e) {
1531 LOG.error("Exception encountered while submitting operational future for update"
1532 + " VpnInterface {} on vpn {}", vpnInterfaceName, newVpnName, e);
1535 List<ListenableFuture<Void>> futures = new ArrayList<>();
1536 futures.add(writeConfigTxn.submit());
1537 LOG.info("update: vpn interface updated for interface {} oldVpn(s) {} newVpn {}"
1538 + "processed successfully", update.getName(),
1539 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()), newVpnName);
1543 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1544 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1549 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1550 VpnInterface original, VpnInterface update) {
1551 boolean isSwap = Boolean.FALSE;
1552 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1553 final String interfaceName = key.getName();
1554 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1555 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1556 List<String> oldVpnListCopy = new ArrayList<>();
1557 oldVpnListCopy.addAll(oldVpnList);
1558 List<String> newVpnList = update.getVpnInstanceNames().stream()
1559 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1560 oldVpnList.removeAll(newVpnList);
1561 newVpnList.removeAll(oldVpnListCopy);
1562 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1563 for (String oldVpnName: oldVpnList) {
1564 isSwap = Boolean.TRUE;
1565 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1566 + " running config-driven swap removal", interfaceName, oldVpnName);
1567 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1568 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1569 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1571 //Wait for previous interface bindings to be removed
1574 } catch (InterruptedException e) {
1577 for (String newVpnName: newVpnList) {
1578 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1579 isSwap = Boolean.TRUE;
1580 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1581 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1582 + "running config-driven swap addition", interfaceName, newVpnName);
1583 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1584 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1585 ? origAdjs.getAdjacency() : new ArrayList<>();
1586 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1587 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1588 ? updateAdjs.getAdjacency() : new ArrayList<>();
1590 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1591 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1592 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1593 interfaceName, oldVpnListCopy, newVpnName);
1600 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1601 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1602 synchronized (label.toString().intern()) {
1603 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1604 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1605 Optional<LabelRouteInfo> opResult = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
1606 if (opResult.isPresent()) {
1607 LabelRouteInfo labelRouteInfo =
1608 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1609 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, labelRouteInfo);
1612 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label, nextHopIpList);
1615 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1616 SubnetRoute route, WriteTransaction writeConfigTxn) {
1618 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1619 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, null /* parentVpnRd */)
1620 .addAugmentation(SubnetRoute.class, route).build();
1621 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1622 InstanceIdentifierBuilder<VrfTables> idBuilder =
1623 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1624 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1625 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1626 if (writeConfigTxn != null) {
1627 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1629 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1631 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1632 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1635 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1636 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1637 WriteTransaction writeConfigTxn) {
1639 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1640 LogicalDatastoreType.OPERATIONAL, identifier);
1642 if (optVpnInterface.isPresent()) {
1643 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1644 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1645 String vpnName = currVpnIntf.getVpnInstanceName();
1646 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1647 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1648 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker,
1649 LogicalDatastoreType.OPERATIONAL, adjPath);
1650 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1651 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1652 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1653 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1654 List<Adjacency> adjacencies;
1655 if (optAdjacencies.isPresent()) {
1656 adjacencies = optAdjacencies.get().getAdjacency();
1658 // This code will be hit in case of first PNF adjacency
1659 adjacencies = new ArrayList<>();
1661 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1662 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1663 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1664 Adjacency operationalAdjacency = null;
1665 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()) {
1666 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1667 : RouteOrigin.STATIC;
1668 String nh = adj.getNextHopIpList().get(0);
1669 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1670 synchronized (vpnPrefixKey.intern()) {
1671 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1672 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1673 if (rdToAllocate.isPresent()) {
1674 input.setRd(rdToAllocate.get());
1675 operationalAdjacency = populator.createOperationalAdjacency(input);
1676 int label = operationalAdjacency.getLabel().intValue();
1677 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1678 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1679 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1680 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1681 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1682 vpnName, label, currVpnIntf.getName(), dpnId);
1684 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}", vpnName,
1688 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1689 // Keeping the MPLS check for now.
1690 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1691 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1692 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1693 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1694 vpnsToImportRoute.forEach(vpn -> {
1695 if (vpn.getVrfId() != null) {
1696 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1697 dataBroker, vpn.getVpnId(), vpnId, prefix,
1698 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1700 rds -> vpnManager.addExtraRoute(
1701 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1702 adj.getIpAddress(), nh, rds,
1703 currVpnIntf.getVpnInstanceName(),
1704 l3vni, RouteOrigin.SELF_IMPORTED,
1705 currVpnIntf.getName(), opAdjacency, encapType, writeConfigTxn));
1710 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1711 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1712 currVpnIntf.getName(), vpnName);
1714 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1717 LogicalDatastoreType.OPERATIONAL,
1718 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1719 adj.getSubnetId().getValue()), prefix),
1720 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1721 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1723 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1724 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */, 0 /*l3vni*/,
1725 null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1727 input.setRd(adj.getVrfId());
1729 if (operationalAdjacency == null) {
1730 operationalAdjacency = populator.createOperationalAdjacency(input);
1732 adjacencies.add(operationalAdjacency);
1733 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1734 VpnInterfaceOpDataEntry newVpnIntf =
1735 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1736 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1737 currVpnIntf.getGatewayMacAddress());
1739 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1743 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1744 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1745 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1748 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1749 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1750 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1751 LogicalDatastoreType.OPERATIONAL, identifier);
1753 if (optVpnInterface.isPresent()) {
1754 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1756 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1757 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1758 if (optAdjacencies.isPresent()) {
1759 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1761 if (!adjacencies.isEmpty()) {
1762 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1763 Iterator<Adjacency> adjIt = adjacencies.iterator();
1764 while (adjIt.hasNext()) {
1765 Adjacency adjElem = adjIt.next();
1766 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1767 String rd = adjElem.getVrfId();
1770 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1771 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1772 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1773 currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove(),
1774 currVpnIntf.getLportTag(), currVpnIntf.getGatewayMacAddress());
1776 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1777 if (adj.getNextHopIpList() != null) {
1778 for (String nh : adj.getNextHopIpList()) {
1779 deleteExtraRouteFromCurrentAndImportingVpns(
1780 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1781 currVpnIntf.getName(), writeConfigTxn);
1783 } else if (adj.isPhysNetworkFunc()) {
1784 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1785 adj.getIpAddress(), adj.getSubnetId());
1786 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1794 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1795 dpnId, adj.getVrfId());
1797 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1798 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1803 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1804 String rd, String intfName, WriteTransaction writeConfigTxn) {
1805 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1806 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1807 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1808 String vpnRd = vpn.getVrfId();
1809 if (vpnRd != null) {
1810 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
1815 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1816 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1817 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1818 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1821 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1822 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1823 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1826 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1827 WriteTransaction writeOperTxn) {
1828 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1829 if (dpId.equals(BigInteger.ZERO)) {
1830 LOG.error("addToNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1831 + " association model", vpnInterfaceName, routerName);
1835 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1837 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1838 .OPERATIONAL, routerDpnListIdentifier);
1839 RouterInterfaces routerInterface =
1840 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1841 vpnInterfaceName).build();
1842 if (optionalRouterDpnList.isPresent()) {
1843 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1844 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1846 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1847 builder.setRouterId(routerName);
1848 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1849 builder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1850 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1851 getRouterId(routerName),
1852 builder.build(), true);
1856 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1857 WriteTransaction writeOperTxn) {
1858 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1859 if (dpId.equals(BigInteger.ZERO)) {
1860 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1861 + " dissociation model", vpnInterfaceName, routerName);
1865 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1866 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1867 .OPERATIONAL, routerDpnListIdentifier);
1868 if (optionalRouterDpnList.isPresent()) {
1869 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1870 RouterInterfaces routerInterface =
1871 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1872 vpnInterfaceName).build();
1874 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1875 if (routerInterfaces.isEmpty()) {
1876 if (writeOperTxn != null) {
1877 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1879 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1882 if (writeOperTxn != null) {
1883 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1884 RouterInterfaces.class,
1885 new RouterInterfacesKey(vpnInterfaceName)));
1887 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL,
1888 routerDpnListIdentifier.child(
1889 RouterInterfaces.class,
1890 new RouterInterfacesKey(vpnInterfaceName)));
1897 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1898 WriteTransaction writeOperTxn) {
1899 if (dpId.equals(BigInteger.ZERO)) {
1900 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1901 + " dissociation model", vpnInterfaceName, routerName);
1905 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1906 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1907 .OPERATIONAL, routerDpnListIdentifier);
1908 if (optionalRouterDpnList.isPresent()) {
1909 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1910 RouterInterfaces routerInterface =
1911 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1912 vpnInterfaceName).build();
1913 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1914 if (routerInterfaces.isEmpty()) {
1915 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1917 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1918 RouterInterfaces.class,
1919 new RouterInterfacesKey(vpnInterfaceName)));
1925 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1926 WriteTransaction writeConfigTxn, String vpnName) {
1927 if (vpnInterface == null) {
1930 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
1932 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1933 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1936 for (Adjacency adj : adjs) {
1937 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1938 String primaryInterfaceIp = adj.getIpAddress();
1939 String macAddress = adj.getMacAddress();
1940 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1942 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1943 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1945 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1946 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1947 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1948 routerInt, label, writeConfigTxn);
1949 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1950 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1955 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1956 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1957 primaryRd, vpnName);
1960 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1961 WriteTransaction writeConfigTxn, String vpnName) {
1962 Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
1963 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1965 List<Adjacency> adjsList = adjs.getAdjacency();
1966 for (Adjacency adj : adjsList) {
1967 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1968 String primaryInterfaceIp = adj.getIpAddress();
1969 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1970 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1971 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1972 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1977 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
1978 vpnInterface.getName(), rd);
1982 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
1983 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
1984 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
1985 vpnName, intefaceData.vpnInterface.getName());
1988 final VpnInterfaceKey key = intefaceData.identifier
1989 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1990 final String interfaceName = key.getName();
1991 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
1992 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1993 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
1994 intefaceData.identifier, vpnName);
1998 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
1999 VpnInterface vpnInterface, String vpnName) {
2000 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
2002 if (vpnInterfaces == null) {
2003 vpnInterfaces = new ConcurrentLinkedQueue<>();
2005 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2006 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2007 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2008 vpnInterface.getName(), vpnName);
2011 public boolean isVpnInstanceReady(String vpnInstanceName) {
2012 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnInstanceName);
2013 if (vpnRd == null) {
2016 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
2018 return vpnInstanceOpDataEntry != null;
2021 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2022 synchronized (vpnInstanceName.intern()) {
2023 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2024 unprocessedVpnInterfaces.get(vpnInstanceName);
2025 if (vpnInterfaces != null) {
2026 while (!vpnInterfaces.isEmpty()) {
2027 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2028 if (hasVpnInstanceCreatedSuccessfully) {
2029 processSavedInterface(savedInterface, vpnInstanceName);
2030 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2031 savedInterface.vpnInterface.getName(), vpnInstanceName);
2033 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2034 savedInterface.vpnInterface.getName(), vpnInstanceName);
2038 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2043 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2044 VpnInterface vpnInterface) {
2045 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2046 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2047 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2048 if (vpnInterfaces != null) {
2049 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2050 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2051 + "unprocessed list", vpnInterface.getName(),
2052 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2055 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2056 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2061 public void vpnInstanceIsReady(String vpnInstanceName) {
2062 processSavedInterfaces(vpnInstanceName, true);
2065 public void vpnInstanceFailed(String vpnInstanceName) {
2066 processSavedInterfaces(vpnInstanceName, false);
2069 private static class UnprocessedVpnInterfaceData {
2070 InstanceIdentifier<VpnInterface> identifier;
2071 VpnInterface vpnInterface;
2073 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2074 this.identifier = identifier;
2075 this.vpnInterface = vpnInterface;
2079 public int hashCode() {
2080 final int prime = 31;
2082 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2083 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2088 public boolean equals(Object obj) {
2095 if (getClass() != obj.getClass()) {
2098 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2099 if (identifier == null) {
2100 if (other.identifier != null) {
2103 } else if (!identifier.equals(other.identifier)) {
2106 if (vpnInterface == null) {
2107 if (other.vpnInterface != null) {
2110 } else if (!vpnInterface.equals(other.vpnInterface)) {
2117 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2118 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
2119 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
2120 if (vpnInstanceOpData == null) {
2123 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2124 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2127 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2128 vpnToDpnLists.forEach(vpnToDpnList -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2129 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2130 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2131 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = VpnUtil.read(dataBroker,
2132 LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2133 if (!vpnInterfaceOptional.isPresent()) {
2136 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2137 vpnInterface.getInterfaceName());
2138 if (configVpnAdjacencies == null) {
2139 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2142 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2143 .getAugmentation(AdjacenciesOp.class).getAdjacency();
2144 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2145 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2146 // in operational DS. These unprocessed adjacencies will be handled below.
2147 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2148 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2149 configVpnAdjacencies.stream()
2150 .filter(adjacency -> operationVpnAdjacencies.stream()
2151 .noneMatch(operationalAdjacency ->
2152 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2153 .forEach(adjacency -> {
2154 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2155 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2157 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
2158 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
2159 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2160 addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd, adjacency,
2161 vpnInterfaceOptional.get().getDpnId(), writeConfigTxn, writeOperTxn);
2162 ListenableFuture<Void> operFuture = writeOperTxn.submit();
2165 } catch (ExecutionException | InterruptedException e) {
2166 LOG.error("Exception encountered while submitting operational"
2167 + " future for vpnInterface {}", vpnInterface, e);
2169 List<ListenableFuture<Void>> futures = new ArrayList<>();
2170 futures.add(writeConfigTxn.submit());
2173 return Collections.emptyList();
2180 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2181 private final String interfaceName;
2182 private final boolean add;
2183 private final String txnDestination;
2185 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2186 this.interfaceName = interfaceName;
2188 this.txnDestination = transactionDest;
2192 public void onSuccess(Void voidObj) {
2194 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2195 interfaceName, txnDestination);
2197 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2202 public void onFailure(Throwable throwable) {
2204 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2205 interfaceName, txnDestination, throwable);
2207 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2208 VpnUtil.unsetScheduledToRemoveForVpnInterface(txRunner, interfaceName);