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;
35 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
36 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
37 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
38 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
39 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
40 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
41 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
42 import org.opendaylight.genius.mdsalutil.MDSALUtil;
43 import org.opendaylight.genius.mdsalutil.NWUtil;
44 import org.opendaylight.genius.mdsalutil.NwConstants;
45 import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
46 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
47 import org.opendaylight.infrautils.caches.CacheProvider;
48 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
49 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
50 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
51 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
52 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
53 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
54 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
55 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
56 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
57 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderHandler;
58 import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput;
59 import org.opendaylight.netvirt.vpnmanager.populator.intfc.VpnPopulator;
60 import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
110 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
111 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
112 import org.slf4j.Logger;
113 import org.slf4j.LoggerFactory;
116 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager> {
118 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
119 private static final short DJC_MAX_RETRIES = 3;
121 private final DataBroker dataBroker;
122 private final ManagedNewTransactionRunner txRunner;
123 private final IBgpManager bgpManager;
124 private final IFibManager fibManager;
125 private final IMdsalApiManager mdsalManager;
126 private final IdManagerService idManager;
127 private final OdlInterfaceRpcService ifaceMgrRpcService;
128 private final VpnFootprintService vpnFootprintService;
129 private final IInterfaceManager interfaceManager;
130 private final IVpnManager vpnManager;
131 private final ArpResponderHandler arpResponderHandler;
132 private final JobCoordinator jobCoordinator;
134 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
136 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
137 new ConcurrentHashMap<>();
139 private final DataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
142 public VpnInterfaceManager(final DataBroker dataBroker,
143 final IBgpManager bgpManager,
144 final IdManagerService idManager,
145 final IMdsalApiManager mdsalManager,
146 final IFibManager fibManager,
147 final OdlInterfaceRpcService ifaceMgrRpcService,
148 final VpnFootprintService vpnFootprintService,
149 final IInterfaceManager interfaceManager,
150 final IVpnManager vpnManager,
151 final ArpResponderHandler arpResponderHandler,
152 final JobCoordinator jobCoordinator,
153 final CacheProvider cacheProvider) {
154 super(VpnInterface.class, VpnInterfaceManager.class);
156 this.dataBroker = dataBroker;
157 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
158 this.bgpManager = bgpManager;
159 this.idManager = idManager;
160 this.mdsalManager = mdsalManager;
161 this.fibManager = fibManager;
162 this.ifaceMgrRpcService = ifaceMgrRpcService;
163 this.vpnFootprintService = vpnFootprintService;
164 this.interfaceManager = interfaceManager;
165 this.vpnManager = vpnManager;
166 this.arpResponderHandler = arpResponderHandler;
167 this.jobCoordinator = jobCoordinator;
169 vpnInstanceOpDataEntryCache = new DataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
170 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
171 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
174 public Runnable isNotifyTaskQueued(String intfName) {
175 return vpnIntfMap.remove(intfName);
179 public void start() {
180 LOG.info("{} start", getClass().getSimpleName());
181 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
186 public void close() {
188 vpnInstanceOpDataEntryCache.close();
192 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
193 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
197 protected VpnInterfaceManager getDataTreeChangeListener() {
198 return VpnInterfaceManager.this;
202 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
203 LOG.info("add: intfName {} onto vpnName {}",
204 vpnInterface.getName(),
205 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
206 addVpnInterface(identifier, vpnInterface, null, null);
209 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
210 final VpnInterface vpnInterface, String vpnName) {
211 synchronized (vpnName.intern()) {
212 if (isVpnInstanceReady(vpnName)) {
215 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
220 // TODO Clean up the exception handling
221 @SuppressWarnings("checkstyle:IllegalCatch")
222 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
223 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
224 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
225 String vpnName = vpnInterfaceVpnInstance.getVpnName();
226 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
230 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
231 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
232 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
233 final String interfaceName = key.getName();
235 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
236 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
237 vpnName, vpnInterface.getName());
240 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
241 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
242 List<Adjacency> copyOldAdjs = null;
243 if (oldAdjs != null) {
244 copyOldAdjs = new ArrayList<>();
245 copyOldAdjs.addAll(oldAdjs);
247 List<Adjacency> copyNewAdjs = null;
248 if (newAdjs != null) {
249 copyNewAdjs = new ArrayList<>();
250 copyNewAdjs.addAll(newAdjs);
252 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
255 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
256 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
257 final List<Adjacency> newAdjs,
258 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
259 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
260 final String interfaceName = key.getName();
261 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
262 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
263 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
264 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
265 if (interfaceState != null) {
267 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
268 final int ifIndex = interfaceState.getIfIndex();
269 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName, () -> {
270 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
271 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
272 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
273 LOG.info("addVpnInterface: VPN Interface add event - intfName {} vpnName {} on dpn {}" ,
274 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
275 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false, writeConfigTxn,
276 writeOperTxn, writeInvTxn, interfaceState, vpnName);
277 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
278 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
279 + " Update for swapping VPN {} case.", interfaceName, vpnName);
280 if (newAdjs != null) {
281 for (Adjacency adj : newAdjs) {
282 if (oldAdjs.contains(adj)) {
285 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
287 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd,
288 adj, dpnId, writeOperTxn, writeConfigTxn);
293 for (Adjacency adj : oldAdjs) {
294 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
296 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
297 writeOperTxn, writeConfigTxn);
301 ListenableFuture<Void> operFuture = writeOperTxn.submit();
304 } catch (ExecutionException e) {
305 LOG.error("addVpnInterface: Exception encountered while submitting operational future for"
306 + " addVpnInterface {} on vpn {}: {}", vpnInterface.getName(), vpnName, e);
309 List<ListenableFuture<Void>> futures = new ArrayList<>();
310 ListenableFuture<Void> configFuture = writeConfigTxn.submit();
311 futures.add(configFuture);
312 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"));
313 futures.add(writeInvTxn.submit());
314 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
315 + " processed successfully", interfaceName, vpnName, dpnId);
318 } catch (NumberFormatException | IllegalStateException e) {
319 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
320 + "interface {}. Interface addition on vpn {} failed", interfaceName,
324 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
325 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(),
327 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
328 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
329 writeConfigTxn, vpnName);
330 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
331 vpnName, vpnInterface.getDpnId());
332 ListenableFuture<Void> futures = writeConfigTxn.submit();
333 String errorText = "addVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
334 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
335 ListenableFutures.addErrorLogging(futures, LOG, errorText);
336 return Collections.singletonList(futures);
339 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
340 + " is not available", interfaceName, vpnName);
343 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
344 + " as vpn is pending delete", interfaceName, vpnName,
345 vpnInterface.getDpnId());
349 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
350 // see comments below.
351 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
352 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
353 final int lportTag, boolean isInterfaceUp,
354 WriteTransaction writeConfigTxn,
355 WriteTransaction writeOperTxn,
356 WriteTransaction writeInvTxn,
357 Interface interfaceState,
358 final String vpnName) {
359 final String interfaceName = vpnInterface.getName();
360 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
361 interfaceName, vpnName);
362 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
363 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
364 if (!isInterfaceUp) {
365 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
366 interfaceName, dpId, vpnName);
367 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
368 if (vpnId == VpnConstants.INVALID_ID) {
369 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
370 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
375 boolean waitForVpnInterfaceOpRemoval = false;
376 if (opVpnInterface != null && !opVpnInterface.isScheduledForRemove()) {
377 String opVpnName = opVpnInterface.getVpnInstanceName();
378 String primaryInterfaceIp = null;
379 if (opVpnName.equals(vpnName)) {
380 // Please check if the primary VRF Entry does not exist for VPNInterface
381 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
383 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
384 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
386 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
387 + " for this vpn interface could not be obtained", interfaceName, dpId,
391 for (Adjacency adj : adjs) {
392 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
393 primaryInterfaceIp = adj.getIpAddress();
397 if (primaryInterfaceIp == null) {
398 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
399 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
403 // Get the rd of the vpn instance
404 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, primaryRd, primaryInterfaceIp);
406 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
407 + " bailing out from here.", interfaceName, dpId, vpnName);
410 waitForVpnInterfaceOpRemoval = true;
412 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
413 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
416 if (!waitForVpnInterfaceOpRemoval) {
417 // Add the VPNInterface and quit
418 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
419 null/*ipAddressSourceValuePair*/,
421 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
422 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
423 if (!isBgpVpnInternetVpn) {
424 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false /*isTunnelInterface*/,
427 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
429 if (interfaceManager.isExternalInterface(interfaceName)) {
430 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
431 NwConstants.ADD_FLOW);
436 // FIB didn't get a chance yet to clean up this VPNInterface
437 // Let us give it a chance here !
438 LOG.info("processVpnInterfaceUp: Trying to add VPN Interface {} on dpn {} for vpn {},"
439 + " but waiting for FIB to clean up! ", interfaceName, dpId, vpnName);
441 Runnable notifyTask = new VpnNotifyTask();
442 synchronized (notifyTask) {
443 // Per FB's "Unconditional wait" violation, the code should really verify that the condition it
444 // intends to wait for is not already satisfied before calling wait. However the VpnNotifyTask is
445 // published here while holding the lock on it so this path will hit the wait before notify can be
447 vpnIntfMap.put(interfaceName, notifyTask);
449 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
450 } catch (InterruptedException e) {
455 vpnIntfMap.remove(interfaceName);
458 if (opVpnInterface != null) {
459 LOG.warn("processVpnInterfaceUp: VPN Interface {} removal on dpn {} for vpn {}"
460 + " by FIB did not complete on time," + " bailing addition ...", interfaceName,
462 VpnUtil.unsetScheduledToRemoveForVpnInterface(dataBroker, interfaceName);
465 // VPNInterface got removed, proceed with Add
466 LOG.info("processVpnInterfaceUp: Continuing to plumb vpn interface {} onto dpn {} for vpn {}",
467 interfaceName, dpId, vpnName);
468 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
469 null/*ipAddressSourceValuePair*/,
471 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
472 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
473 if (!isBgpVpnInternetVpn) {
474 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false/*isTunnelInterface*/, jobCoordinator);
476 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
477 + " FIB to clean up", interfaceName, dpId, vpnName);
478 if (interfaceManager.isExternalInterface(interfaceName)) {
479 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId,
480 lportTag, writeInvTxn, NwConstants.ADD_FLOW);
483 // Interface is retained in the DPN, but its Link Up.
484 // Advertise prefixes again for this interface to BGP
485 InstanceIdentifier<VpnInterface> identifier =
486 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName());
487 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
488 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
489 advertiseAdjacenciesForVpnToBgp(primaryRd, dpId, vpnInterfaceOpIdentifier, vpnName, interfaceName);
490 // Perform similar operation as interface add event for extraroutes.
491 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
492 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
493 if (!optAdjacencies.isPresent()) {
494 LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
497 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
498 for (Adjacency adjacency : adjacencies) {
499 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
502 // if BGPVPN Internet, filter only IPv6 Adjacencies
503 if (isBgpVpnInternetVpn && !VpnUtil.isAdjacencyEligibleToVpnInternet(
504 dataBroker, adjacency)) {
507 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
508 dpId, writeOperTxn, writeConfigTxn);
513 private void processExternalVpnInterface(String interfaceName, String vpnName, long vpnId, BigInteger dpId,
514 int lportTag, WriteTransaction writeInvTxn, int addOrRemove) {
517 // vpn instance of ext-net interface is the network-id
518 extNetworkId = new Uuid(vpnName);
519 } catch (IllegalArgumentException e) {
520 LOG.error("processExternalVpnInterface: VPN instance {} is not Uuid. Processing external vpn interface {}"
521 + " on dpn {} failed", vpnName, interfaceName, dpId);
525 List<Uuid> routerIds = VpnUtil.getExternalNetworkRouterIds(dataBroker, extNetworkId);
526 if (routerIds == null || routerIds.isEmpty()) {
527 LOG.info("processExternalVpnInterface: No router is associated with {}."
528 + " Bailing out of processing external vpn interface {} on dpn {} for vpn {}",
529 extNetworkId.getValue(), interfaceName, dpId, vpnName);
533 LOG.info("processExternalVpnInterface: Router-ids {} associated with exernal vpn-interface {} on dpn {}"
534 + " for vpn {}", routerIds, interfaceName, dpId, vpnName);
535 for (Uuid routerId : routerIds) {
536 String routerName = routerId.getValue();
537 BigInteger primarySwitch = VpnUtil.getPrimarySwitchForRouter(dataBroker, routerName);
538 if (Objects.equals(primarySwitch, dpId)) {
539 Routers router = VpnUtil.getExternalRouter(dataBroker, routerName);
540 if (router != null) {
541 if (addOrRemove == NwConstants.ADD_FLOW) {
542 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
543 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
544 dpId, interfaceName, lportTag, writeInvTxn);
546 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
547 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
548 dpId, interfaceName, lportTag);
551 LOG.error("processExternalVpnInterface: No external-router found for router-id {}. Bailing out of"
552 + " processing external vpn-interface {} on dpn {} for vpn {}", routerName,
553 interfaceName, dpId, vpnName);
559 // TODO Clean up the exception handling
560 @SuppressWarnings("checkstyle:IllegalCatch")
561 private void advertiseAdjacenciesForVpnToBgp(final String rd, BigInteger dpnId,
562 final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
563 String vpnName, String interfaceName) {
565 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} on dpn {} in vpn {}",
566 interfaceName, dpnId, vpnName);
569 if (rd.equals(vpnName)) {
570 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} on dpn {}"
571 + " as it is in internal vpn{} with rd {}", interfaceName, dpnId, vpnName, rd);
575 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} on dpn {} in vpn {} with rd {} ",
576 interfaceName, dpnId, vpnName, rd);
578 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
579 if (nextHopIp == null) {
580 LOG.error("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} on dpn {} is null,"
581 + " returning from advertising route with rd {} vpn {} to bgp", interfaceName, dpnId,
587 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
588 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
589 if (adjacencies.isPresent()) {
590 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
592 if (!nextHops.isEmpty()) {
593 LOG.debug("advertiseAdjacenciesForVpnToBgp: NextHops are {} for interface {} on dpn {} for vpn {}"
594 + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
595 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
596 long l3vni = vpnInstanceOpData.getL3vni();
597 VrfEntry.EncapType encapType = VpnUtil.isL3VpnOverVxLan(l3vni)
598 ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
599 for (Adjacency nextHop : nextHops) {
600 if (nextHop.getAdjacencyType() == AdjacencyType.ExtraRoute) {
603 String gatewayMac = null;
605 if (VpnUtil.isL3VpnOverVxLan(l3vni)) {
606 final VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
607 vpnInstanceOpData.getVpnInstanceName(), nextHop.getIpAddress());
608 gatewayMac = arpResponderHandler.getGatewayMacAddressForInterface(gwPort, interfaceName).get();
610 label = nextHop.getLabel();
613 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Adding Fib Entry rd {} prefix {}"
614 + " nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
615 bgpManager.advertisePrefix(rd, nextHop.getMacAddress(), nextHop.getIpAddress(), nextHopIp,
616 encapType, (int)label, l3vni, 0 /*l2vni*/,
618 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Added Fib Entry rd {} prefix {}"
619 + " nexthop {} label {} for interface {} on dpn {} for vpn {}", rd,
620 nextHop.getIpAddress(), nextHopIp, label, interfaceName, dpnId, vpnName);
621 } catch (Exception e) {
622 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to advertise prefix {} in vpn {} with rd {}"
623 + " for interface {} on dpn {}", nextHop.getIpAddress(),
624 vpnName, rd, interfaceName, dpnId, e);
631 // TODO Clean up the exception handling
632 @SuppressWarnings("checkstyle:IllegalCatch")
633 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
634 String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
636 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
637 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
639 String rd = VpnUtil.getVpnRd(dataBroker, interfaceName);
641 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
642 interfaceName, vpnName);
645 if (rd.equals(vpnName)) {
647 "withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in "
648 + "internal vpn{} with rd {}", interfaceName, vpnName, rd);
652 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", interfaceName,
654 if (adjacencies.isPresent()) {
655 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
657 if (!nextHops.isEmpty()) {
658 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
659 nextHops, interfaceName, vpnName, rd);
660 for (Adjacency nextHop : nextHops) {
662 if (nextHop.getAdjacencyType() != AdjacencyType.ExtraRoute) {
663 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removing Fib Entry rd {}"
664 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
665 interfaceName, vpnName);
666 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
667 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removed Fib Entry rd {}"
668 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
669 interfaceName, vpnName);
671 // Perform similar operation as interface delete event for extraroutes.
672 String allocatedRd = nextHop.getVrfId();
673 for (String nh : nextHop.getNextHopIpList()) {
674 deleteExtraRouteFromCurrentAndImportingVpns(
675 vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn);
678 } catch (Exception e) {
679 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
680 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
687 @SuppressWarnings("checkstyle:IllegalCatch")
688 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
689 String primaryRd, String interfaceName, final long vpnId,
690 WriteTransaction writeConfigTxn,
691 WriteTransaction writeOperTxn,
692 final WriteTransaction writeInvTxn,
693 Interface interfaceState) {
694 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
696 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
697 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
698 if (!adjacencies.isPresent()) {
699 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
700 null/*gwMac*/, writeOperTxn);
704 // Get the rd of the vpn instance
705 String nextHopIp = null;
707 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
708 } catch (Exception e) {
709 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
710 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
712 List<String> nhList = new ArrayList<>();
713 if (nextHopIp != null) {
714 nhList.add(nextHopIp);
715 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
716 interfaceName, dpnId, vpnName, nhList);
718 Optional<String> gwMac = Optional.absent();
719 String vpnInterfaceSubnetGwMacAddress = null;
720 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
721 Long l3vni = vpnInstanceOpData.getL3vni();
722 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
723 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
724 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
725 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
726 List<Adjacency> value = new ArrayList<>();
727 for (Adjacency nextHop : nextHops) {
728 String rd = primaryRd;
729 String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
730 if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
731 && NWUtil.isIpv4Address(nexthopIpValue)) {
732 String prefix = nextHop.getIpAddress() == null ? "null" :
733 VpnUtil.getIpPrefix(nextHop.getIpAddress());
734 LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
735 + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
738 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
739 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
740 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
741 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
742 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
743 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
745 LogicalDatastoreType.OPERATIONAL,
746 VpnUtil.getPrefixToInterfaceIdentifier(
747 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
748 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
750 final Uuid subnetId = nextHop.getSubnetId();
752 String gatewayIp = nextHop.getSubnetGatewayIp();
753 if (gatewayIp == null) {
754 Optional<String> gatewayIpOptional = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
755 if (gatewayIpOptional.isPresent()) {
756 gatewayIp = gatewayIpOptional.get();
760 if (gatewayIp != null) {
761 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
762 if (gwMac.isPresent()) {
763 // A valid mac-address is available for this subnet-gateway-ip
764 // Use this for programming ARP_RESPONDER table here. And save this
765 // info into vpnInterface operational, so it can used in VrfEntryProcessor
766 // to populate L3_GW_MAC_TABLE there.
767 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
768 gatewayIp, gwMac.get());
769 vpnInterfaceSubnetGwMacAddress = gwMac.get();
771 // A valid mac-address is not available for this subnet-gateway-ip
772 // Use the connected-mac-address to configure ARP_RESPONDER Table.
773 // Save this connected-mac-address as gateway-mac-address for the
774 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
775 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
776 if (gwMac.isPresent()) {
777 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
778 vpnId, writeInvTxn, NwConstants.ADD_FLOW, gwMac.get());
779 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
780 gatewayIp, gwMac.get());
782 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
783 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
785 interfaceName, vpnName, gatewayIp);
789 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
790 + "cannot create ARP responder flow for interface name {}, vpnName {}",
791 subnetId, interfaceName, vpnName);
792 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
794 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
795 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
797 //Extra route adjacency
798 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
799 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
800 synchronized (vpnPrefixKey.intern()) {
801 java.util.Optional<String> rdToAllocate = VpnUtil
802 .allocateRdForExtraRouteAndUpdateUsedRdsMap(dataBroker, vpnId, null,
803 prefix, vpnName, nextHop.getNextHopIpList().get(0), dpnId);
804 if (rdToAllocate.isPresent()) {
805 rd = rdToAllocate.get();
806 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
809 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
813 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
814 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
815 interfaceName, dpnId);
817 // Please note that primary adjacency will use a subnet-gateway-mac-address that
818 // can be different from the gateway-mac-address within the VRFEntry as the
819 // gateway-mac-address is a superset.
820 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
821 : RouteOrigin.STATIC;
822 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
823 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
824 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
825 Adjacency operationalAdjacency = null;
827 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
828 } catch (NullPointerException e) {
829 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
830 input, e.getMessage());
833 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
834 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
835 vpnName, l3vni, origin,
836 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
838 value.add(operationalAdjacency);
841 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
842 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
843 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
845 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
846 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
847 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
849 for (Adjacency nextHop : aug.getAdjacency()) {
850 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
851 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
852 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
853 : RouteOrigin.STATIC;
854 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
855 registeredPopulator.populateFib(input, writeConfigTxn);
860 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
861 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
862 VpnInterfaceOpDataEntry opInterface =
863 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, Boolean.FALSE, lportTag, gwMac);
864 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
865 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
866 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
867 WriteTransaction.CREATE_MISSING_PARENTS);
868 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
869 interfaceName, dpnId, vpnName);
872 // TODO Clean up the exception handling
873 @SuppressWarnings("checkstyle:IllegalCatch")
874 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
875 StateTunnelList stateTunnelList,
876 WriteTransaction writeConfigTxn,
877 WriteTransaction writeOperTxn) {
879 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
880 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
881 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
882 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
883 if (adjList.isEmpty()) {
884 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
885 vpnInterface, srcDpnId);
888 String prefix = null;
890 List<Adjacency> value = new ArrayList<>();
891 boolean isNextHopAddReqd = false;
892 String vpnName = vpnInterface.getVpnInstanceName();
893 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
894 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
895 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
896 vpnInterface.getName(), vpnInterface.getDpnId(),
897 vpnInterface.getVpnInstanceName(), adjList);
898 for (Adjacency adj : adjList) {
899 String rd = adj.getVrfId();
900 rd = rd != null ? rd : vpnName;
901 prefix = adj.getIpAddress();
902 label = adj.getLabel();
903 List<String> nhList = Collections.singletonList(srcTepIp);
904 List<String> nextHopList = adj.getNextHopIpList();
905 // If TEP is added , update the nexthop of primary adjacency.
906 // Secondary adj nexthop is already pointing to primary adj IP address.
907 if (nextHopList != null && !nextHopList.isEmpty() && nextHopList.get(0).equalsIgnoreCase(srcTepIp)) {
908 /* everything right already */
910 isNextHopAddReqd = true;
913 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
914 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
916 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
917 if (!vrfEntryOptional.isPresent()) {
920 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
921 if (!nhList.contains(srcTepIp)) {
922 nhList.add(srcTepIp);
923 isNextHopAddReqd = true;
928 if (isNextHopAddReqd) {
929 updateLabelMapper(label, nhList);
930 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
931 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
932 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
933 // Update the VRF entry with nextHop
934 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
935 label, true, writeConfigTxn);
937 //Get the list of VPN's importing this route(prefix) .
938 // Then update the VRF entry with nhList
939 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
940 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
941 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
942 String vpnRd = vpn.getVrfId();
944 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
945 srcTepIp, label, true, writeConfigTxn);
946 LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
947 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
948 vpnInterface.getName(), srcDpnId, vpnName,
949 vpn.getVpnInstanceName(), vpnRd);
952 // Advertise the prefix to BGP only for external vpn
953 // since there is a nexthop change.
955 if (!rd.equalsIgnoreCase(vpnName)) {
956 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, nhList,
957 VrfEntry.EncapType.Mplsgre, (int)label, 0 /*evi*/, 0 /*l2vni*/,
958 null /*gatewayMacAddress*/);
960 LOG.info("updateVpnInterfaceOnTepAdd: Advertised rd {} prefix {} nhList {} label {}"
961 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label, vpnInterface.getName(),
963 } catch (Exception ex) {
964 LOG.error("updateVpnInterfaceOnTepAdd: Exception when advertising prefix {} nh {} label {}"
965 + " on rd {} for interface {} on dpn {} vpn {} as {}", prefix, nhList, label, rd,
966 vpnInterface.getName(), srcDpnId,
971 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
972 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
973 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
974 .addAugmentation(AdjacenciesOp.class, aug).build();
975 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
976 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
977 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
978 WriteTransaction.CREATE_MISSING_PARENTS);
979 LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
980 vpnInterface.getName(), srcDpnId, vpnName);
984 // TODO Clean up the exception handling
985 @SuppressWarnings("checkstyle:IllegalCatch")
986 public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
987 StateTunnelList stateTunnelList,
988 WriteTransaction writeConfigTxn,
989 WriteTransaction writeOperTxn) {
991 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
992 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
993 String prefix = null;
995 boolean isNextHopRemoveReqd = false;
996 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
997 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
998 String vpnName = vpnInterface.getVpnInstanceName();
999 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1000 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1001 if (adjList != null) {
1002 List<Adjacency> value = new ArrayList<>();
1003 LOG.info("updateVpnInterfaceOnTepDelete: AdjacencyList for interface {} on dpn {} vpn {} is {}",
1004 vpnInterface.getName(), vpnInterface.getDpnId(),
1005 vpnInterface.getVpnInstanceName(), adjList);
1006 for (Adjacency adj : adjList) {
1007 List<String> nhList = new ArrayList<>();
1008 String rd = adj.getVrfId();
1009 rd = rd != null ? rd : vpnName;
1010 prefix = adj.getIpAddress();
1011 List<String> nextHopList = adj.getNextHopIpList();
1012 label = adj.getLabel();
1013 if (nextHopList != null && !nextHopList.isEmpty()) {
1014 isNextHopRemoveReqd = true;
1016 // If TEP is deleted , remove the nexthop from primary adjacency.
1017 // Secondary adj nexthop will continue to point to primary adj IP address.
1018 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1019 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
1021 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
1022 if (!vrfEntryOptional.isPresent()) {
1025 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
1026 if (nhList.contains(srcTepIp)) {
1027 nhList.remove(srcTepIp);
1028 isNextHopRemoveReqd = true;
1033 if (isNextHopRemoveReqd) {
1034 updateLabelMapper(label, nhList);
1035 LOG.info("updateVpnInterfaceOnTepDelete: Updated label mapper : label {} dpn {} prefix {}"
1036 + " nexthoplist {} vpn {} vpnid {} rd {} interface {}", label, srcDpnId,
1037 prefix, nhList, vpnName,
1038 vpnId, rd, vpnInterface.getName());
1039 // Update the VRF entry with removed nextHop
1040 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
1041 label, false, writeConfigTxn);
1043 //Get the list of VPN's importing this route(prefix) .
1044 // Then update the VRF entry with nhList
1045 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1046 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1047 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1048 String vpnRd = vpn.getVrfId();
1049 if (vpnRd != null) {
1050 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1051 srcTepIp, label, false, writeConfigTxn);
1052 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1053 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1054 nhList, label, vpnInterface.getName(), srcDpnId,
1056 vpn.getVpnInstanceName(), vpnRd);
1060 // Withdraw prefix from BGP only for external vpn.
1062 if (!rd.equalsIgnoreCase(vpnName)) {
1063 bgpManager.withdrawPrefix(rd, prefix);
1065 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1066 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1067 vpnInterface.getName(), srcDpnId,
1069 } catch (Exception ex) {
1070 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1071 + " on rd {} for interface {} on dpn {} vpn {} as {}", prefix, nhList, label, rd,
1072 vpnInterface.getName(), srcDpnId,
1077 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1078 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1079 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1080 .addAugmentation(AdjacenciesOp.class, aug).build();
1081 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1082 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1083 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1084 WriteTransaction.CREATE_MISSING_PARENTS);
1085 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1086 vpnInterface.getName(), srcDpnId, vpnName);
1090 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1091 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1093 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1094 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
1095 if (vpnInstanceOpDataEntry == null) {
1096 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1097 + " to check for vpns exporting the routes", vpnName);
1098 return vpnsToExportRoute;
1101 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1102 if (input.getVpnInstanceName() == null) {
1103 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1107 return !input.getVpnInstanceName().equals(vpnName);
1110 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1111 Iterable<String> commonRTs =
1112 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1113 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1114 return Iterators.size(commonRTs.iterator()) > 0;
1118 VpnUtil.getAllVpnInstanceOpData(dataBroker).stream().filter(excludeVpn).filter(matchRTs).collect(
1119 Collectors.toList());
1120 return vpnsToExportRoute;
1123 // TODO Clean up the exception handling
1124 @SuppressWarnings("checkstyle:IllegalCatch")
1125 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1126 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1127 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1128 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getVrfId());
1129 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1130 if (vrfEntries != null) {
1131 for (VrfEntry vrfEntry : vrfEntries) {
1133 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1134 RouteOrigin.value(vrfEntry.getOrigin()))) {
1135 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1136 + " is not a controller managed non intervpn link route. Ignoring.",
1137 vpn.getVrfId(), vrfEntry.getDestPrefix());
1140 String prefix = vrfEntry.getDestPrefix();
1141 String gwMac = vrfEntry.getGatewayMacAddress();
1142 vrfEntry.getRoutePaths().forEach(routePath -> {
1143 String nh = routePath.getNexthopAddress();
1144 int label = routePath.getLabel().intValue();
1145 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1146 vrfEntry.getOrigin()))) {
1147 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1148 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1150 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1151 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1152 0 /*l3vni*/, gwMac, null /*parentVpnRd*/, RouteOrigin.SELF_IMPORTED,
1155 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} prefix {}"
1156 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1158 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1159 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, writeConfigTxn);
1162 } catch (RuntimeException e) {
1163 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1164 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1165 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1168 writeConfigTxn.submit();
1170 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1171 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1176 @SuppressWarnings("checkstyle:IllegalCatch")
1178 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1179 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1180 final String interfaceName = key.getName();
1181 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1182 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1183 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1187 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1188 final VpnInterface vpnInterface, final String vpnName,
1189 final String interfaceName) {
1190 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1191 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
1192 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1193 deleteFibEntryForRouterInterface(vpnInterface, writeConfigTxn, vpnName);
1194 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1195 ListenableFuture<Void> futures = writeConfigTxn.submit();
1196 String errorText = "removeVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
1197 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
1198 ListenableFutures.addErrorLogging(futures, LOG, errorText);
1199 return Collections.singletonList(futures);
1200 }, DJC_MAX_RETRIES);
1202 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1203 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1207 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1208 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1209 final VpnInterface vpnInterface, final String vpnName,
1210 final String interfaceName, final Interface interfaceState) {
1211 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1212 vpnName, vpnInterface.getDpnId());
1213 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1214 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1216 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1217 ListenableFuture<Void> configFuture = txRunner
1218 .callWithNewWriteOnlyTransactionAndSubmit(writeConfigTxn -> {
1219 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeOperTxn -> {
1220 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1221 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1222 interfaceName, vpnName);
1223 BigInteger dpId = BigInteger.ZERO;
1225 String gwMacAddress = null;
1226 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1227 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1228 final Optional<VpnInterfaceOpDataEntry> optVpnInterface =
1229 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1230 if (interfaceState != null) {
1232 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1233 } catch (NumberFormatException | IllegalStateException e) {
1234 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1235 + " data store for interface {} on dpn {} for vpn {} Fetching"
1236 + " from vpn interface op data store. ", interfaceName,
1237 vpnInterface.getDpnId(), vpnName, e);
1238 dpId = BigInteger.ZERO;
1240 ifIndex = interfaceState.getIfIndex();
1241 gwMacAddress = interfaceState.getPhysAddress().getValue();
1243 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1244 + " from vpn interface op.", interfaceName);
1245 if (optVpnInterface.isPresent()) {
1246 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1247 dpId = vpnOpInterface.getDpnId();
1248 ifIndex = vpnOpInterface.getLportTag().intValue();
1249 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1251 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1252 + " as interfaceState and vpn interface op is not"
1253 + " available", interfaceName, vpnName);
1257 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1258 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1259 writeConfigTxn, writeOperTxn, writeInvTxn);
1261 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1263 interfaceName, vpnInterface.getDpnId(), vpnName);
1267 futures.add(configFuture);
1268 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1270 }, DJC_MAX_RETRIES);
1273 protected void processVpnInterfaceDown(BigInteger dpId,
1274 String interfaceName,
1277 VpnInterfaceOpDataEntry vpnOpInterface,
1278 boolean isInterfaceStateDown,
1279 WriteTransaction writeConfigTxn,
1280 WriteTransaction writeOperTxn,
1281 WriteTransaction writeInvTxn) {
1282 if (vpnOpInterface == null) {
1283 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1284 + " as it is not available in operational data store", interfaceName, dpId);
1287 final String vpnName = vpnOpInterface.getVpnInstanceName();
1288 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1289 interfaceName, vpnName);
1290 if (!isInterfaceStateDown) {
1291 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1292 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1294 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1295 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1296 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1297 if (interfaceManager.isExternalInterface(interfaceName)) {
1298 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1299 NwConstants.DEL_FLOW);
1301 if (!isBgpVpnInternetVpn) {
1302 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1304 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1305 + " successful", interfaceName, dpId, vpnName);
1307 // Interface is retained in the DPN, but its Link Down.
1308 // Only withdraw the prefixes for this interface from BGP
1309 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1313 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1314 final String vpnName, final long vpnId, String gwMac,
1315 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1316 final WriteTransaction writeInvTxn) {
1318 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1319 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1320 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1321 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1323 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1324 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1325 interfaceName, dpnId, vpnName, primaryRd);
1326 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1327 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1328 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1329 interfaceName, dpnId, vpnName, nextHops);
1330 for (Adjacency nextHop : nextHops) {
1331 if (nextHop.isPhysNetworkFunc()) {
1332 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1333 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1334 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1335 null/*writeCfgTxn*/);
1337 String rd = nextHop.getVrfId();
1338 List<String> nhList;
1339 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1340 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1342 // This is a primary adjacency
1343 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1344 : Collections.emptyList();
1345 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1346 interfaceName, writeInvTxn);
1348 if (!nhList.isEmpty()) {
1349 if (rd.equals(vpnName)) {
1350 //this is an internal vpn - the rd is assigned to the vpn instance name;
1351 //remove from FIB directly
1352 nhList.forEach((nh) -> removeAdjacencyFromInternalVpn(nextHop, vpnName,
1353 interfaceName, dpnId, writeConfigTxn));
1355 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd, interfaceName,
1359 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1360 + " interface {}", nextHop.getIpAddress(), rd,
1361 nextHop.getAdjacencyType().toString(), interfaceName);
1362 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
1363 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1366 String ip = nextHop.getIpAddress().split("/")[0];
1367 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1368 if (vpnVipToPort != null) {
1369 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip);
1370 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed adjacency for Interface {}"
1371 + " ip {} on dpn {} for vpn {} from VpnPortData Entry", vpnVipToPort.getPortName(),
1372 ip, dpnId, vpnName);
1376 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1377 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1378 + " Removing it.", interfaceName, vpnName, dpnId);
1379 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1383 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1384 String interfaceName, BigInteger dpnId,
1385 WriteTransaction writeConfigTxn) {
1387 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1389 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1390 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1391 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1395 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1396 BigInteger dpnId, String rd, String interfaceName,
1397 WriteTransaction writeConfigTxn) {
1398 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1399 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1400 nhList.forEach((nh) -> {
1401 //IRT: remove routes from other vpns importing it
1402 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1403 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1404 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1405 String vpnRd = vpn.getVrfId();
1406 if (vpnRd != null) {
1407 fibManager.removeOrUpdateFibEntry(vpnRd,
1408 nextHop.getIpAddress(), nh, writeConfigTxn);
1409 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1410 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1411 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1412 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1418 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1419 int lportTag, String gwMac, String interfaceName,
1420 WriteTransaction writeInvTxn) {
1421 final Uuid subnetId = nextHop.getSubnetId();
1422 if (nextHop.getSubnetGatewayMacAddress() == null) {
1423 // A valid mac-address was not available for this subnet-gateway-ip
1424 // So a connected-mac-address was used for this subnet and we need
1425 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1426 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1427 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1429 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1433 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1434 String interfaceName) {
1435 // This is either an extra-route (or) a learned IP via subnet-route
1436 List<String> nhList = null;
1437 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1438 if (nextHopIp == null || nextHopIp.isEmpty()) {
1439 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1440 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1441 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1443 nhList = Collections.emptyList();
1445 nhList = Collections.singletonList(nextHopIp);
1450 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1451 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1452 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1453 // else use connected interface
1454 if (gwPort != null && gwPort.isSubnetIp()) {
1455 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1456 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1457 return Optional.of(gwPort.getMacAddress());
1459 return Optional.absent();
1463 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1464 final VpnInterface update) {
1465 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1466 update.getDpnId(), original.getVpnInstanceNames(),
1467 update.getVpnInstanceNames());
1468 final String vpnInterfaceName = update.getName();
1469 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1470 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1471 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1472 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1473 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1474 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1475 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1477 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1478 //handles switching between <internal VPN - external VPN>
1479 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1480 LOG.info("update: handled VPNInterface {} on dpn {} update"
1481 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1482 original.getName(), dpnId,
1483 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1484 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1487 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1488 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1489 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1490 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1491 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1492 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1493 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1494 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1495 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1496 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1497 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1498 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1499 update.getName(), newVpnName);
1500 //handle both addition and removal of adjacencies
1501 //currently, new adjacency may be an extra route
1502 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1503 if (!oldAdjs.equals(newAdjs)) {
1504 for (Adjacency adj : copyNewAdjs) {
1505 if (copyOldAdjs.contains(adj)) {
1506 copyOldAdjs.remove(adj);
1508 // add new adjacency - right now only extra route will hit this path
1509 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1510 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1511 dpnId, writeOperTxn, writeConfigTxn);
1513 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to vpn "
1514 + "interface {} on vpn {} dpnId {}",
1515 adj.getIpAddress(), adj.getNextHopIpList(),
1516 adj.getLabel(), adj.getSubnetId(), update.getName(),
1520 for (Adjacency adj : copyOldAdjs) {
1521 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1522 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1523 writeOperTxn, writeConfigTxn);
1525 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1526 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj.getNextHopIpList(),
1527 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1530 ListenableFuture<Void> operFuture = writeOperTxn.submit();
1533 } catch (ExecutionException e) {
1534 LOG.error("Exception encountered while submitting operational future for update"
1535 + " VpnInterface {} on vpn {}: {}", vpnInterfaceName, newVpnName, e);
1538 List<ListenableFuture<Void>> futures = new ArrayList<>();
1539 futures.add(writeConfigTxn.submit());
1540 LOG.info("update: vpn interface updated for interface {} oldVpn(s) {} newVpn {}"
1541 + "processed successfully", update.getName(),
1542 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()), newVpnName);
1546 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1547 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1552 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1553 VpnInterface original, VpnInterface update) {
1554 boolean isSwap = Boolean.FALSE;
1555 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1556 final String interfaceName = key.getName();
1557 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1558 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1559 List<String> oldVpnListCopy = new ArrayList<>();
1560 oldVpnListCopy.addAll(oldVpnList);
1561 List<String> newVpnList = update.getVpnInstanceNames().stream()
1562 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1563 oldVpnList.removeAll(newVpnList);
1564 for (String oldVpnName: oldVpnList) {
1565 isSwap = Boolean.TRUE;
1566 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {} running"
1567 + " config-driven swap removal", interfaceName, oldVpnName);
1568 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1569 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1570 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1572 //Wait for previous interface bindings to be removed
1575 } catch (InterruptedException e) {
1578 newVpnList.removeAll(oldVpnListCopy);
1579 for (String newVpnName: newVpnList) {
1580 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1581 isSwap = Boolean.TRUE;
1582 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1583 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1584 + "running config-driven swap addition", interfaceName, newVpnName);
1585 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1586 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1587 ? origAdjs.getAdjacency() : new ArrayList<>();
1588 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1589 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1590 ? updateAdjs.getAdjacency() : new ArrayList<>();
1592 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1593 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1594 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1595 interfaceName, oldVpnListCopy, newVpnName);
1601 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1602 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1603 synchronized (label.toString().intern()) {
1604 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1605 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1606 Optional<LabelRouteInfo> opResult = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
1607 if (opResult.isPresent()) {
1608 LabelRouteInfo labelRouteInfo =
1609 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1610 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, labelRouteInfo);
1613 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label, nextHopIpList);
1616 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1617 SubnetRoute route, WriteTransaction writeConfigTxn) {
1619 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1620 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, null /* parentVpnRd */)
1621 .addAugmentation(SubnetRoute.class, route).build();
1622 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1623 InstanceIdentifierBuilder<VrfTables> idBuilder =
1624 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1625 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1626 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1627 if (writeConfigTxn != null) {
1628 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1630 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1632 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1633 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1636 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1637 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1638 WriteTransaction writeConfigTxn) {
1640 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1641 LogicalDatastoreType.OPERATIONAL, identifier);
1643 if (optVpnInterface.isPresent()) {
1644 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1645 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1646 String vpnName = currVpnIntf.getVpnInstanceName();
1647 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1648 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1649 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker,
1650 LogicalDatastoreType.OPERATIONAL, adjPath);
1651 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1652 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1653 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1654 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1655 List<Adjacency> adjacencies;
1656 if (optAdjacencies.isPresent()) {
1657 adjacencies = optAdjacencies.get().getAdjacency();
1659 // This code will be hit in case of first PNF adjacency
1660 adjacencies = new ArrayList<>();
1662 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1663 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1664 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1665 Adjacency operationalAdjacency = null;
1666 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()) {
1667 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1668 : RouteOrigin.STATIC;
1669 String nh = adj.getNextHopIpList().get(0);
1670 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1671 synchronized (vpnPrefixKey.intern()) {
1672 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1673 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1674 if (rdToAllocate.isPresent()) {
1675 input.setRd(rdToAllocate.get());
1676 operationalAdjacency = populator.createOperationalAdjacency(input);
1677 int label = operationalAdjacency.getLabel().intValue();
1678 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1679 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1680 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1681 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1682 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1683 vpnName, label, currVpnIntf.getName(), dpnId);
1685 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}", vpnName,
1689 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1690 // Keeping the MPLS check for now.
1691 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1692 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1693 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1694 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1695 vpnsToImportRoute.forEach(vpn -> {
1696 if (vpn.getVrfId() != null) {
1697 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1698 dataBroker, vpn.getVpnId(), vpnId, prefix,
1699 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1701 rds -> vpnManager.addExtraRoute(
1702 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1703 adj.getIpAddress(), nh, rds,
1704 currVpnIntf.getVpnInstanceName(),
1705 l3vni, RouteOrigin.SELF_IMPORTED,
1706 currVpnIntf.getName(), opAdjacency, encapType, writeConfigTxn));
1711 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1712 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1713 currVpnIntf.getName(), vpnName);
1715 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1718 LogicalDatastoreType.OPERATIONAL,
1719 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1720 adj.getSubnetId().getValue()), prefix),
1721 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1722 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1724 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1725 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */, 0 /*l3vni*/,
1726 null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1728 input.setRd(adj.getVrfId());
1730 if (operationalAdjacency == null) {
1731 operationalAdjacency = populator.createOperationalAdjacency(input);
1733 adjacencies.add(operationalAdjacency);
1734 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1735 VpnInterfaceOpDataEntry newVpnIntf =
1736 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1737 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1738 currVpnIntf.getGatewayMacAddress());
1740 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1744 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1745 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1746 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1749 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1750 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1751 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1752 LogicalDatastoreType.OPERATIONAL, identifier);
1754 if (optVpnInterface.isPresent()) {
1755 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1757 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1758 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1759 if (optAdjacencies.isPresent()) {
1760 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1762 if (!adjacencies.isEmpty()) {
1763 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1764 Iterator<Adjacency> adjIt = adjacencies.iterator();
1765 while (adjIt.hasNext()) {
1766 Adjacency adjElem = adjIt.next();
1767 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1768 String rd = adjElem.getVrfId();
1771 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1772 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1773 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1774 currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove(),
1775 currVpnIntf.getLportTag(), currVpnIntf.getGatewayMacAddress());
1777 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1778 if (adj.getNextHopIpList() != null) {
1779 for (String nh : adj.getNextHopIpList()) {
1780 deleteExtraRouteFromCurrentAndImportingVpns(
1781 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1782 currVpnIntf.getName(), writeConfigTxn);
1784 } else if (adj.isPhysNetworkFunc()) {
1785 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet [}",
1786 adj.getIpAddress(), adj.getSubnetId());
1787 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1795 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1796 dpnId, adj.getVrfId());
1798 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1799 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1804 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1805 String rd, String intfName, WriteTransaction writeConfigTxn) {
1806 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1807 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1808 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1809 String vpnRd = vpn.getVrfId();
1810 if (vpnRd != null) {
1811 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
1816 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1817 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1818 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1819 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1822 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1823 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1824 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1827 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1828 WriteTransaction writeOperTxn) {
1829 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1830 if (dpId.equals(BigInteger.ZERO)) {
1831 LOG.error("addToNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1832 + " association model", vpnInterfaceName, routerName);
1836 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1838 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1839 .OPERATIONAL, routerDpnListIdentifier);
1840 RouterInterfaces routerInterface =
1841 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1842 vpnInterfaceName).build();
1843 if (optionalRouterDpnList.isPresent()) {
1844 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1845 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1847 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1848 builder.setRouterId(routerName);
1849 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1850 builder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1851 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1852 getRouterId(routerName),
1853 builder.build(), true);
1857 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1858 WriteTransaction writeOperTxn) {
1859 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1860 if (dpId.equals(BigInteger.ZERO)) {
1861 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1862 + " dissociation model", vpnInterfaceName, routerName);
1866 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1867 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1868 .OPERATIONAL, routerDpnListIdentifier);
1869 if (optionalRouterDpnList.isPresent()) {
1870 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1871 RouterInterfaces routerInterface =
1872 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1873 vpnInterfaceName).build();
1875 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1876 if (routerInterfaces.isEmpty()) {
1877 if (writeOperTxn != null) {
1878 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1880 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1883 if (writeOperTxn != null) {
1884 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1885 RouterInterfaces.class,
1886 new RouterInterfacesKey(vpnInterfaceName)));
1888 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL,
1889 routerDpnListIdentifier.child(
1890 RouterInterfaces.class,
1891 new RouterInterfacesKey(vpnInterfaceName)));
1898 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1899 WriteTransaction writeOperTxn) {
1900 if (dpId.equals(BigInteger.ZERO)) {
1901 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1902 + " dissociation model", vpnInterfaceName, routerName);
1906 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1907 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1908 .OPERATIONAL, routerDpnListIdentifier);
1909 if (optionalRouterDpnList.isPresent()) {
1910 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1911 RouterInterfaces routerInterface =
1912 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1913 vpnInterfaceName).build();
1914 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1915 if (routerInterfaces.isEmpty()) {
1916 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1918 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1919 RouterInterfaces.class,
1920 new RouterInterfacesKey(vpnInterfaceName)));
1926 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1927 WriteTransaction writeConfigTxn, String vpnName) {
1928 if (vpnInterface == null) {
1931 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
1933 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1934 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1937 for (Adjacency adj : adjs) {
1938 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1939 String primaryInterfaceIp = adj.getIpAddress();
1940 String macAddress = adj.getMacAddress();
1941 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1943 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1944 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1946 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1947 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1948 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1949 routerInt, label, writeConfigTxn);
1950 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1951 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1956 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1957 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1958 primaryRd, vpnName);
1961 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1962 WriteTransaction writeConfigTxn, String vpnName) {
1963 Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
1964 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1966 List<Adjacency> adjsList = adjs.getAdjacency();
1967 for (Adjacency adj : adjsList) {
1968 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1969 String primaryInterfaceIp = adj.getIpAddress();
1970 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1971 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1972 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1973 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1978 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
1979 vpnInterface.getName(), rd);
1983 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
1984 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
1985 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
1986 vpnName, intefaceData.vpnInterface.getName());
1989 final VpnInterfaceKey key = intefaceData.identifier
1990 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1991 final String interfaceName = key.getName();
1992 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
1993 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1994 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
1995 intefaceData.identifier, vpnName);
1999 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
2000 VpnInterface vpnInterface, String vpnName) {
2001 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
2003 if (vpnInterfaces == null) {
2004 vpnInterfaces = new ConcurrentLinkedQueue<>();
2006 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2007 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2008 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2009 vpnInterface.getName(), vpnName);
2012 public boolean isVpnInstanceReady(String vpnInstanceName) {
2013 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnInstanceName);
2014 if (vpnRd == null) {
2017 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
2019 return vpnInstanceOpDataEntry != null;
2022 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2023 synchronized (vpnInstanceName.intern()) {
2024 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2025 unprocessedVpnInterfaces.get(vpnInstanceName);
2026 if (vpnInterfaces != null) {
2027 while (!vpnInterfaces.isEmpty()) {
2028 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2029 if (hasVpnInstanceCreatedSuccessfully) {
2030 processSavedInterface(savedInterface, vpnInstanceName);
2031 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2032 savedInterface.vpnInterface.getName(), vpnInstanceName);
2034 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2035 savedInterface.vpnInterface.getName(), vpnInstanceName);
2039 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2044 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2045 VpnInterface vpnInterface) {
2046 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2047 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2048 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2049 if (vpnInterfaces != null) {
2050 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2051 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2052 + "unprocessed list", vpnInterface.getName(),
2053 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2056 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2057 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2062 public void vpnInstanceIsReady(String vpnInstanceName) {
2063 processSavedInterfaces(vpnInstanceName, true);
2066 public void vpnInstanceFailed(String vpnInstanceName) {
2067 processSavedInterfaces(vpnInstanceName, false);
2070 private static class UnprocessedVpnInterfaceData {
2071 InstanceIdentifier<VpnInterface> identifier;
2072 VpnInterface vpnInterface;
2074 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2075 this.identifier = identifier;
2076 this.vpnInterface = vpnInterface;
2080 public int hashCode() {
2081 final int prime = 31;
2083 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2084 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2089 public boolean equals(Object obj) {
2096 if (getClass() != obj.getClass()) {
2099 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2100 if (identifier == null) {
2101 if (other.identifier != null) {
2104 } else if (!identifier.equals(other.identifier)) {
2107 if (vpnInterface == null) {
2108 if (other.vpnInterface != null) {
2111 } else if (!vpnInterface.equals(other.vpnInterface)) {
2118 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2119 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
2120 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
2121 if (vpnInstanceOpData == null) {
2124 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2125 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2128 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2129 vpnToDpnLists.forEach(vpnToDpnList -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2130 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2131 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2132 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = VpnUtil.read(dataBroker,
2133 LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2134 if (!vpnInterfaceOptional.isPresent()) {
2137 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2138 vpnInterface.getInterfaceName());
2139 if (configVpnAdjacencies == null) {
2140 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2143 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2144 .getAugmentation(AdjacenciesOp.class).getAdjacency();
2145 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2146 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2147 // in operational DS. These unprocessed adjacencies will be handled below.
2148 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2149 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2150 configVpnAdjacencies.stream()
2151 .filter(adjacency -> operationVpnAdjacencies.stream()
2152 .noneMatch(operationalAdjacency ->
2153 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2154 .forEach(adjacency -> {
2155 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2156 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2158 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
2159 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
2160 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2161 addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd, adjacency,
2162 vpnInterfaceOptional.get().getDpnId(), writeConfigTxn, writeOperTxn);
2163 ListenableFuture<Void> operFuture = writeOperTxn.submit();
2166 } catch (ExecutionException | InterruptedException e) {
2167 LOG.error("Exception encountered while submitting operational"
2168 + " future for vpnInterface {}", vpnInterface, e);
2170 List<ListenableFuture<Void>> futures = new ArrayList<>();
2171 futures.add(writeConfigTxn.submit());
2174 return Collections.emptyList();
2181 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2182 private final String interfaceName;
2183 private final boolean add;
2184 private final String txnDestination;
2186 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2187 this.interfaceName = interfaceName;
2189 this.txnDestination = transactionDest;
2193 public void onSuccess(Void voidObj) {
2195 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2196 interfaceName, txnDestination);
2198 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2203 public void onFailure(Throwable throwable) {
2205 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2206 interfaceName, txnDestination, throwable);
2208 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2209 VpnUtil.unsetScheduledToRemoveForVpnInterface(dataBroker, interfaceName);