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()) {
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, vpn.getVrfId(), 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, vpn.getVrfId(),
1160 } catch (RuntimeException e) {
1161 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1162 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1163 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1166 writeConfigTxn.submit();
1168 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1169 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1174 @SuppressWarnings("checkstyle:IllegalCatch")
1176 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1177 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1178 final String interfaceName = key.getName();
1179 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1180 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1181 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1185 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1186 final VpnInterface vpnInterface, final String vpnName,
1187 final String interfaceName) {
1188 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1189 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
1190 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1191 deleteFibEntryForRouterInterface(vpnInterface, writeConfigTxn, vpnName);
1192 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1193 ListenableFuture<Void> futures = writeConfigTxn.submit();
1194 String errorText = "removeVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
1195 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
1196 ListenableFutures.addErrorLogging(futures, LOG, errorText);
1197 return Collections.singletonList(futures);
1198 }, DJC_MAX_RETRIES);
1200 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1201 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1205 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1206 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1207 final VpnInterface vpnInterface, final String vpnName,
1208 final String interfaceName, final Interface interfaceState) {
1209 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1210 vpnName, vpnInterface.getDpnId());
1211 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1212 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1214 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1215 ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1216 writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1217 writeOperTxn -> 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);
1262 futures.add(configFuture);
1263 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1265 }, DJC_MAX_RETRIES);
1268 protected void processVpnInterfaceDown(BigInteger dpId,
1269 String interfaceName,
1272 VpnInterfaceOpDataEntry vpnOpInterface,
1273 boolean isInterfaceStateDown,
1274 WriteTransaction writeConfigTxn,
1275 WriteTransaction writeOperTxn,
1276 WriteTransaction writeInvTxn) {
1277 if (vpnOpInterface == null) {
1278 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1279 + " as it is not available in operational data store", interfaceName, dpId);
1282 final String vpnName = vpnOpInterface.getVpnInstanceName();
1283 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1284 interfaceName, vpnName);
1285 if (!isInterfaceStateDown) {
1286 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1287 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1289 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1290 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1291 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1292 if (interfaceManager.isExternalInterface(interfaceName)) {
1293 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1294 NwConstants.DEL_FLOW);
1296 if (!isBgpVpnInternetVpn) {
1297 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1299 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1300 + " successful", interfaceName, dpId, vpnName);
1302 // Interface is retained in the DPN, but its Link Down.
1303 // Only withdraw the prefixes for this interface from BGP
1304 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1308 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1309 final String vpnName, final long vpnId, String gwMac,
1310 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1311 final WriteTransaction writeInvTxn) {
1313 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1314 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1315 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1316 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1318 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1319 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1320 interfaceName, dpnId, vpnName, primaryRd);
1321 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1322 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1323 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1324 interfaceName, dpnId, vpnName, nextHops);
1325 for (Adjacency nextHop : nextHops) {
1326 if (nextHop.isPhysNetworkFunc()) {
1327 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1328 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1329 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1330 null/*writeCfgTxn*/);
1332 String rd = nextHop.getVrfId();
1333 List<String> nhList;
1334 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1335 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1337 // This is a primary adjacency
1338 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1339 : Collections.emptyList();
1340 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1341 interfaceName, writeInvTxn);
1343 if (!nhList.isEmpty()) {
1344 if (rd.equals(vpnName)) {
1345 //this is an internal vpn - the rd is assigned to the vpn instance name;
1346 //remove from FIB directly
1347 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1348 interfaceName, dpnId, writeConfigTxn));
1350 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd, interfaceName,
1354 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1355 + " interface {}", nextHop.getIpAddress(), rd,
1356 nextHop.getAdjacencyType().toString(), interfaceName);
1357 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1358 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1361 String ip = nextHop.getIpAddress().split("/")[0];
1362 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1363 if (vpnVipToPort != null) {
1364 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip);
1365 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed adjacency for Interface {}"
1366 + " ip {} on dpn {} for vpn {} from VpnPortData Entry", vpnVipToPort.getPortName(),
1367 ip, dpnId, vpnName);
1371 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1372 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1373 + " Removing it.", interfaceName, vpnName, dpnId);
1374 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1378 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1379 String interfaceName, BigInteger dpnId,
1380 WriteTransaction writeConfigTxn) {
1382 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1384 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1385 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1386 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1390 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1391 BigInteger dpnId, String rd, String interfaceName,
1392 WriteTransaction writeConfigTxn) {
1393 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1394 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1395 nhList.forEach((nh) -> {
1396 //IRT: remove routes from other vpns importing it
1397 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1398 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1399 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1400 String vpnRd = vpn.getVrfId();
1401 if (vpnRd != null) {
1402 fibManager.removeOrUpdateFibEntry(vpnRd,
1403 nextHop.getIpAddress(), nh, writeConfigTxn);
1404 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1405 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1406 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1407 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1413 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1414 int lportTag, String gwMac, String interfaceName,
1415 WriteTransaction writeInvTxn) {
1416 final Uuid subnetId = nextHop.getSubnetId();
1417 if (nextHop.getSubnetGatewayMacAddress() == null) {
1418 // A valid mac-address was not available for this subnet-gateway-ip
1419 // So a connected-mac-address was used for this subnet and we need
1420 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1421 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1422 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1424 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1428 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1429 String interfaceName) {
1430 // This is either an extra-route (or) a learned IP via subnet-route
1431 List<String> nhList = null;
1432 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1433 if (nextHopIp == null || nextHopIp.isEmpty()) {
1434 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1435 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1436 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1438 nhList = Collections.emptyList();
1440 nhList = Collections.singletonList(nextHopIp);
1445 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1446 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1447 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1448 // else use connected interface
1449 if (gwPort != null && gwPort.isSubnetIp()) {
1450 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1451 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1452 return Optional.of(gwPort.getMacAddress());
1454 return Optional.absent();
1458 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1459 final VpnInterface update) {
1460 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1461 update.getDpnId(), original.getVpnInstanceNames(),
1462 update.getVpnInstanceNames());
1463 final String vpnInterfaceName = update.getName();
1464 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1465 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1466 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1467 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1468 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1469 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1470 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1472 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1473 //handles switching between <internal VPN - external VPN>
1474 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1475 LOG.info("update: handled VPNInterface {} on dpn {} update"
1476 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1477 original.getName(), dpnId,
1478 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1479 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1482 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1483 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1484 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1485 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1486 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1487 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1488 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1489 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1490 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1491 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1492 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1493 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1494 update.getName(), newVpnName);
1495 //handle both addition and removal of adjacencies
1496 //currently, new adjacency may be an extra route
1497 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1498 if (!oldAdjs.equals(newAdjs)) {
1499 for (Adjacency adj : copyNewAdjs) {
1500 if (copyOldAdjs.contains(adj)) {
1501 copyOldAdjs.remove(adj);
1503 // add new adjacency - right now only extra route will hit this path
1504 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1505 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1506 dpnId, writeOperTxn, writeConfigTxn);
1508 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to vpn "
1509 + "interface {} on vpn {} dpnId {}",
1510 adj.getIpAddress(), adj.getNextHopIpList(),
1511 adj.getLabel(), adj.getSubnetId(), update.getName(),
1515 for (Adjacency adj : copyOldAdjs) {
1516 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1517 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1518 writeOperTxn, writeConfigTxn);
1520 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1521 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj.getNextHopIpList(),
1522 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1525 ListenableFuture<Void> operFuture = writeOperTxn.submit();
1528 } catch (ExecutionException e) {
1529 LOG.error("Exception encountered while submitting operational future for update"
1530 + " VpnInterface {} on vpn {}", vpnInterfaceName, newVpnName, e);
1533 List<ListenableFuture<Void>> futures = new ArrayList<>();
1534 futures.add(writeConfigTxn.submit());
1535 LOG.info("update: vpn interface updated for interface {} oldVpn(s) {} newVpn {}"
1536 + "processed successfully", update.getName(),
1537 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()), newVpnName);
1541 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1542 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1547 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1548 VpnInterface original, VpnInterface update) {
1549 boolean isSwap = Boolean.FALSE;
1550 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1551 final String interfaceName = key.getName();
1552 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1553 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1554 List<String> oldVpnListCopy = new ArrayList<>();
1555 oldVpnListCopy.addAll(oldVpnList);
1556 List<String> newVpnList = update.getVpnInstanceNames().stream()
1557 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1558 oldVpnList.removeAll(newVpnList);
1559 newVpnList.removeAll(oldVpnListCopy);
1560 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1561 for (String oldVpnName: oldVpnList) {
1562 isSwap = Boolean.TRUE;
1563 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1564 + " running config-driven swap removal", interfaceName, oldVpnName);
1565 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1566 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1567 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1569 //Wait for previous interface bindings to be removed
1572 } catch (InterruptedException e) {
1575 for (String newVpnName: newVpnList) {
1576 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1577 isSwap = Boolean.TRUE;
1578 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1579 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1580 + "running config-driven swap addition", interfaceName, newVpnName);
1581 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1582 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1583 ? origAdjs.getAdjacency() : new ArrayList<>();
1584 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1585 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1586 ? updateAdjs.getAdjacency() : new ArrayList<>();
1588 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1589 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1590 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1591 interfaceName, oldVpnListCopy, newVpnName);
1598 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1599 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1600 synchronized (label.toString().intern()) {
1601 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1602 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1603 Optional<LabelRouteInfo> opResult = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
1604 if (opResult.isPresent()) {
1605 LabelRouteInfo labelRouteInfo =
1606 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1607 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, labelRouteInfo);
1610 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label, nextHopIpList);
1613 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1614 SubnetRoute route, String parentVpnRd, WriteTransaction writeConfigTxn) {
1616 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1617 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, parentVpnRd)
1618 .addAugmentation(SubnetRoute.class, route).build();
1619 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1620 InstanceIdentifierBuilder<VrfTables> idBuilder =
1621 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1622 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1623 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1624 if (writeConfigTxn != null) {
1625 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1627 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1629 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1630 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1633 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1634 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1635 WriteTransaction writeConfigTxn) {
1637 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1638 LogicalDatastoreType.OPERATIONAL, identifier);
1640 if (optVpnInterface.isPresent()) {
1641 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1642 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1643 String vpnName = currVpnIntf.getVpnInstanceName();
1644 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1645 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1646 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker,
1647 LogicalDatastoreType.OPERATIONAL, adjPath);
1648 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1649 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1650 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1651 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1652 List<Adjacency> adjacencies;
1653 if (optAdjacencies.isPresent()) {
1654 adjacencies = optAdjacencies.get().getAdjacency();
1656 // This code will be hit in case of first PNF adjacency
1657 adjacencies = new ArrayList<>();
1659 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1660 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1661 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1662 Adjacency operationalAdjacency = null;
1663 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()) {
1664 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1665 : RouteOrigin.STATIC;
1666 String nh = adj.getNextHopIpList().get(0);
1667 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1668 synchronized (vpnPrefixKey.intern()) {
1669 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1670 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1671 if (rdToAllocate.isPresent()) {
1672 input.setRd(rdToAllocate.get());
1673 operationalAdjacency = populator.createOperationalAdjacency(input);
1674 int label = operationalAdjacency.getLabel().intValue();
1675 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1676 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1677 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1678 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1679 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1680 vpnName, label, currVpnIntf.getName(), dpnId);
1682 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}", vpnName,
1686 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1687 // Keeping the MPLS check for now.
1688 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1689 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1690 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1691 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1692 vpnsToImportRoute.forEach(vpn -> {
1693 if (vpn.getVrfId() != null) {
1694 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1695 dataBroker, vpn.getVpnId(), vpnId, prefix,
1696 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1698 rds -> vpnManager.addExtraRoute(
1699 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1700 adj.getIpAddress(), nh, rds,
1701 currVpnIntf.getVpnInstanceName(),
1702 l3vni, RouteOrigin.SELF_IMPORTED,
1703 currVpnIntf.getName(), opAdjacency, encapType, writeConfigTxn));
1708 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1709 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1710 currVpnIntf.getName(), vpnName);
1712 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1715 LogicalDatastoreType.OPERATIONAL,
1716 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1717 adj.getSubnetId().getValue()), prefix),
1718 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1719 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1721 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1722 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */, 0 /*l3vni*/,
1723 null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1725 input.setRd(adj.getVrfId());
1727 if (operationalAdjacency == null) {
1728 operationalAdjacency = populator.createOperationalAdjacency(input);
1730 adjacencies.add(operationalAdjacency);
1731 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1732 VpnInterfaceOpDataEntry newVpnIntf =
1733 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1734 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1735 currVpnIntf.getGatewayMacAddress());
1737 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1741 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1742 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1743 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1746 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1747 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1748 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1749 LogicalDatastoreType.OPERATIONAL, identifier);
1751 if (optVpnInterface.isPresent()) {
1752 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1754 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1755 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1756 if (optAdjacencies.isPresent()) {
1757 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1759 if (!adjacencies.isEmpty()) {
1760 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1761 Iterator<Adjacency> adjIt = adjacencies.iterator();
1762 while (adjIt.hasNext()) {
1763 Adjacency adjElem = adjIt.next();
1764 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1765 String rd = adjElem.getVrfId();
1768 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1769 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1770 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1771 currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove(),
1772 currVpnIntf.getLportTag(), currVpnIntf.getGatewayMacAddress());
1774 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1775 if (adj.getNextHopIpList() != null) {
1776 for (String nh : adj.getNextHopIpList()) {
1777 deleteExtraRouteFromCurrentAndImportingVpns(
1778 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1779 currVpnIntf.getName(), writeConfigTxn);
1781 } else if (adj.isPhysNetworkFunc()) {
1782 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1783 adj.getIpAddress(), adj.getSubnetId());
1784 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1792 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1793 dpnId, adj.getVrfId());
1795 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1796 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1801 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1802 String rd, String intfName, WriteTransaction writeConfigTxn) {
1803 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1804 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1805 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1806 String vpnRd = vpn.getVrfId();
1807 if (vpnRd != null) {
1808 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
1813 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1814 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1815 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1816 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1819 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1820 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1821 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1824 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1825 WriteTransaction writeOperTxn) {
1826 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1827 if (dpId.equals(BigInteger.ZERO)) {
1828 LOG.error("addToNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1829 + " association model", vpnInterfaceName, routerName);
1833 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1835 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1836 .OPERATIONAL, routerDpnListIdentifier);
1837 RouterInterfaces routerInterface =
1838 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1839 vpnInterfaceName).build();
1840 if (optionalRouterDpnList.isPresent()) {
1841 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1842 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1844 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1845 builder.setRouterId(routerName);
1846 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1847 builder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1848 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1849 getRouterId(routerName),
1850 builder.build(), true);
1854 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1855 WriteTransaction writeOperTxn) {
1856 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1857 if (dpId.equals(BigInteger.ZERO)) {
1858 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1859 + " dissociation model", vpnInterfaceName, routerName);
1863 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1864 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1865 .OPERATIONAL, routerDpnListIdentifier);
1866 if (optionalRouterDpnList.isPresent()) {
1867 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1868 RouterInterfaces routerInterface =
1869 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1870 vpnInterfaceName).build();
1872 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1873 if (routerInterfaces.isEmpty()) {
1874 if (writeOperTxn != null) {
1875 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1877 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1880 if (writeOperTxn != null) {
1881 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1882 RouterInterfaces.class,
1883 new RouterInterfacesKey(vpnInterfaceName)));
1885 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL,
1886 routerDpnListIdentifier.child(
1887 RouterInterfaces.class,
1888 new RouterInterfacesKey(vpnInterfaceName)));
1895 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1896 WriteTransaction writeOperTxn) {
1897 if (dpId.equals(BigInteger.ZERO)) {
1898 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1899 + " dissociation model", vpnInterfaceName, routerName);
1903 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1904 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1905 .OPERATIONAL, routerDpnListIdentifier);
1906 if (optionalRouterDpnList.isPresent()) {
1907 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1908 RouterInterfaces routerInterface =
1909 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1910 vpnInterfaceName).build();
1911 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1912 if (routerInterfaces.isEmpty()) {
1913 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1915 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1916 RouterInterfaces.class,
1917 new RouterInterfacesKey(vpnInterfaceName)));
1923 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1924 WriteTransaction writeConfigTxn, String vpnName) {
1925 if (vpnInterface == null) {
1928 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
1930 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1931 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1934 for (Adjacency adj : adjs) {
1935 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1936 String primaryInterfaceIp = adj.getIpAddress();
1937 String macAddress = adj.getMacAddress();
1938 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1940 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1941 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1943 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1944 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1945 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1946 routerInt, label, writeConfigTxn);
1947 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1948 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1953 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1954 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1955 primaryRd, vpnName);
1958 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1959 WriteTransaction writeConfigTxn, String vpnName) {
1960 Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
1961 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1963 List<Adjacency> adjsList = adjs.getAdjacency();
1964 for (Adjacency adj : adjsList) {
1965 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1966 String primaryInterfaceIp = adj.getIpAddress();
1967 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1968 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1969 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1970 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1975 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
1976 vpnInterface.getName(), rd);
1980 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
1981 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
1982 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
1983 vpnName, intefaceData.vpnInterface.getName());
1986 final VpnInterfaceKey key = intefaceData.identifier
1987 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1988 final String interfaceName = key.getName();
1989 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
1990 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1991 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
1992 intefaceData.identifier, vpnName);
1996 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
1997 VpnInterface vpnInterface, String vpnName) {
1998 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
2000 if (vpnInterfaces == null) {
2001 vpnInterfaces = new ConcurrentLinkedQueue<>();
2003 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2004 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2005 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2006 vpnInterface.getName(), vpnName);
2009 public boolean isVpnInstanceReady(String vpnInstanceName) {
2010 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnInstanceName);
2011 if (vpnRd == null) {
2014 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
2016 return vpnInstanceOpDataEntry != null;
2019 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2020 synchronized (vpnInstanceName.intern()) {
2021 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2022 unprocessedVpnInterfaces.get(vpnInstanceName);
2023 if (vpnInterfaces != null) {
2024 while (!vpnInterfaces.isEmpty()) {
2025 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2026 if (hasVpnInstanceCreatedSuccessfully) {
2027 processSavedInterface(savedInterface, vpnInstanceName);
2028 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2029 savedInterface.vpnInterface.getName(), vpnInstanceName);
2031 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2032 savedInterface.vpnInterface.getName(), vpnInstanceName);
2036 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2041 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2042 VpnInterface vpnInterface) {
2043 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2044 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2045 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2046 if (vpnInterfaces != null) {
2047 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2048 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2049 + "unprocessed list", vpnInterface.getName(),
2050 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2053 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2054 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2059 public void vpnInstanceIsReady(String vpnInstanceName) {
2060 processSavedInterfaces(vpnInstanceName, true);
2063 public void vpnInstanceFailed(String vpnInstanceName) {
2064 processSavedInterfaces(vpnInstanceName, false);
2067 private static class UnprocessedVpnInterfaceData {
2068 InstanceIdentifier<VpnInterface> identifier;
2069 VpnInterface vpnInterface;
2071 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2072 this.identifier = identifier;
2073 this.vpnInterface = vpnInterface;
2077 public int hashCode() {
2078 final int prime = 31;
2080 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2081 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2086 public boolean equals(Object obj) {
2093 if (getClass() != obj.getClass()) {
2096 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2097 if (identifier == null) {
2098 if (other.identifier != null) {
2101 } else if (!identifier.equals(other.identifier)) {
2104 if (vpnInterface == null) {
2105 if (other.vpnInterface != null) {
2108 } else if (!vpnInterface.equals(other.vpnInterface)) {
2115 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2116 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
2117 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
2118 if (vpnInstanceOpData == null) {
2121 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2122 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2125 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2126 vpnToDpnLists.forEach(vpnToDpnList -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2127 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2128 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2129 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = VpnUtil.read(dataBroker,
2130 LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2131 if (!vpnInterfaceOptional.isPresent()) {
2134 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2135 vpnInterface.getInterfaceName());
2136 if (configVpnAdjacencies == null) {
2137 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2140 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2141 .getAugmentation(AdjacenciesOp.class).getAdjacency();
2142 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2143 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2144 // in operational DS. These unprocessed adjacencies will be handled below.
2145 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2146 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2147 configVpnAdjacencies.stream()
2148 .filter(adjacency -> operationVpnAdjacencies.stream()
2149 .noneMatch(operationalAdjacency ->
2150 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2151 .forEach(adjacency -> {
2152 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2153 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2155 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
2156 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
2157 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2158 addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd, adjacency,
2159 vpnInterfaceOptional.get().getDpnId(), writeConfigTxn, writeOperTxn);
2160 ListenableFuture<Void> operFuture = writeOperTxn.submit();
2163 } catch (ExecutionException | InterruptedException e) {
2164 LOG.error("Exception encountered while submitting operational"
2165 + " future for vpnInterface {}", vpnInterface, e);
2167 List<ListenableFuture<Void>> futures = new ArrayList<>();
2168 futures.add(writeConfigTxn.submit());
2171 return Collections.emptyList();
2178 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2179 private final String interfaceName;
2180 private final boolean add;
2181 private final String txnDestination;
2183 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2184 this.interfaceName = interfaceName;
2186 this.txnDestination = transactionDest;
2190 public void onSuccess(Void voidObj) {
2192 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2193 interfaceName, txnDestination);
2195 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2200 public void onFailure(Throwable throwable) {
2202 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2203 interfaceName, txnDestination, throwable);
2205 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2206 VpnUtil.unsetScheduledToRemoveForVpnInterface(txRunner, interfaceName);