2 * Copyright (c) 2016 - 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.vpnmanager;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Iterators;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import com.google.common.util.concurrent.MoreExecutors;
17 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.List;
24 import java.util.Objects;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentLinkedQueue;
27 import java.util.function.Consumer;
28 import java.util.function.Predicate;
29 import java.util.stream.Collectors;
30 import javax.annotation.PostConstruct;
31 import javax.annotation.PreDestroy;
32 import javax.inject.Inject;
33 import javax.inject.Singleton;
34 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
35 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
36 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
37 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
39 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
40 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
41 import org.opendaylight.genius.mdsalutil.MDSALUtil;
42 import org.opendaylight.genius.mdsalutil.NWUtil;
43 import org.opendaylight.genius.mdsalutil.NwConstants;
44 import org.opendaylight.genius.mdsalutil.cache.InstanceIdDataObjectCache;
45 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
46 import org.opendaylight.infrautils.caches.CacheProvider;
47 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
48 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
49 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
50 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
51 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
52 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
53 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
54 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
55 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
56 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderHandler;
57 import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput;
58 import org.opendaylight.netvirt.vpnmanager.populator.intfc.VpnPopulator;
59 import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry;
60 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
109 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
110 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
111 import org.slf4j.Logger;
112 import org.slf4j.LoggerFactory;
115 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager> {
117 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
118 private static final short DJC_MAX_RETRIES = 3;
120 private final DataBroker dataBroker;
121 private final ManagedNewTransactionRunner txRunner;
122 private final IBgpManager bgpManager;
123 private final IFibManager fibManager;
124 private final IMdsalApiManager mdsalManager;
125 private final IdManagerService idManager;
126 private final OdlInterfaceRpcService ifaceMgrRpcService;
127 private final VpnFootprintService vpnFootprintService;
128 private final IInterfaceManager interfaceManager;
129 private final IVpnManager vpnManager;
130 private final ArpResponderHandler arpResponderHandler;
131 private final JobCoordinator jobCoordinator;
133 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
135 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
136 new ConcurrentHashMap<>();
138 private final InstanceIdDataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
141 public VpnInterfaceManager(final DataBroker dataBroker,
142 final IBgpManager bgpManager,
143 final IdManagerService idManager,
144 final IMdsalApiManager mdsalManager,
145 final IFibManager fibManager,
146 final OdlInterfaceRpcService ifaceMgrRpcService,
147 final VpnFootprintService vpnFootprintService,
148 final IInterfaceManager interfaceManager,
149 final IVpnManager vpnManager,
150 final ArpResponderHandler arpResponderHandler,
151 final JobCoordinator jobCoordinator,
152 final CacheProvider cacheProvider) {
153 super(VpnInterface.class, VpnInterfaceManager.class);
155 this.dataBroker = dataBroker;
156 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
157 this.bgpManager = bgpManager;
158 this.idManager = idManager;
159 this.mdsalManager = mdsalManager;
160 this.fibManager = fibManager;
161 this.ifaceMgrRpcService = ifaceMgrRpcService;
162 this.vpnFootprintService = vpnFootprintService;
163 this.interfaceManager = interfaceManager;
164 this.vpnManager = vpnManager;
165 this.arpResponderHandler = arpResponderHandler;
166 this.jobCoordinator = jobCoordinator;
168 vpnInstanceOpDataEntryCache = new InstanceIdDataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
169 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
170 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
173 public Runnable isNotifyTaskQueued(String intfName) {
174 return vpnIntfMap.remove(intfName);
178 public void start() {
179 LOG.info("{} start", getClass().getSimpleName());
180 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
185 public void close() {
187 vpnInstanceOpDataEntryCache.close();
191 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
192 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
196 protected VpnInterfaceManager getDataTreeChangeListener() {
197 return VpnInterfaceManager.this;
201 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
202 LOG.info("add: intfName {} onto vpnName {}",
203 vpnInterface.getName(),
204 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
205 addVpnInterface(identifier, vpnInterface, null, null);
208 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
209 final VpnInterface vpnInterface, String vpnName) {
210 synchronized (vpnName.intern()) {
211 if (isVpnInstanceReady(vpnName)) {
214 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
219 // TODO Clean up the exception handling
220 @SuppressWarnings("checkstyle:IllegalCatch")
221 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
222 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
223 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
224 String vpnName = vpnInterfaceVpnInstance.getVpnName();
225 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
229 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
230 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
231 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
232 final String interfaceName = key.getName();
234 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
235 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
236 vpnName, vpnInterface.getName());
239 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
240 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
241 List<Adjacency> copyOldAdjs = null;
242 if (oldAdjs != null) {
243 copyOldAdjs = new ArrayList<>();
244 copyOldAdjs.addAll(oldAdjs);
246 List<Adjacency> copyNewAdjs = null;
247 if (newAdjs != null) {
248 copyNewAdjs = new ArrayList<>();
249 copyNewAdjs.addAll(newAdjs);
251 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
254 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
255 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
256 final List<Adjacency> newAdjs,
257 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
258 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
259 final String interfaceName = key.getName();
260 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
261 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
262 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
263 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
264 if (interfaceState != null) {
266 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
267 final int ifIndex = interfaceState.getIfIndex();
268 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName, () -> {
269 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
270 // (the inventory tx goes in last)
271 List<ListenableFuture<Void>> futures = new ArrayList<>();
272 ListenableFuture<Void> confFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
273 confTx -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
274 operTx -> futures.add(
275 txRunner.callWithNewWriteOnlyTransactionAndSubmit(invTx -> {
277 "addVpnInterface: VPN Interface add event - intfName {} vpnName {}"
279 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
280 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false,
281 confTx, operTx, invTx, interfaceState, vpnName);
282 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
283 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
284 + " Update for swapping VPN {} case.", interfaceName, vpnName);
285 if (newAdjs != null) {
286 for (Adjacency adj : newAdjs) {
287 if (oldAdjs.contains(adj)) {
290 if (!isBgpVpnInternetVpn
291 || VpnUtil.isAdjacencyEligibleToVpnInternet(
293 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier,
294 primaryRd, adj, dpnId, operTx, confTx);
299 for (Adjacency adj : oldAdjs) {
300 if (!isBgpVpnInternetVpn
301 || VpnUtil.isAdjacencyEligibleToVpnInternet(
303 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
309 futures.add(confFuture);
310 Futures.addCallback(confFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"),
311 MoreExecutors.directExecutor());
312 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
313 + " processed successfully", interfaceName, vpnName, dpnId);
316 } catch (NumberFormatException | IllegalStateException e) {
317 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
318 + "interface {}. Interface addition on vpn {} failed", interfaceName,
322 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
323 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(),
325 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
326 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
328 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
329 vpnName, vpnInterface.getDpnId());
331 ListenableFutures.addErrorLogging(future, LOG,
332 "Error creating FIB entry for interface {} on VPN {}", vpnInterface.getName(), vpnName);
333 return Collections.singletonList(future);
336 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
337 + " is not available", interfaceName, vpnName);
340 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
341 + " as vpn is pending delete", interfaceName, vpnName,
342 vpnInterface.getDpnId());
346 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
347 // see comments below.
348 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
349 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
350 final int lportTag, boolean isInterfaceUp,
351 WriteTransaction writeConfigTxn,
352 WriteTransaction writeOperTxn,
353 WriteTransaction writeInvTxn,
354 Interface interfaceState,
355 final String vpnName) {
356 final String interfaceName = vpnInterface.getName();
357 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
358 interfaceName, vpnName);
359 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
360 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
361 if (!isInterfaceUp) {
362 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
363 interfaceName, dpId, vpnName);
364 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
365 if (vpnId == VpnConstants.INVALID_ID) {
366 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
367 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
372 boolean waitForVpnInterfaceOpRemoval = false;
373 if (opVpnInterface != null && !opVpnInterface.isScheduledForRemove()) {
374 String opVpnName = opVpnInterface.getVpnInstanceName();
375 String primaryInterfaceIp = null;
376 if (opVpnName.equals(vpnName)) {
377 // Please check if the primary VRF Entry does not exist for VPNInterface
378 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
380 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
381 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
383 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
384 + " for this vpn interface could not be obtained", interfaceName, dpId,
388 for (Adjacency adj : adjs) {
389 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
390 primaryInterfaceIp = adj.getIpAddress();
394 if (primaryInterfaceIp == null) {
395 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
396 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
400 // Get the rd of the vpn instance
401 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, primaryRd, primaryInterfaceIp);
403 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
404 + " bailing out from here.", interfaceName, dpId, vpnName);
407 waitForVpnInterfaceOpRemoval = true;
409 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
410 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
413 if (!waitForVpnInterfaceOpRemoval) {
414 // Add the VPNInterface and quit
415 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
416 null/*ipAddressSourceValuePair*/,
418 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
419 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
420 if (!isBgpVpnInternetVpn) {
421 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false /*isTunnelInterface*/,
424 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
426 if (interfaceManager.isExternalInterface(interfaceName)) {
427 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
428 NwConstants.ADD_FLOW);
433 // FIB didn't get a chance yet to clean up this VPNInterface
434 // Let us give it a chance here !
435 LOG.info("processVpnInterfaceUp: Trying to add VPN Interface {} on dpn {} for vpn {},"
436 + " but waiting for FIB to clean up! ", interfaceName, dpId, vpnName);
438 Runnable notifyTask = new VpnNotifyTask();
439 synchronized (notifyTask) {
440 // Per FB's "Unconditional wait" violation, the code should really verify that the condition it
441 // intends to wait for is not already satisfied before calling wait. However the VpnNotifyTask is
442 // published here while holding the lock on it so this path will hit the wait before notify can be
444 vpnIntfMap.put(interfaceName, notifyTask);
446 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
447 } catch (InterruptedException e) {
452 vpnIntfMap.remove(interfaceName);
455 if (opVpnInterface != null) {
456 LOG.warn("processVpnInterfaceUp: VPN Interface {} removal on dpn {} for vpn {}"
457 + " by FIB did not complete on time," + " bailing addition ...", interfaceName,
459 VpnUtil.unsetScheduledToRemoveForVpnInterface(txRunner, interfaceName);
462 // VPNInterface got removed, proceed with Add
463 LOG.info("processVpnInterfaceUp: Continuing to plumb vpn interface {} onto dpn {} for vpn {}",
464 interfaceName, dpId, vpnName);
465 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
466 null/*ipAddressSourceValuePair*/,
468 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
469 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
470 if (!isBgpVpnInternetVpn) {
471 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false/*isTunnelInterface*/, jobCoordinator);
473 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
474 + " FIB to clean up", interfaceName, dpId, vpnName);
475 if (interfaceManager.isExternalInterface(interfaceName)) {
476 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId,
477 lportTag, writeInvTxn, NwConstants.ADD_FLOW);
480 // Interface is retained in the DPN, but its Link Up.
481 // Advertise prefixes again for this interface to BGP
482 InstanceIdentifier<VpnInterface> identifier =
483 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName());
484 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
485 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
486 advertiseAdjacenciesForVpnToBgp(primaryRd, dpId, vpnInterfaceOpIdentifier, vpnName, interfaceName);
487 // Perform similar operation as interface add event for extraroutes.
488 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
489 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
490 if (!optAdjacencies.isPresent()) {
491 LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
494 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
495 for (Adjacency adjacency : adjacencies) {
496 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
499 // if BGPVPN Internet, filter only IPv6 Adjacencies
500 if (isBgpVpnInternetVpn && !VpnUtil.isAdjacencyEligibleToVpnInternet(
501 dataBroker, adjacency)) {
504 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
505 dpId, writeOperTxn, writeConfigTxn);
510 private void processExternalVpnInterface(String interfaceName, String vpnName, long vpnId, BigInteger dpId,
511 int lportTag, WriteTransaction writeInvTxn, int addOrRemove) {
514 // vpn instance of ext-net interface is the network-id
515 extNetworkId = new Uuid(vpnName);
516 } catch (IllegalArgumentException e) {
517 LOG.error("processExternalVpnInterface: VPN instance {} is not Uuid. Processing external vpn interface {}"
518 + " on dpn {} failed", vpnName, interfaceName, dpId);
522 List<Uuid> routerIds = VpnUtil.getExternalNetworkRouterIds(dataBroker, extNetworkId);
523 if (routerIds == null || routerIds.isEmpty()) {
524 LOG.info("processExternalVpnInterface: No router is associated with {}."
525 + " Bailing out of processing external vpn interface {} on dpn {} for vpn {}",
526 extNetworkId.getValue(), interfaceName, dpId, vpnName);
530 LOG.info("processExternalVpnInterface: Router-ids {} associated with exernal vpn-interface {} on dpn {}"
531 + " for vpn {}", routerIds, interfaceName, dpId, vpnName);
532 for (Uuid routerId : routerIds) {
533 String routerName = routerId.getValue();
534 BigInteger primarySwitch = VpnUtil.getPrimarySwitchForRouter(dataBroker, routerName);
535 if (Objects.equals(primarySwitch, dpId)) {
536 Routers router = VpnUtil.getExternalRouter(dataBroker, routerName);
537 if (router != null) {
538 if (addOrRemove == NwConstants.ADD_FLOW) {
539 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
540 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
541 dpId, interfaceName, lportTag, writeInvTxn);
543 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
544 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
545 dpId, interfaceName, lportTag);
548 LOG.error("processExternalVpnInterface: No external-router found for router-id {}. Bailing out of"
549 + " processing external vpn-interface {} on dpn {} for vpn {}", routerName,
550 interfaceName, dpId, vpnName);
556 // TODO Clean up the exception handling
557 @SuppressWarnings("checkstyle:IllegalCatch")
558 private void advertiseAdjacenciesForVpnToBgp(final String rd, BigInteger dpnId,
559 final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
560 String vpnName, String interfaceName) {
562 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} on dpn {} in vpn {}",
563 interfaceName, dpnId, vpnName);
566 if (rd.equals(vpnName)) {
567 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} on dpn {}"
568 + " as it is in internal vpn{} with rd {}", interfaceName, dpnId, vpnName, rd);
572 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} on dpn {} in vpn {} with rd {} ",
573 interfaceName, dpnId, vpnName, rd);
575 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
576 if (nextHopIp == null) {
577 LOG.error("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} on dpn {} is null,"
578 + " returning from advertising route with rd {} vpn {} to bgp", interfaceName, dpnId,
584 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
585 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
586 if (adjacencies.isPresent()) {
587 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
589 if (!nextHops.isEmpty()) {
590 LOG.debug("advertiseAdjacenciesForVpnToBgp: NextHops are {} for interface {} on dpn {} for vpn {}"
591 + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
592 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
593 long l3vni = vpnInstanceOpData.getL3vni();
594 VrfEntry.EncapType encapType = VpnUtil.isL3VpnOverVxLan(l3vni)
595 ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
596 for (Adjacency nextHop : nextHops) {
597 if (nextHop.getAdjacencyType() == AdjacencyType.ExtraRoute) {
600 String gatewayMac = null;
602 if (VpnUtil.isL3VpnOverVxLan(l3vni)) {
603 final VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
604 vpnInstanceOpData.getVpnInstanceName(), nextHop.getIpAddress());
605 gatewayMac = arpResponderHandler.getGatewayMacAddressForInterface(gwPort, interfaceName).get();
607 label = nextHop.getLabel();
610 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Adding Fib Entry rd {} prefix {}"
611 + " nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
612 bgpManager.advertisePrefix(rd, nextHop.getMacAddress(), nextHop.getIpAddress(), nextHopIp,
613 encapType, (int)label, l3vni, 0 /*l2vni*/,
615 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Added Fib Entry rd {} prefix {}"
616 + " nexthop {} label {} for interface {} on dpn {} for vpn {}", rd,
617 nextHop.getIpAddress(), nextHopIp, label, interfaceName, dpnId, vpnName);
618 } catch (Exception e) {
619 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to advertise prefix {} in vpn {} with rd {}"
620 + " for interface {} on dpn {}", nextHop.getIpAddress(),
621 vpnName, rd, interfaceName, dpnId, e);
628 // TODO Clean up the exception handling
629 @SuppressWarnings("checkstyle:IllegalCatch")
630 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
631 String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
633 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
634 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
636 String rd = VpnUtil.getVpnRd(dataBroker, interfaceName);
638 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
639 interfaceName, vpnName);
642 if (rd.equals(vpnName)) {
644 "withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in "
645 + "internal vpn{} with rd {}", interfaceName, vpnName, rd);
649 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", interfaceName,
651 if (adjacencies.isPresent()) {
652 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
654 if (!nextHops.isEmpty()) {
655 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
656 nextHops, interfaceName, vpnName, rd);
657 for (Adjacency nextHop : nextHops) {
659 if (nextHop.getAdjacencyType() != AdjacencyType.ExtraRoute) {
660 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removing Fib Entry rd {}"
661 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
662 interfaceName, vpnName);
663 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
664 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removed Fib Entry rd {}"
665 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
666 interfaceName, vpnName);
668 // Perform similar operation as interface delete event for extraroutes.
669 String allocatedRd = nextHop.getVrfId();
670 for (String nh : nextHop.getNextHopIpList()) {
671 deleteExtraRouteFromCurrentAndImportingVpns(
672 vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn);
675 } catch (Exception e) {
676 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
677 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
684 @SuppressWarnings("checkstyle:IllegalCatch")
685 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
686 String primaryRd, String interfaceName, final long vpnId,
687 WriteTransaction writeConfigTxn,
688 WriteTransaction writeOperTxn,
689 final WriteTransaction writeInvTxn,
690 Interface interfaceState) {
691 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
693 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
694 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
695 if (!adjacencies.isPresent()) {
696 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
697 null/*gwMac*/, writeOperTxn);
701 // Get the rd of the vpn instance
702 String nextHopIp = null;
704 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
705 } catch (Exception e) {
706 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
707 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
709 List<String> nhList = new ArrayList<>();
710 if (nextHopIp != null) {
711 nhList.add(nextHopIp);
712 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
713 interfaceName, dpnId, vpnName, nhList);
715 Optional<String> gwMac = Optional.absent();
716 String vpnInterfaceSubnetGwMacAddress = null;
717 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
718 Long l3vni = vpnInstanceOpData.getL3vni();
719 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
720 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
721 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
722 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
723 List<Adjacency> value = new ArrayList<>();
724 for (Adjacency nextHop : nextHops) {
725 String rd = primaryRd;
726 String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
727 if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
728 && NWUtil.isIpv4Address(nexthopIpValue)) {
729 String prefix = nextHop.getIpAddress() == null ? "null" :
730 VpnUtil.getIpPrefix(nextHop.getIpAddress());
731 LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
732 + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
735 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
736 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
737 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
738 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
739 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
740 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
742 LogicalDatastoreType.OPERATIONAL,
743 VpnUtil.getPrefixToInterfaceIdentifier(
744 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
745 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
747 final Uuid subnetId = nextHop.getSubnetId();
749 String gatewayIp = nextHop.getSubnetGatewayIp();
750 if (gatewayIp == null) {
751 Optional<String> gatewayIpOptional = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
752 if (gatewayIpOptional.isPresent()) {
753 gatewayIp = gatewayIpOptional.get();
757 if (gatewayIp != null) {
758 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
759 if (gwMac.isPresent()) {
760 // A valid mac-address is available for this subnet-gateway-ip
761 // Use this for programming ARP_RESPONDER table here. And save this
762 // info into vpnInterface operational, so it can used in VrfEntryProcessor
763 // to populate L3_GW_MAC_TABLE there.
764 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
765 gatewayIp, gwMac.get());
766 vpnInterfaceSubnetGwMacAddress = gwMac.get();
768 // A valid mac-address is not available for this subnet-gateway-ip
769 // Use the connected-mac-address to configure ARP_RESPONDER Table.
770 // Save this connected-mac-address as gateway-mac-address for the
771 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
772 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
773 if (gwMac.isPresent()) {
774 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
775 vpnId, writeInvTxn, NwConstants.ADD_FLOW, gwMac.get());
776 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
777 gatewayIp, gwMac.get());
779 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
780 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
782 subnetId, interfaceName, vpnName, gatewayIp);
786 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
787 + "cannot create ARP responder flow for interface name {}, vpnName {}",
788 subnetId, interfaceName, vpnName);
789 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
791 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
792 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
794 //Extra route adjacency
795 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
796 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
797 synchronized (vpnPrefixKey.intern()) {
798 java.util.Optional<String> rdToAllocate = VpnUtil
799 .allocateRdForExtraRouteAndUpdateUsedRdsMap(dataBroker, vpnId, null,
800 prefix, vpnName, nextHop.getNextHopIpList().get(0), dpnId);
801 if (rdToAllocate.isPresent()) {
802 rd = rdToAllocate.get();
803 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
806 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
810 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
811 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
812 interfaceName, dpnId);
814 // Please note that primary adjacency will use a subnet-gateway-mac-address that
815 // can be different from the gateway-mac-address within the VRFEntry as the
816 // gateway-mac-address is a superset.
817 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
818 : RouteOrigin.STATIC;
819 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
820 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
821 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
822 Adjacency operationalAdjacency = null;
824 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
825 } catch (NullPointerException e) {
826 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
827 input, e.getMessage());
830 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
831 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
832 vpnName, l3vni, origin,
833 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
835 value.add(operationalAdjacency);
838 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
839 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
840 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
842 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
843 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
844 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
846 for (Adjacency nextHop : aug.getAdjacency()) {
847 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
848 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
849 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
850 : RouteOrigin.STATIC;
851 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
852 registeredPopulator.populateFib(input, writeConfigTxn);
857 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
858 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
859 VpnInterfaceOpDataEntry opInterface =
860 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, Boolean.FALSE, lportTag, gwMac);
861 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
862 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
863 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
864 WriteTransaction.CREATE_MISSING_PARENTS);
865 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
866 interfaceName, dpnId, vpnName);
869 // TODO Clean up the exception handling
870 @SuppressWarnings("checkstyle:IllegalCatch")
871 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
872 StateTunnelList stateTunnelList,
873 WriteTransaction writeConfigTxn,
874 WriteTransaction writeOperTxn) {
876 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
877 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
878 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
879 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
880 if (adjList.isEmpty()) {
881 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
882 vpnInterface, srcDpnId);
885 String prefix = null;
887 List<Adjacency> value = new ArrayList<>();
888 boolean isNextHopAddReqd = false;
889 String vpnName = vpnInterface.getVpnInstanceName();
890 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
891 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
892 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
893 vpnInterface.getName(), vpnInterface.getDpnId(),
894 vpnInterface.getVpnInstanceName(), adjList);
895 for (Adjacency adj : adjList) {
896 String rd = adj.getVrfId();
897 rd = rd != null ? rd : vpnName;
898 prefix = adj.getIpAddress();
899 label = adj.getLabel();
900 List<String> nhList = Collections.singletonList(srcTepIp);
901 List<String> nextHopList = adj.getNextHopIpList();
902 // If TEP is added , update the nexthop of primary adjacency.
903 // Secondary adj nexthop is already pointing to primary adj IP address.
904 if (nextHopList != null && !nextHopList.isEmpty()) {
905 /* everything right already */
907 isNextHopAddReqd = true;
910 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
911 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
913 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
914 if (!vrfEntryOptional.isPresent()) {
917 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
918 if (!nhList.contains(srcTepIp)) {
919 nhList.add(srcTepIp);
920 isNextHopAddReqd = true;
925 if (isNextHopAddReqd) {
926 updateLabelMapper(label, nhList);
927 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
928 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
929 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
930 // Update the VRF entry with nextHop
931 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
932 label, true, writeConfigTxn);
934 //Get the list of VPN's importing this route(prefix) .
935 // Then update the VRF entry with nhList
936 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
937 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
938 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
939 String vpnRd = vpn.getVrfId();
941 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
942 srcTepIp, label, true, writeConfigTxn);
943 LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
944 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
945 vpnInterface.getName(), srcDpnId, vpnName,
946 vpn.getVpnInstanceName(), vpnRd);
949 // Advertise the prefix to BGP only for external vpn
950 // since there is a nexthop change.
952 if (!rd.equalsIgnoreCase(vpnName)) {
953 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, nhList,
954 VrfEntry.EncapType.Mplsgre, (int)label, 0 /*evi*/, 0 /*l2vni*/,
955 null /*gatewayMacAddress*/);
957 LOG.info("updateVpnInterfaceOnTepAdd: Advertised rd {} prefix {} nhList {} label {}"
958 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label, vpnInterface.getName(),
960 } catch (Exception ex) {
961 LOG.error("updateVpnInterfaceOnTepAdd: Exception when advertising prefix {} nh {} label {}"
962 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
963 vpnInterface.getName(), srcDpnId, vpnName, ex);
967 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
968 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
969 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
970 .addAugmentation(AdjacenciesOp.class, aug).build();
971 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
972 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
973 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
974 WriteTransaction.CREATE_MISSING_PARENTS);
975 LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
976 vpnInterface.getName(), srcDpnId, vpnName);
980 // TODO Clean up the exception handling
981 @SuppressWarnings("checkstyle:IllegalCatch")
982 public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
983 StateTunnelList stateTunnelList,
984 WriteTransaction writeConfigTxn,
985 WriteTransaction writeOperTxn) {
987 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
988 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
989 String prefix = null;
991 boolean isNextHopRemoveReqd = false;
992 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
993 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
994 String vpnName = vpnInterface.getVpnInstanceName();
995 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
996 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
997 if (adjList != null) {
998 List<Adjacency> value = new ArrayList<>();
999 LOG.info("updateVpnInterfaceOnTepDelete: AdjacencyList for interface {} on dpn {} vpn {} is {}",
1000 vpnInterface.getName(), vpnInterface.getDpnId(),
1001 vpnInterface.getVpnInstanceName(), adjList);
1002 for (Adjacency adj : adjList) {
1003 List<String> nhList = new ArrayList<>();
1004 String rd = adj.getVrfId();
1005 rd = rd != null ? rd : vpnName;
1006 prefix = adj.getIpAddress();
1007 List<String> nextHopList = adj.getNextHopIpList();
1008 label = adj.getLabel();
1009 if (nextHopList != null && !nextHopList.isEmpty()) {
1010 isNextHopRemoveReqd = true;
1012 // If TEP is deleted , remove the nexthop from primary adjacency.
1013 // Secondary adj nexthop will continue to point to primary adj IP address.
1014 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1015 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
1017 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
1018 if (!vrfEntryOptional.isPresent()) {
1021 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
1022 if (nhList.contains(srcTepIp)) {
1023 nhList.remove(srcTepIp);
1024 isNextHopRemoveReqd = true;
1029 if (isNextHopRemoveReqd) {
1030 updateLabelMapper(label, nhList);
1031 LOG.info("updateVpnInterfaceOnTepDelete: Updated label mapper : label {} dpn {} prefix {}"
1032 + " nexthoplist {} vpn {} vpnid {} rd {} interface {}", label, srcDpnId,
1033 prefix, nhList, vpnName,
1034 vpnId, rd, vpnInterface.getName());
1035 // Update the VRF entry with removed nextHop
1036 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
1037 label, false, writeConfigTxn);
1039 //Get the list of VPN's importing this route(prefix) .
1040 // Then update the VRF entry with nhList
1041 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1042 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1043 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1044 String vpnRd = vpn.getVrfId();
1045 if (vpnRd != null) {
1046 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1047 srcTepIp, label, false, writeConfigTxn);
1048 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1049 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1050 nhList, label, vpnInterface.getName(), srcDpnId,
1052 vpn.getVpnInstanceName(), vpnRd);
1056 // Withdraw prefix from BGP only for external vpn.
1058 if (!rd.equalsIgnoreCase(vpnName)) {
1059 bgpManager.withdrawPrefix(rd, prefix);
1061 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1062 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1063 vpnInterface.getName(), srcDpnId,
1065 } catch (Exception ex) {
1066 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1067 + " on rd {} for interface {} on dpn {} vpn {}", prefix, nhList, label, rd,
1068 vpnInterface.getName(), srcDpnId, vpnName, ex);
1072 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1073 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1074 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1075 .addAugmentation(AdjacenciesOp.class, aug).build();
1076 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1077 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1078 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1079 WriteTransaction.CREATE_MISSING_PARENTS);
1080 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1081 vpnInterface.getName(), srcDpnId, vpnName);
1085 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1086 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1088 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1089 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
1090 if (vpnInstanceOpDataEntry == null) {
1091 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1092 + " to check for vpns exporting the routes", vpnName);
1093 return vpnsToExportRoute;
1096 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1097 if (input.getVpnInstanceName() == null) {
1098 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1102 return !input.getVpnInstanceName().equals(vpnName);
1105 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1106 Iterable<String> commonRTs =
1107 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1108 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1109 return Iterators.size(commonRTs.iterator()) > 0;
1113 VpnUtil.getAllVpnInstanceOpData(dataBroker).stream().filter(excludeVpn).filter(matchRTs).collect(
1114 Collectors.toList());
1115 return vpnsToExportRoute;
1118 // TODO Clean up the exception handling
1119 @SuppressWarnings("checkstyle:IllegalCatch")
1120 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1121 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1122 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1123 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getVrfId());
1124 if (vrfEntries != null) {
1125 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1126 for (VrfEntry vrfEntry : vrfEntries) {
1128 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1129 RouteOrigin.value(vrfEntry.getOrigin()))) {
1130 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1131 + " is not a controller managed non intervpn link route. Ignoring.",
1132 vpn.getVrfId(), vrfEntry.getDestPrefix());
1135 String prefix = vrfEntry.getDestPrefix();
1136 String gwMac = vrfEntry.getGatewayMacAddress();
1137 vrfEntry.getRoutePaths().forEach(routePath -> {
1138 String nh = routePath.getNexthopAddress();
1139 int label = routePath.getLabel().intValue();
1140 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1141 vrfEntry.getOrigin()))) {
1142 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1143 + " nexthop {} label {} to vpn {} vpnRd {}",
1144 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1145 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1146 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1147 0 /*l3vni*/, gwMac, vpn.getVrfId(), RouteOrigin.SELF_IMPORTED,
1150 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} "
1151 + "prefix {} nexthop {} label {} to vpn {} vpnRd {}",
1152 vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
1153 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1154 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, vpn.getVrfId(),
1158 } catch (RuntimeException e) {
1159 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1160 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1161 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1164 }), LOG, "Error handing VPN exporting routes");
1166 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1167 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1173 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1174 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1175 final String interfaceName = key.getName();
1176 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1177 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1178 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1182 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1183 final VpnInterface vpnInterface, final String vpnName,
1184 final String interfaceName) {
1185 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1186 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName(), () -> {
1187 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1188 deleteFibEntryForRouterInterface(vpnInterface, confTx, vpnName);
1189 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1191 ListenableFutures.addErrorLogging(future, LOG, "Error removing call for interface {} on VPN {}",
1192 vpnInterface.getName(), vpnName);
1193 return Collections.singletonList(future);
1194 }, DJC_MAX_RETRIES);
1196 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1197 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1201 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1202 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1203 final VpnInterface vpnInterface, final String vpnName,
1204 final String interfaceName, final Interface interfaceState) {
1205 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1206 vpnName, vpnInterface.getDpnId());
1207 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1208 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1210 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1211 ListenableFuture<Void> configFuture = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1212 writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1213 writeOperTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1214 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1215 interfaceName, vpnName);
1216 BigInteger dpId = BigInteger.ZERO;
1218 String gwMacAddress = null;
1219 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1220 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1221 final Optional<VpnInterfaceOpDataEntry> optVpnInterface =
1222 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1223 if (interfaceState != null) {
1225 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1226 } catch (NumberFormatException | IllegalStateException e) {
1227 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1228 + " data store for interface {} on dpn {} for vpn {} Fetching"
1229 + " from vpn interface op data store. ", interfaceName,
1230 vpnInterface.getDpnId(), vpnName, e);
1231 dpId = BigInteger.ZERO;
1233 ifIndex = interfaceState.getIfIndex();
1234 gwMacAddress = interfaceState.getPhysAddress().getValue();
1236 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1237 + " from vpn interface op.", interfaceName);
1238 if (optVpnInterface.isPresent()) {
1239 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1240 dpId = vpnOpInterface.getDpnId();
1241 ifIndex = vpnOpInterface.getLportTag().intValue();
1242 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1244 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1245 + " as interfaceState and vpn interface op is not"
1246 + " available", interfaceName, vpnName);
1250 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1251 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1252 writeConfigTxn, writeOperTxn, writeInvTxn);
1254 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1256 interfaceName, vpnInterface.getDpnId(), vpnName);
1258 futures.add(configFuture);
1259 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1261 }, DJC_MAX_RETRIES);
1264 protected void processVpnInterfaceDown(BigInteger dpId,
1265 String interfaceName,
1268 VpnInterfaceOpDataEntry vpnOpInterface,
1269 boolean isInterfaceStateDown,
1270 WriteTransaction writeConfigTxn,
1271 WriteTransaction writeOperTxn,
1272 WriteTransaction writeInvTxn) {
1273 if (vpnOpInterface == null) {
1274 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1275 + " as it is not available in operational data store", interfaceName, dpId);
1278 final String vpnName = vpnOpInterface.getVpnInstanceName();
1279 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1280 interfaceName, vpnName);
1281 if (!isInterfaceStateDown) {
1282 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1283 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1285 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1286 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1287 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1288 if (interfaceManager.isExternalInterface(interfaceName)) {
1289 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1290 NwConstants.DEL_FLOW);
1292 if (!isBgpVpnInternetVpn) {
1293 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1295 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1296 + " successful", interfaceName, dpId, vpnName);
1298 // Interface is retained in the DPN, but its Link Down.
1299 // Only withdraw the prefixes for this interface from BGP
1300 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1304 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1305 final String vpnName, final long vpnId, String gwMac,
1306 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1307 final WriteTransaction writeInvTxn) {
1309 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1310 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1311 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1312 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1314 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1315 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1316 interfaceName, dpnId, vpnName, primaryRd);
1317 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1318 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1319 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1320 interfaceName, dpnId, vpnName, nextHops);
1321 for (Adjacency nextHop : nextHops) {
1322 if (nextHop.isPhysNetworkFunc()) {
1323 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1324 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1325 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1326 null/*writeCfgTxn*/);
1328 String rd = nextHop.getVrfId();
1329 List<String> nhList;
1330 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1331 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1333 // This is a primary adjacency
1334 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1335 : Collections.emptyList();
1336 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1337 interfaceName, writeInvTxn);
1339 if (!nhList.isEmpty()) {
1340 if (rd.equals(vpnName)) {
1341 //this is an internal vpn - the rd is assigned to the vpn instance name;
1342 //remove from FIB directly
1343 nhList.forEach(removeAdjacencyFromInternalVpn(nextHop, vpnName,
1344 interfaceName, dpnId, writeConfigTxn));
1346 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd, interfaceName,
1350 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1351 + " interface {}", nextHop.getIpAddress(), rd,
1352 nextHop.getAdjacencyType().toString(), interfaceName);
1353 bgpManager.withdrawPrefixIfPresent(rd, nextHop.getIpAddress());
1354 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1357 String ip = nextHop.getIpAddress().split("/")[0];
1358 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1359 if (vpnVipToPort != null) {
1360 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip, null);
1361 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed adjacency for Interface {}"
1362 + " ip {} on dpn {} for vpn {} from VpnPortData Entry", vpnVipToPort.getPortName(),
1363 ip, dpnId, vpnName);
1367 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1368 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1369 + " Removing it.", interfaceName, vpnName, dpnId);
1370 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1374 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1375 String interfaceName, BigInteger dpnId,
1376 WriteTransaction writeConfigTxn) {
1378 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1380 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1381 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1382 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1386 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1387 BigInteger dpnId, String rd, String interfaceName,
1388 WriteTransaction writeConfigTxn) {
1389 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1390 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1391 nhList.forEach((nh) -> {
1392 //IRT: remove routes from other vpns importing it
1393 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1394 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1395 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1396 String vpnRd = vpn.getVrfId();
1397 if (vpnRd != null) {
1398 fibManager.removeOrUpdateFibEntry(vpnRd,
1399 nextHop.getIpAddress(), nh, writeConfigTxn);
1400 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1401 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1402 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1403 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1409 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1410 int lportTag, String gwMac, String interfaceName,
1411 WriteTransaction writeInvTxn) {
1412 final Uuid subnetId = nextHop.getSubnetId();
1413 if (nextHop.getSubnetGatewayMacAddress() == null) {
1414 // A valid mac-address was not available for this subnet-gateway-ip
1415 // So a connected-mac-address was used for this subnet and we need
1416 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1417 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1418 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1420 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1424 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1425 String interfaceName) {
1426 // This is either an extra-route (or) a learned IP via subnet-route
1427 List<String> nhList = null;
1428 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1429 if (nextHopIp == null || nextHopIp.isEmpty()) {
1430 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1431 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1432 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1434 nhList = Collections.emptyList();
1436 nhList = Collections.singletonList(nextHopIp);
1441 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1442 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1443 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1444 // else use connected interface
1445 if (gwPort != null && gwPort.isSubnetIp()) {
1446 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1447 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1448 return Optional.of(gwPort.getMacAddress());
1450 return Optional.absent();
1454 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1455 final VpnInterface update) {
1456 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1457 update.getDpnId(), original.getVpnInstanceNames(),
1458 update.getVpnInstanceNames());
1459 final String vpnInterfaceName = update.getName();
1460 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1461 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1462 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1463 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1464 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1465 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1466 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1468 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1469 //handles switching between <internal VPN - external VPN>
1470 if (handleVpnSwapForVpnInterface(identifier, original, update)) {
1471 LOG.info("update: handled VPNInterface {} on dpn {} update"
1472 + "upon VPN swap from oldVpn(s) {} to newVpn(s) {}",
1473 original.getName(), dpnId,
1474 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1475 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1478 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1479 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1480 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1481 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1482 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1483 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1484 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName, () -> {
1485 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
1486 List<ListenableFuture<Void>> futures = new ArrayList<>();
1487 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(confTx -> {
1488 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx -> {
1489 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1490 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1491 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1492 update.getName(), newVpnName);
1493 //handle both addition and removal of adjacencies
1494 //currently, new adjacency may be an extra route
1495 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1496 if (!oldAdjs.equals(newAdjs)) {
1497 for (Adjacency adj : copyNewAdjs) {
1498 if (copyOldAdjs.contains(adj)) {
1499 copyOldAdjs.remove(adj);
1501 // add new adjacency - right now only extra route will hit this path
1502 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker,
1504 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1505 dpnId, operTx, confTx);
1507 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to"
1508 + " vpn interface {} on vpn {} dpnId {}",
1509 adj.getIpAddress(), adj.getNextHopIpList(),
1510 adj.getLabel(), adj.getSubnetId(), update.getName(),
1514 for (Adjacency adj : copyOldAdjs) {
1515 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker,
1517 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency
1518 && !adj.isPhysNetworkFunc()) {
1519 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1521 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1522 LogicalDatastoreType.OPERATIONAL, vpnInterfaceOpIdentifier);
1523 VpnInterfaceOpDataEntry vpnInterfaceOpDataEntry = optVpnInterface.get();
1524 long vpnId = VpnUtil.getVpnId(dataBroker, newVpnName);
1525 VpnUtil.removePrefixToInterfaceAdj(dataBroker, adj, vpnId,
1526 vpnInterfaceOpDataEntry, operTx);
1528 String vpnRd = VpnUtil.getVpnRd(dataBroker, newVpnName);
1529 LOG.debug("update: remove prefix {} from the FIB and BGP entry "
1530 + "for the Vpn-Rd {} ", adj.getIpAddress(), vpnRd);
1532 fibManager.removeFibEntry(vpnRd, adj.getIpAddress(), confTx);
1533 if (vpnRd != null && !vpnRd.equalsIgnoreCase(newVpnName)) {
1534 bgpManager.withdrawPrefix(vpnRd, adj.getIpAddress());
1537 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1541 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1542 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj
1543 .getNextHopIpList(),
1544 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1552 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1553 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1558 private boolean handleVpnSwapForVpnInterface(InstanceIdentifier<VpnInterface> identifier,
1559 VpnInterface original, VpnInterface update) {
1560 boolean isSwap = Boolean.FALSE;
1561 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1562 final String interfaceName = key.getName();
1563 List<String> oldVpnList = original.getVpnInstanceNames().stream()
1564 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1565 List<String> oldVpnListCopy = new ArrayList<>();
1566 oldVpnListCopy.addAll(oldVpnList);
1567 List<String> newVpnList = update.getVpnInstanceNames().stream()
1568 .map(VpnInstanceNames::getVpnName).collect(Collectors.toList());
1569 oldVpnList.removeAll(newVpnList);
1570 newVpnList.removeAll(oldVpnListCopy);
1571 if (!oldVpnList.isEmpty() || !newVpnList.isEmpty()) {
1572 for (String oldVpnName: oldVpnList) {
1573 isSwap = Boolean.TRUE;
1574 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} remove vpnName {}"
1575 + " running config-driven swap removal", interfaceName, oldVpnName);
1576 removeVpnInterfaceCall(identifier, original, oldVpnName, interfaceName);
1577 LOG.info("handleVpnSwapForVpnInterface: Processed Remove for update on VPNInterface {} upon VPN swap"
1578 + "from old vpn {} to newVpn(s) {}", interfaceName, oldVpnName, newVpnList);
1580 //Wait for previous interface bindings to be removed
1583 } catch (InterruptedException e) {
1586 for (String newVpnName: newVpnList) {
1587 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1588 isSwap = Boolean.TRUE;
1589 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1590 LOG.info("handleVpnSwapForVpnInterface: VPN Interface update event - intfName {} onto vpnName {}"
1591 + "running config-driven swap addition", interfaceName, newVpnName);
1592 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1593 final List<Adjacency> oldAdjs = (origAdjs != null && origAdjs.getAdjacency() != null)
1594 ? origAdjs.getAdjacency() : new ArrayList<>();
1595 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1596 final List<Adjacency> newAdjs = (updateAdjs != null && updateAdjs.getAdjacency() != null)
1597 ? updateAdjs.getAdjacency() : new ArrayList<>();
1599 addVpnInterfaceCall(identifier, update, oldAdjs, newAdjs, newVpnName);
1600 LOG.info("handleVpnSwapForVpnInterface: Processed Add for update on VPNInterface {}"
1601 + "from oldVpn(s) {} to newVpn {} upon VPN swap",
1602 interfaceName, oldVpnListCopy, newVpnName);
1609 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1610 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1611 synchronized (label.toString().intern()) {
1612 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1613 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1614 Optional<LabelRouteInfo> opResult = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
1615 if (opResult.isPresent()) {
1616 LabelRouteInfo labelRouteInfo =
1617 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1618 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, labelRouteInfo);
1621 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label, nextHopIpList);
1624 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1625 SubnetRoute route, String parentVpnRd, WriteTransaction writeConfigTxn) {
1627 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1628 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, parentVpnRd)
1629 .addAugmentation(SubnetRoute.class, route).build();
1630 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1631 InstanceIdentifierBuilder<VrfTables> idBuilder =
1632 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1633 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1634 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1635 if (writeConfigTxn != null) {
1636 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1638 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1640 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1641 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1644 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1645 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1646 WriteTransaction writeConfigTxn) {
1648 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1649 LogicalDatastoreType.OPERATIONAL, identifier);
1651 if (optVpnInterface.isPresent()) {
1652 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1653 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1654 String vpnName = currVpnIntf.getVpnInstanceName();
1655 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1656 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1657 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker,
1658 LogicalDatastoreType.OPERATIONAL, adjPath);
1659 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1660 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1661 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1662 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1663 List<Adjacency> adjacencies;
1664 if (optAdjacencies.isPresent()) {
1665 adjacencies = optAdjacencies.get().getAdjacency();
1667 // This code will be hit in case of first PNF adjacency
1668 adjacencies = new ArrayList<>();
1670 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1671 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1672 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1673 Adjacency operationalAdjacency = null;
1674 //Handling dual stack neutron port primary adjacency
1675 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency && !adj.isPhysNetworkFunc()) {
1676 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to existing interface {} for vpn {}", prefix,
1677 currVpnIntf.getName(), vpnName);
1678 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,
1679 currVpnIntf.getName());
1680 if (interfaceState != null) {
1681 processVpnInterfaceAdjacencies(dpnId, currVpnIntf.getLportTag().intValue(), vpnName, primaryRd,
1682 currVpnIntf.getName(),
1683 vpnId, writeConfigTxn, writeOperTxn, null, interfaceState);
1686 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()
1687 && adj.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1688 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1689 : RouteOrigin.STATIC;
1690 String nh = adj.getNextHopIpList().get(0);
1691 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1692 synchronized (vpnPrefixKey.intern()) {
1693 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1694 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1695 if (rdToAllocate.isPresent()) {
1696 input.setRd(rdToAllocate.get());
1697 operationalAdjacency = populator.createOperationalAdjacency(input);
1698 int label = operationalAdjacency.getLabel().intValue();
1699 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1700 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1701 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1702 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1703 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1704 vpnName, label, currVpnIntf.getName(), dpnId);
1706 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}", vpnName,
1710 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1711 // Keeping the MPLS check for now.
1712 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1713 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1714 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1715 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1716 vpnsToImportRoute.forEach(vpn -> {
1717 if (vpn.getVrfId() != null) {
1718 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1719 dataBroker, vpn.getVpnId(), vpnId, prefix,
1720 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1722 rds -> vpnManager.addExtraRoute(
1723 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1724 adj.getIpAddress(), nh, rds,
1725 currVpnIntf.getVpnInstanceName(),
1726 l3vni, RouteOrigin.SELF_IMPORTED,
1727 currVpnIntf.getName(), opAdjacency, encapType, writeConfigTxn));
1732 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1733 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1734 currVpnIntf.getName(), vpnName);
1736 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1739 LogicalDatastoreType.OPERATIONAL,
1740 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1741 adj.getSubnetId().getValue()), prefix),
1742 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1743 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1745 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1746 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */, 0 /*l3vni*/,
1747 null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1749 input.setRd(adj.getVrfId());
1751 if (operationalAdjacency == null) {
1752 operationalAdjacency = populator.createOperationalAdjacency(input);
1754 adjacencies.add(operationalAdjacency);
1755 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1756 VpnInterfaceOpDataEntry newVpnIntf =
1757 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1758 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1759 currVpnIntf.getGatewayMacAddress());
1761 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1765 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1766 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1767 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1770 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1771 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1772 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1773 LogicalDatastoreType.OPERATIONAL, identifier);
1775 if (optVpnInterface.isPresent()) {
1776 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1778 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1779 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1780 if (optAdjacencies.isPresent()) {
1781 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1783 if (!adjacencies.isEmpty()) {
1784 LOG.trace("delAdjFromVpnInterface: Adjacencies are {}", adjacencies);
1785 Iterator<Adjacency> adjIt = adjacencies.iterator();
1786 while (adjIt.hasNext()) {
1787 Adjacency adjElem = adjIt.next();
1788 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1789 String rd = adjElem.getVrfId();
1792 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1793 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1794 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1795 currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove(),
1796 currVpnIntf.getLportTag(), currVpnIntf.getGatewayMacAddress());
1798 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1799 if (adj.getNextHopIpList() != null) {
1800 for (String nh : adj.getNextHopIpList()) {
1801 deleteExtraRouteFromCurrentAndImportingVpns(
1802 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1803 currVpnIntf.getName(), writeConfigTxn);
1805 } else if (adj.isPhysNetworkFunc()) {
1806 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet {}",
1807 adj.getIpAddress(), adj.getSubnetId());
1808 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1816 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1817 dpnId, adj.getVrfId());
1819 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1820 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1825 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1826 String rd, String intfName, WriteTransaction writeConfigTxn) {
1827 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1828 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1829 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1830 String vpnRd = vpn.getVrfId();
1831 if (vpnRd != null) {
1832 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
1837 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1838 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1839 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1840 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1843 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1844 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1845 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1848 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1849 WriteTransaction writeOperTxn) {
1850 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1851 if (dpId.equals(BigInteger.ZERO)) {
1852 LOG.error("addToNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1853 + " association model", vpnInterfaceName, routerName);
1857 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1859 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1860 .OPERATIONAL, routerDpnListIdentifier);
1861 RouterInterfaces routerInterface =
1862 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1863 vpnInterfaceName).build();
1864 if (optionalRouterDpnList.isPresent()) {
1865 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1866 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1868 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1869 builder.setRouterId(routerName);
1870 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1871 builder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1872 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1873 getRouterId(routerName),
1874 builder.build(), true);
1878 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1879 WriteTransaction writeOperTxn) {
1880 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1881 if (dpId.equals(BigInteger.ZERO)) {
1882 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1883 + " dissociation model", vpnInterfaceName, routerName);
1887 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1888 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1889 .OPERATIONAL, routerDpnListIdentifier);
1890 if (optionalRouterDpnList.isPresent()) {
1891 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1892 RouterInterfaces routerInterface =
1893 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1894 vpnInterfaceName).build();
1896 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1897 if (routerInterfaces.isEmpty()) {
1898 if (writeOperTxn != null) {
1899 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1901 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1904 if (writeOperTxn != null) {
1905 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1906 RouterInterfaces.class,
1907 new RouterInterfacesKey(vpnInterfaceName)));
1909 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL,
1910 routerDpnListIdentifier.child(
1911 RouterInterfaces.class,
1912 new RouterInterfacesKey(vpnInterfaceName)));
1919 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1920 WriteTransaction writeOperTxn) {
1921 if (dpId.equals(BigInteger.ZERO)) {
1922 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1923 + " dissociation model", vpnInterfaceName, routerName);
1927 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1928 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1929 .OPERATIONAL, routerDpnListIdentifier);
1930 if (optionalRouterDpnList.isPresent()) {
1931 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1932 RouterInterfaces routerInterface =
1933 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1934 vpnInterfaceName).build();
1935 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1936 if (routerInterfaces.isEmpty()) {
1937 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1939 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1940 RouterInterfaces.class,
1941 new RouterInterfacesKey(vpnInterfaceName)));
1947 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
1948 WriteTransaction writeConfigTxn, String vpnName) {
1949 if (vpnInterface == null) {
1952 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
1954 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
1955 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
1958 for (Adjacency adj : adjs) {
1959 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1960 String primaryInterfaceIp = adj.getIpAddress();
1961 String macAddress = adj.getMacAddress();
1962 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1964 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1965 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
1967 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
1968 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
1969 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
1970 routerInt, label, writeConfigTxn);
1971 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
1972 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
1977 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
1978 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
1979 primaryRd, vpnName);
1982 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
1983 WriteTransaction writeConfigTxn, String vpnName) {
1984 Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
1985 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1987 List<Adjacency> adjsList = adjs.getAdjacency();
1988 for (Adjacency adj : adjsList) {
1989 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1990 String primaryInterfaceIp = adj.getIpAddress();
1991 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
1992 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
1993 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
1994 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
1999 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
2000 vpnInterface.getName(), rd);
2004 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
2005 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
2006 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
2007 vpnName, intefaceData.vpnInterface.getName());
2010 final VpnInterfaceKey key = intefaceData.identifier
2011 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
2012 final String interfaceName = key.getName();
2013 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
2014 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
2015 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
2016 intefaceData.identifier, vpnName);
2020 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
2021 VpnInterface vpnInterface, String vpnName) {
2022 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
2024 if (vpnInterfaces == null) {
2025 vpnInterfaces = new ConcurrentLinkedQueue<>();
2027 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2028 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2029 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2030 vpnInterface.getName(), vpnName);
2033 public boolean isVpnInstanceReady(String vpnInstanceName) {
2034 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnInstanceName);
2035 if (vpnRd == null) {
2038 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
2040 return vpnInstanceOpDataEntry != null;
2043 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2044 synchronized (vpnInstanceName.intern()) {
2045 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2046 unprocessedVpnInterfaces.get(vpnInstanceName);
2047 if (vpnInterfaces != null) {
2048 while (!vpnInterfaces.isEmpty()) {
2049 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2050 if (hasVpnInstanceCreatedSuccessfully) {
2051 processSavedInterface(savedInterface, vpnInstanceName);
2052 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2053 savedInterface.vpnInterface.getName(), vpnInstanceName);
2055 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2056 savedInterface.vpnInterface.getName(), vpnInstanceName);
2060 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2065 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2066 VpnInterface vpnInterface) {
2067 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2068 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2069 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2070 if (vpnInterfaces != null) {
2071 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2072 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2073 + "unprocessed list", vpnInterface.getName(),
2074 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2077 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2078 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2083 public void vpnInstanceIsReady(String vpnInstanceName) {
2084 processSavedInterfaces(vpnInstanceName, true);
2087 public void vpnInstanceFailed(String vpnInstanceName) {
2088 processSavedInterfaces(vpnInstanceName, false);
2091 private static class UnprocessedVpnInterfaceData {
2092 InstanceIdentifier<VpnInterface> identifier;
2093 VpnInterface vpnInterface;
2095 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2096 this.identifier = identifier;
2097 this.vpnInterface = vpnInterface;
2101 public int hashCode() {
2102 final int prime = 31;
2104 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2105 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2110 public boolean equals(Object obj) {
2117 if (getClass() != obj.getClass()) {
2120 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2121 if (identifier == null) {
2122 if (other.identifier != null) {
2125 } else if (!identifier.equals(other.identifier)) {
2128 if (vpnInterface == null) {
2129 if (other.vpnInterface != null) {
2132 } else if (!vpnInterface.equals(other.vpnInterface)) {
2139 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2140 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
2141 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
2142 if (vpnInstanceOpData == null) {
2145 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2146 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2149 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2150 vpnToDpnLists.forEach(vpnToDpnList -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2151 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2152 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2153 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = VpnUtil.read(dataBroker,
2154 LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2155 if (!vpnInterfaceOptional.isPresent()) {
2158 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2159 vpnInterface.getInterfaceName());
2160 if (configVpnAdjacencies == null) {
2161 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2164 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2165 .getAugmentation(AdjacenciesOp.class).getAdjacency();
2166 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2167 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2168 // in operational DS. These unprocessed adjacencies will be handled below.
2169 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2170 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2171 configVpnAdjacencies.stream()
2172 .filter(adjacency -> operationVpnAdjacencies.stream()
2173 .noneMatch(operationalAdjacency ->
2174 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2175 .forEach(adjacency -> {
2176 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2177 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName(),
2179 // TODO Deal with sequencing — the config tx must only submitted if the oper tx goes in
2180 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2181 List<ListenableFuture<Void>> futures = new ArrayList<>();
2182 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(operTx -> futures.add(
2183 txRunner.callWithNewWriteOnlyTransactionAndSubmit(
2184 confTx -> addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd,
2185 adjacency, vpnInterfaceOptional.get().getDpnId(), confTx,
2189 return Collections.emptyList();
2196 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2197 private final String interfaceName;
2198 private final boolean add;
2199 private final String txnDestination;
2201 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2202 this.interfaceName = interfaceName;
2204 this.txnDestination = transactionDest;
2208 public void onSuccess(Void voidObj) {
2210 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2211 interfaceName, txnDestination);
2213 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2218 public void onFailure(Throwable throwable) {
2220 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}",
2221 interfaceName, txnDestination, throwable);
2223 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed", interfaceName, throwable);
2224 VpnUtil.unsetScheduledToRemoveForVpnInterface(txRunner, interfaceName);