2 * Copyright (c) 2016 - 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.vpnmanager;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Iterators;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
17 import java.math.BigInteger;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Iterator;
21 import java.util.List;
23 import java.util.Objects;
24 import java.util.concurrent.BlockingQueue;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentLinkedQueue;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.Executors;
29 import java.util.concurrent.LinkedBlockingQueue;
30 import java.util.concurrent.ScheduledExecutorService;
31 import java.util.concurrent.TimeUnit;
32 import java.util.function.Consumer;
33 import java.util.function.Predicate;
34 import java.util.stream.Collectors;
35 import javax.annotation.PostConstruct;
36 import javax.annotation.PreDestroy;
37 import javax.inject.Inject;
38 import javax.inject.Singleton;
39 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
40 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
41 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
42 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
43 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
44 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
45 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
46 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
47 import org.opendaylight.genius.mdsalutil.MDSALUtil;
48 import org.opendaylight.genius.mdsalutil.NwConstants;
49 import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
50 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
51 import org.opendaylight.infrautils.caches.CacheProvider;
52 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
53 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
54 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
55 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
56 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
57 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
58 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
59 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
60 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
61 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderHandler;
62 import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput;
63 import org.opendaylight.netvirt.vpnmanager.populator.intfc.VpnPopulator;
64 import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
115 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
116 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
117 import org.slf4j.Logger;
118 import org.slf4j.LoggerFactory;
121 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager> {
123 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
124 private static final int VPN_INF_UPDATE_TIMER_TASK_DELAY = 1000;
125 private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
126 private static final short DJC_MAX_RETRIES = 3;
128 private final DataBroker dataBroker;
129 private final ManagedNewTransactionRunner txRunner;
130 private final IBgpManager bgpManager;
131 private final IFibManager fibManager;
132 private final IMdsalApiManager mdsalManager;
133 private final IdManagerService idManager;
134 private final OdlInterfaceRpcService ifaceMgrRpcService;
135 private final VpnFootprintService vpnFootprintService;
136 private final IInterfaceManager interfaceManager;
137 private final IVpnManager vpnManager;
138 private final ArpResponderHandler arpResponderHandler;
139 private final JobCoordinator jobCoordinator;
141 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
143 private final BlockingQueue<UpdateData> vpnInterfacesUpdateQueue = new LinkedBlockingQueue<>();
144 private final ScheduledExecutorService vpnInfUpdateTaskExecutor = Executors.newScheduledThreadPool(1);
146 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
147 new ConcurrentHashMap<>();
149 private final DataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
152 public VpnInterfaceManager(final DataBroker dataBroker,
153 final IBgpManager bgpManager,
154 final IdManagerService idManager,
155 final IMdsalApiManager mdsalManager,
156 final IFibManager fibManager,
157 final OdlInterfaceRpcService ifaceMgrRpcService,
158 final VpnFootprintService vpnFootprintService,
159 final IInterfaceManager interfaceManager,
160 final IVpnManager vpnManager,
161 final ArpResponderHandler arpResponderHandler,
162 final JobCoordinator jobCoordinator,
163 final CacheProvider cacheProvider) {
164 super(VpnInterface.class, VpnInterfaceManager.class);
166 this.dataBroker = dataBroker;
167 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
168 this.bgpManager = bgpManager;
169 this.idManager = idManager;
170 this.mdsalManager = mdsalManager;
171 this.fibManager = fibManager;
172 this.ifaceMgrRpcService = ifaceMgrRpcService;
173 this.vpnFootprintService = vpnFootprintService;
174 this.interfaceManager = interfaceManager;
175 this.vpnManager = vpnManager;
176 this.arpResponderHandler = arpResponderHandler;
177 this.jobCoordinator = jobCoordinator;
178 vpnInfUpdateTaskExecutor.scheduleWithFixedDelay(new VpnInterfaceUpdateTimerTask(),
179 0, VPN_INF_UPDATE_TIMER_TASK_DELAY, TIME_UNIT);
181 vpnInstanceOpDataEntryCache = new DataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
182 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
183 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
186 public Runnable isNotifyTaskQueued(String intfName) {
187 return vpnIntfMap.remove(intfName);
191 public void start() {
192 LOG.info("{} start", getClass().getSimpleName());
193 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
198 public void close() {
200 vpnInfUpdateTaskExecutor.shutdown();
201 vpnInstanceOpDataEntryCache.close();
205 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
206 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
210 protected VpnInterfaceManager getDataTreeChangeListener() {
211 return VpnInterfaceManager.this;
215 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
216 LOG.info("add: intfName {} onto vpnName {}",
217 vpnInterface.getName(),
218 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
219 addVpnInterface(identifier, vpnInterface, null, null);
222 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
223 final VpnInterface vpnInterface, String vpnName) {
224 synchronized (vpnName.intern()) {
225 if (isVpnInstanceReady(vpnName)) {
228 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
233 // TODO Clean up the exception handling
234 @SuppressWarnings("checkstyle:IllegalCatch")
235 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
236 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
237 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
238 String vpnName = vpnInterfaceVpnInstance.getVpnName();
239 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
243 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
244 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
245 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
246 final String interfaceName = key.getName();
248 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
249 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
250 vpnName, vpnInterface.getName());
253 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
254 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
255 List<Adjacency> copyOldAdjs = null;
256 if (oldAdjs != null) {
257 copyOldAdjs = new ArrayList<>();
258 copyOldAdjs.addAll(oldAdjs);
260 List<Adjacency> copyNewAdjs = null;
261 if (newAdjs != null) {
262 copyNewAdjs = new ArrayList<>();
263 copyNewAdjs.addAll(newAdjs);
265 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
268 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
269 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
270 final List<Adjacency> newAdjs,
271 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
272 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
273 final String interfaceName = key.getName();
274 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
275 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
276 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
277 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
278 if (interfaceState != null) {
280 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
281 final int ifIndex = interfaceState.getIfIndex();
282 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName + vpnName, () -> {
283 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
284 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
285 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
286 LOG.info("addVpnInterface: VPN Interface add event - intfName {} vpnName {} on dpn {}" ,
287 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
288 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false, writeConfigTxn,
289 writeOperTxn, writeInvTxn, interfaceState, vpnName);
290 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
291 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
292 + " Update for swapping VPN {} case.", interfaceName, vpnName);
293 if (newAdjs != null) {
294 for (Adjacency adj : newAdjs) {
295 if (oldAdjs.contains(adj)) {
298 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
300 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd,
301 adj, dpnId, writeOperTxn, writeConfigTxn);
306 for (Adjacency adj : oldAdjs) {
307 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
309 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
310 writeOperTxn, writeConfigTxn);
314 ListenableFuture<Void> operFuture = writeOperTxn.submit();
317 } catch (ExecutionException e) {
318 LOG.error("addVpnInterface: Exception encountered while submitting operational future for"
319 + " addVpnInterface {} on vpn {}: {}", vpnInterface.getName(), vpnName, e);
322 List<ListenableFuture<Void>> futures = new ArrayList<>();
323 ListenableFuture<Void> configFuture = writeConfigTxn.submit();
324 futures.add(configFuture);
325 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"));
326 futures.add(writeInvTxn.submit());
327 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
328 + " processed successfully", interfaceName, vpnName, dpnId);
331 } catch (NumberFormatException | IllegalStateException e) {
332 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
333 + "interface {}. Interface addition on vpn {} failed", interfaceName,
337 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
338 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName() + vpnName,
340 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
341 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
342 writeConfigTxn, vpnName);
343 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
344 vpnName, vpnInterface.getDpnId());
345 ListenableFuture<Void> futures = writeConfigTxn.submit();
346 String errorText = "addVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
347 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
348 ListenableFutures.addErrorLogging(futures, LOG, errorText);
349 return Collections.singletonList(futures);
352 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
353 + " is not available", interfaceName, vpnName);
356 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
357 + " as vpn is pending delete", interfaceName, vpnName,
358 vpnInterface.getDpnId());
362 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
363 // see comments below.
364 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
365 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
366 final int lportTag, boolean isInterfaceUp,
367 WriteTransaction writeConfigTxn,
368 WriteTransaction writeOperTxn,
369 WriteTransaction writeInvTxn,
370 Interface interfaceState,
371 final String vpnName) {
372 final String interfaceName = vpnInterface.getName();
373 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
374 interfaceName, vpnName);
375 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
376 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
377 if (!isInterfaceUp) {
378 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
379 interfaceName, dpId, vpnName);
380 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
381 if (vpnId == VpnConstants.INVALID_ID) {
382 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
383 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
388 boolean waitForVpnInterfaceOpRemoval = false;
389 if (opVpnInterface != null && !opVpnInterface.isScheduledForRemove()) {
390 String opVpnName = opVpnInterface.getVpnInstanceName();
391 String primaryInterfaceIp = null;
392 if (opVpnName.equals(vpnName)) {
393 // Please check if the primary VRF Entry does not exist for VPNInterface
394 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
396 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
397 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
399 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
400 + " for this vpn interface could not be obtained", interfaceName, dpId,
404 for (Adjacency adj : adjs) {
405 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
406 primaryInterfaceIp = adj.getIpAddress();
410 if (primaryInterfaceIp == null) {
411 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
412 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
416 // Get the rd of the vpn instance
417 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, primaryRd, primaryInterfaceIp);
419 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
420 + " bailing out from here.", interfaceName, dpId, vpnName);
423 waitForVpnInterfaceOpRemoval = true;
425 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
426 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
429 if (!waitForVpnInterfaceOpRemoval) {
430 // Add the VPNInterface and quit
431 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
432 null/*ipAddressSourceValuePair*/,
434 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
435 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
436 if (!isBgpVpnInternetVpn) {
437 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false /*isTunnelInterface*/,
440 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
442 if (interfaceManager.isExternalInterface(interfaceName)) {
443 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
444 NwConstants.ADD_FLOW);
449 // FIB didn't get a chance yet to clean up this VPNInterface
450 // Let us give it a chance here !
451 LOG.info("processVpnInterfaceUp: Trying to add VPN Interface {} on dpn {} for vpn {},"
452 + " but waiting for FIB to clean up! ", interfaceName, dpId, vpnName);
454 Runnable notifyTask = new VpnNotifyTask();
455 synchronized (notifyTask) {
456 // Per FB's "Unconditional wait" violation, the code should really verify that the condition it
457 // intends to wait for is not already satisfied before calling wait. However the VpnNotifyTask is
458 // published here while holding the lock on it so this path will hit the wait before notify can be
460 vpnIntfMap.put(interfaceName, notifyTask);
462 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
463 } catch (InterruptedException e) {
468 vpnIntfMap.remove(interfaceName);
471 if (opVpnInterface != null) {
472 LOG.warn("processVpnInterfaceUp: VPN Interface {} removal on dpn {} for vpn {}"
473 + " by FIB did not complete on time," + " bailing addition ...", interfaceName,
475 VpnUtil.unsetScheduledToRemoveForVpnInterface(dataBroker, interfaceName);
478 // VPNInterface got removed, proceed with Add
479 LOG.info("processVpnInterfaceUp: Continuing to plumb vpn interface {} onto dpn {} for vpn {}",
480 interfaceName, dpId, vpnName);
481 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
482 null/*ipAddressSourceValuePair*/,
484 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
485 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
486 if (!isBgpVpnInternetVpn) {
487 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false/*isTunnelInterface*/, jobCoordinator);
489 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
490 + " FIB to clean up", interfaceName, dpId, vpnName);
491 if (interfaceManager.isExternalInterface(interfaceName)) {
492 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId,
493 lportTag, writeInvTxn, NwConstants.ADD_FLOW);
496 // Interface is retained in the DPN, but its Link Up.
497 // Advertise prefixes again for this interface to BGP
498 InstanceIdentifier<VpnInterface> identifier =
499 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName());
500 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
501 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
502 advertiseAdjacenciesForVpnToBgp(primaryRd, dpId, vpnInterfaceOpIdentifier, vpnName, interfaceName);
503 // Perform similar operation as interface add event for extraroutes.
504 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
505 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
506 if (!optAdjacencies.isPresent()) {
507 LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
510 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
511 for (Adjacency adjacency : adjacencies) {
512 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
515 // if BGPVPN Internet, filter only IPv6 Adjacencies
516 if (isBgpVpnInternetVpn && !VpnUtil.isAdjacencyEligibleToVpnInternet(
517 dataBroker, adjacency)) {
520 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
521 dpId, writeOperTxn, writeConfigTxn);
526 private void processExternalVpnInterface(String interfaceName, String vpnName, long vpnId, BigInteger dpId,
527 int lportTag, WriteTransaction writeInvTxn, int addOrRemove) {
530 // vpn instance of ext-net interface is the network-id
531 extNetworkId = new Uuid(vpnName);
532 } catch (IllegalArgumentException e) {
533 LOG.error("processExternalVpnInterface: VPN instance {} is not Uuid. Processing external vpn interface {}"
534 + " on dpn {} failed", vpnName, interfaceName, dpId);
538 List<Uuid> routerIds = VpnUtil.getExternalNetworkRouterIds(dataBroker, extNetworkId);
539 if (routerIds == null || routerIds.isEmpty()) {
540 LOG.info("processExternalVpnInterface: No router is associated with {}."
541 + " Bailing out of processing external vpn interface {} on dpn {} for vpn {}",
542 extNetworkId.getValue(), interfaceName, dpId, vpnName);
546 LOG.info("processExternalVpnInterface: Router-ids {} associated with exernal vpn-interface {} on dpn {}"
547 + " for vpn {}", routerIds, interfaceName, dpId, vpnName);
548 for (Uuid routerId : routerIds) {
549 String routerName = routerId.getValue();
550 BigInteger primarySwitch = VpnUtil.getPrimarySwitchForRouter(dataBroker, routerName);
551 if (Objects.equals(primarySwitch, dpId)) {
552 Routers router = VpnUtil.getExternalRouter(dataBroker, routerName);
553 if (router != null) {
554 if (addOrRemove == NwConstants.ADD_FLOW) {
555 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
556 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
557 dpId, interfaceName, lportTag, writeInvTxn);
559 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
560 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
561 dpId, interfaceName, lportTag);
564 LOG.error("processExternalVpnInterface: No external-router found for router-id {}. Bailing out of"
565 + " processing external vpn-interface {} on dpn {} for vpn {}", routerName,
566 interfaceName, dpId, vpnName);
572 // TODO Clean up the exception handling
573 @SuppressWarnings("checkstyle:IllegalCatch")
574 private void advertiseAdjacenciesForVpnToBgp(final String rd, BigInteger dpnId,
575 final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
576 String vpnName, String interfaceName) {
578 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} on dpn {} in vpn {}",
579 interfaceName, dpnId, vpnName);
582 if (rd.equals(vpnName)) {
583 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} on dpn {}"
584 + " as it is in internal vpn{} with rd {}", interfaceName, dpnId, vpnName, rd);
588 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} on dpn {} in vpn {} with rd {} ",
589 interfaceName, dpnId, vpnName, rd);
591 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
592 if (nextHopIp == null) {
593 LOG.error("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} on dpn {} is null,"
594 + " returning from advertising route with rd {} vpn {} to bgp", interfaceName, dpnId,
600 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
601 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
602 if (adjacencies.isPresent()) {
603 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
605 if (!nextHops.isEmpty()) {
606 LOG.debug("advertiseAdjacenciesForVpnToBgp: NextHops are {} for interface {} on dpn {} for vpn {}"
607 + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
608 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
609 long l3vni = vpnInstanceOpData.getL3vni();
610 VrfEntry.EncapType encapType = VpnUtil.isL3VpnOverVxLan(l3vni)
611 ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
612 for (Adjacency nextHop : nextHops) {
613 if (nextHop.getAdjacencyType() == AdjacencyType.ExtraRoute) {
616 String gatewayMac = null;
618 if (VpnUtil.isL3VpnOverVxLan(l3vni)) {
619 final VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
620 vpnInstanceOpData.getVpnInstanceName(), nextHop.getIpAddress());
621 gatewayMac = arpResponderHandler.getGatewayMacAddressForInterface(gwPort, interfaceName).get();
623 label = nextHop.getLabel();
626 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Adding Fib Entry rd {} prefix {}"
627 + " nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
628 bgpManager.advertisePrefix(rd, nextHop.getMacAddress(), nextHop.getIpAddress(), nextHopIp,
629 encapType, (int)label, l3vni, 0 /*l2vni*/,
631 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Added Fib Entry rd {} prefix {}"
632 + " nexthop {} label {} for interface {} on dpn {} for vpn {}", rd,
633 nextHop.getIpAddress(), nextHopIp, label, interfaceName, dpnId, vpnName);
634 } catch (Exception e) {
635 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to advertise prefix {} in vpn {} with rd {}"
636 + " for interface {} on dpn {}", nextHop.getIpAddress(),
637 vpnName, rd, interfaceName, dpnId, e);
644 // TODO Clean up the exception handling
645 @SuppressWarnings("checkstyle:IllegalCatch")
646 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
647 String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
649 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
650 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
652 String rd = VpnUtil.getVpnRd(dataBroker, interfaceName);
654 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
655 interfaceName, vpnName);
658 if (rd.equals(vpnName)) {
660 "withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in "
661 + "internal vpn{} with rd {}", interfaceName, vpnName, rd);
665 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", interfaceName,
667 if (adjacencies.isPresent()) {
668 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
670 if (!nextHops.isEmpty()) {
671 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
672 nextHops, interfaceName, vpnName, rd);
673 for (Adjacency nextHop : nextHops) {
675 if (nextHop.getAdjacencyType() != AdjacencyType.ExtraRoute) {
676 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removing Fib Entry rd {}"
677 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
678 interfaceName, vpnName);
679 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
680 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removed Fib Entry rd {}"
681 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
682 interfaceName, vpnName);
684 // Perform similar operation as interface delete event for extraroutes.
685 String allocatedRd = nextHop.getVrfId();
686 for (String nh : nextHop.getNextHopIpList()) {
687 deleteExtraRouteFromCurrentAndImportingVpns(
688 vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn);
691 } catch (Exception e) {
692 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
693 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
700 @SuppressWarnings("checkstyle:IllegalCatch")
701 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
702 String primaryRd, String interfaceName, final long vpnId,
703 WriteTransaction writeConfigTxn,
704 WriteTransaction writeOperTxn,
705 final WriteTransaction writeInvTxn,
706 Interface interfaceState) {
707 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
709 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
710 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
711 if (!adjacencies.isPresent()) {
712 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
713 null/*gwMac*/, writeOperTxn);
717 // Get the rd of the vpn instance
718 String nextHopIp = null;
720 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
721 } catch (Exception e) {
722 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
723 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
725 List<String> nhList = new ArrayList<>();
726 if (nextHopIp != null) {
727 nhList.add(nextHopIp);
728 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
729 interfaceName, dpnId, vpnName, nhList);
731 Optional<String> gwMac = Optional.absent();
732 String vpnInterfaceSubnetGwMacAddress = null;
733 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
734 Long l3vni = vpnInstanceOpData.getL3vni();
735 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
736 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
737 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
738 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
739 List<Adjacency> value = new ArrayList<>();
740 for (Adjacency nextHop : nextHops) {
741 String rd = primaryRd;
742 Subnetmap sn = VpnUtil.getSubnetmapFromItsUuid(dataBroker, nextHop.getSubnetId());
743 if (!VpnUtil.isSubnetPartOfVpn(sn, vpnName)) {
744 String prefix = nextHop.getIpAddress() == null ? "null" :
745 VpnUtil.getIpPrefix(nextHop.getIpAddress());
746 LOG.debug("processVpnInterfaceAdjacencies: Not Adding prefix {} to interface {}"
747 + " as the subnet is not part of vpn {}", prefix, interfaceName, vpnName);
750 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
751 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
752 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
753 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
754 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
755 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
757 LogicalDatastoreType.OPERATIONAL,
758 VpnUtil.getPrefixToInterfaceIdentifier(
759 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
760 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
762 final Uuid subnetId = nextHop.getSubnetId();
763 final Optional<String> gatewayIp = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
764 if (gatewayIp.isPresent()) {
765 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp.get());
766 if (gwMac.isPresent()) {
767 // A valid mac-address is available for this subnet-gateway-ip
768 // Use this for programming ARP_RESPONDER table here. And save this
769 // info into vpnInterface operational, so it can used in VrfEntryProcessor
770 // to populate L3_GW_MAC_TABLE there.
771 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
772 gatewayIp.get(), gwMac.get());
773 vpnInterfaceSubnetGwMacAddress = gwMac.get();
775 // A valid mac-address is not available for this subnet-gateway-ip
776 // Use the connected-mac-address to configure ARP_RESPONDER Table.
777 // Save this connected-mac-address as gateway-mac-address for the
778 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
779 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
780 if (gwMac.isPresent()) {
781 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
782 vpnId, writeInvTxn, NwConstants.ADD_FLOW, gwMac.get());
783 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
784 gatewayIp.get(), gwMac.get());
786 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
787 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
789 interfaceName, vpnName, gatewayIp.get());
793 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
794 + "cannot create ARP responder flow for interface name {}, vpnName {}",
795 subnetId, interfaceName, vpnName);
796 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
798 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
799 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
801 //Extra route adjacency
802 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
803 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
804 synchronized (vpnPrefixKey.intern()) {
805 java.util.Optional<String> rdToAllocate = VpnUtil
806 .allocateRdForExtraRouteAndUpdateUsedRdsMap(dataBroker, vpnId, null,
807 prefix, vpnName, nextHop.getNextHopIpList().get(0), dpnId);
808 if (rdToAllocate.isPresent()) {
809 rd = rdToAllocate.get();
810 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
813 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
817 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
818 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
819 interfaceName, dpnId);
821 // Please note that primary adjacency will use a subnet-gateway-mac-address that
822 // can be different from the gateway-mac-address within the VRFEntry as the
823 // gateway-mac-address is a superset.
824 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
825 : RouteOrigin.STATIC;
826 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
827 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
828 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
829 Adjacency operationalAdjacency = null;
831 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
832 } catch (NullPointerException e) {
833 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
834 input, e.getMessage());
837 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
838 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
839 vpnName, l3vni, origin,
840 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
842 value.add(operationalAdjacency);
845 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
846 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
847 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
849 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
850 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
851 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
853 for (Adjacency nextHop : aug.getAdjacency()) {
854 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
855 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
856 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
857 : RouteOrigin.STATIC;
858 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
859 registeredPopulator.populateFib(input, writeConfigTxn);
864 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
865 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
866 VpnInterfaceOpDataEntry opInterface =
867 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, Boolean.FALSE, lportTag, gwMac);
868 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
869 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
870 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
871 WriteTransaction.CREATE_MISSING_PARENTS);
872 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
873 interfaceName, dpnId, vpnName);
876 // TODO Clean up the exception handling
877 @SuppressWarnings("checkstyle:IllegalCatch")
878 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
879 StateTunnelList stateTunnelList,
880 WriteTransaction writeConfigTxn,
881 WriteTransaction writeOperTxn) {
883 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
884 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
885 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
886 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
887 if (adjList.isEmpty()) {
888 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
889 vpnInterface, srcDpnId);
892 String prefix = null;
894 List<Adjacency> value = new ArrayList<>();
895 boolean isNextHopAddReqd = false;
896 String vpnName = vpnInterface.getVpnInstanceName();
897 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
898 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
899 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
900 vpnInterface.getName(), vpnInterface.getDpnId(),
901 vpnInterface.getVpnInstanceName(), adjList);
902 for (Adjacency adj : adjList) {
903 String rd = adj.getVrfId();
904 rd = rd != null ? rd : vpnName;
905 prefix = adj.getIpAddress();
906 label = adj.getLabel();
907 List<String> nhList = Collections.singletonList(srcTepIp);
908 List<String> nextHopList = adj.getNextHopIpList();
909 // If TEP is added , update the nexthop of primary adjacency.
910 // Secondary adj nexthop is already pointing to primary adj IP address.
911 if (nextHopList != null && !nextHopList.isEmpty() && nextHopList.get(0).equalsIgnoreCase(srcTepIp)) {
912 /* everything right already */
914 isNextHopAddReqd = true;
917 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
918 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
920 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
921 if (!vrfEntryOptional.isPresent()) {
924 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
925 if (!nhList.contains(srcTepIp)) {
926 nhList.add(srcTepIp);
927 isNextHopAddReqd = true;
932 if (isNextHopAddReqd) {
933 updateLabelMapper(label, nhList);
934 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
935 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
936 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
937 // Update the VRF entry with nextHop
938 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
939 label, true, writeConfigTxn);
941 //Get the list of VPN's importing this route(prefix) .
942 // Then update the VRF entry with nhList
943 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
944 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
945 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
946 String vpnRd = vpn.getVrfId();
948 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
949 srcTepIp, label, true, writeConfigTxn);
950 LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
951 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
952 vpnInterface.getName(), srcDpnId, vpnName,
953 vpn.getVpnInstanceName(), vpnRd);
956 // Advertise the prefix to BGP only for external vpn
957 // since there is a nexthop change.
959 if (!rd.equalsIgnoreCase(vpnName)) {
960 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, nhList,
961 VrfEntry.EncapType.Mplsgre, (int)label, 0 /*evi*/, 0 /*l2vni*/,
962 null /*gatewayMacAddress*/);
964 LOG.info("updateVpnInterfaceOnTepAdd: Advertised rd {} prefix {} nhList {} label {}"
965 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label, vpnInterface.getName(),
967 } catch (Exception ex) {
968 LOG.error("updateVpnInterfaceOnTepAdd: Exception when advertising prefix {} nh {} label {}"
969 + " on rd {} for interface {} on dpn {} vpn {} as {}", prefix, nhList, label, rd,
970 vpnInterface.getName(), srcDpnId,
975 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
976 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
977 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
978 .addAugmentation(AdjacenciesOp.class, aug).build();
979 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
980 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
981 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
982 WriteTransaction.CREATE_MISSING_PARENTS);
983 LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
984 vpnInterface.getName(), srcDpnId, vpnName);
988 // TODO Clean up the exception handling
989 @SuppressWarnings("checkstyle:IllegalCatch")
990 public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
991 StateTunnelList stateTunnelList,
992 WriteTransaction writeConfigTxn,
993 WriteTransaction writeOperTxn) {
995 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
996 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
997 String prefix = null;
999 boolean isNextHopRemoveReqd = false;
1000 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
1001 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
1002 String vpnName = vpnInterface.getVpnInstanceName();
1003 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1004 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1005 if (adjList != null) {
1006 List<Adjacency> value = new ArrayList<>();
1007 LOG.info("updateVpnInterfaceOnTepDelete: AdjacencyList for interface {} on dpn {} vpn {} is {}",
1008 vpnInterface.getName(), vpnInterface.getDpnId(),
1009 vpnInterface.getVpnInstanceName(), adjList);
1010 for (Adjacency adj : adjList) {
1011 List<String> nhList = new ArrayList<>();
1012 String rd = adj.getVrfId();
1013 rd = rd != null ? rd : vpnName;
1014 prefix = adj.getIpAddress();
1015 List<String> nextHopList = adj.getNextHopIpList();
1016 label = adj.getLabel();
1017 if (nextHopList != null && !nextHopList.isEmpty()) {
1018 isNextHopRemoveReqd = true;
1020 // If TEP is deleted , remove the nexthop from primary adjacency.
1021 // Secondary adj nexthop will continue to point to primary adj IP address.
1022 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1023 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
1025 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
1026 if (!vrfEntryOptional.isPresent()) {
1029 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
1030 if (nhList.contains(srcTepIp)) {
1031 nhList.remove(srcTepIp);
1032 isNextHopRemoveReqd = true;
1037 if (isNextHopRemoveReqd) {
1038 updateLabelMapper(label, nhList);
1039 LOG.info("updateVpnInterfaceOnTepDelete: Updated label mapper : label {} dpn {} prefix {}"
1040 + " nexthoplist {} vpn {} vpnid {} rd {} interface {}", label, srcDpnId,
1041 prefix, nhList, vpnName,
1042 vpnId, rd, vpnInterface.getName());
1043 // Update the VRF entry with removed nextHop
1044 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
1045 label, false, writeConfigTxn);
1047 //Get the list of VPN's importing this route(prefix) .
1048 // Then update the VRF entry with nhList
1049 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1050 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1051 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1052 String vpnRd = vpn.getVrfId();
1053 if (vpnRd != null) {
1054 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1055 srcTepIp, label, false, writeConfigTxn);
1056 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1057 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1058 nhList, label, vpnInterface.getName(), srcDpnId,
1060 vpn.getVpnInstanceName(), vpnRd);
1064 // Withdraw prefix from BGP only for external vpn.
1066 if (!rd.equalsIgnoreCase(vpnName)) {
1067 bgpManager.withdrawPrefix(rd, prefix);
1069 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1070 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1071 vpnInterface.getName(), srcDpnId,
1073 } catch (Exception ex) {
1074 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1075 + " on rd {} for interface {} on dpn {} vpn {} as {}", prefix, nhList, label, rd,
1076 vpnInterface.getName(), srcDpnId,
1081 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1082 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1083 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1084 .addAugmentation(AdjacenciesOp.class, aug).build();
1085 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1086 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1087 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1088 WriteTransaction.CREATE_MISSING_PARENTS);
1089 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1090 vpnInterface.getName(), srcDpnId, vpnName);
1094 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1095 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1097 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1098 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
1099 if (vpnInstanceOpDataEntry == null) {
1100 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1101 + " to check for vpns exporting the routes", vpnName);
1102 return vpnsToExportRoute;
1105 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1106 if (input.getVpnInstanceName() == null) {
1107 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1111 return !input.getVpnInstanceName().equals(vpnName);
1114 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1115 Iterable<String> commonRTs =
1116 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1117 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1118 return Iterators.size(commonRTs.iterator()) > 0;
1122 VpnUtil.getAllVpnInstanceOpData(dataBroker).stream().filter(excludeVpn).filter(matchRTs).collect(
1123 Collectors.toList());
1124 return vpnsToExportRoute;
1127 // TODO Clean up the exception handling
1128 @SuppressWarnings("checkstyle:IllegalCatch")
1129 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1130 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1131 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1132 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getVrfId());
1133 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1134 if (vrfEntries != null) {
1135 for (VrfEntry vrfEntry : vrfEntries) {
1137 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1138 RouteOrigin.value(vrfEntry.getOrigin()))) {
1139 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1140 + " is not a controller managed non intervpn link route. Ignoring.",
1141 vpn.getVrfId(), vrfEntry.getDestPrefix());
1144 String prefix = vrfEntry.getDestPrefix();
1145 String gwMac = vrfEntry.getGatewayMacAddress();
1146 vrfEntry.getRoutePaths().forEach(routePath -> {
1147 String nh = routePath.getNexthopAddress();
1148 int label = routePath.getLabel().intValue();
1149 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1150 vrfEntry.getOrigin()))) {
1151 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1152 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1154 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1155 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1156 0 /*l3vni*/, gwMac, null /*parentVpnRd*/, RouteOrigin.SELF_IMPORTED,
1159 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} prefix {}"
1160 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1162 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1163 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, writeConfigTxn);
1166 } catch (RuntimeException e) {
1167 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1168 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1169 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1172 writeConfigTxn.submit();
1174 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1175 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1180 @SuppressWarnings("checkstyle:IllegalCatch")
1182 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1183 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1184 final String interfaceName = key.getName();
1185 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1186 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1187 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1191 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1192 final VpnInterface vpnInterface, final String vpnName,
1193 final String interfaceName) {
1194 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1195 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName() + vpnName, () -> {
1196 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1197 deleteFibEntryForRouterInterface(vpnInterface, writeConfigTxn, vpnName);
1198 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1199 ListenableFuture<Void> futures = writeConfigTxn.submit();
1200 String errorText = "removeVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
1201 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
1202 ListenableFutures.addErrorLogging(futures, LOG, errorText);
1203 return Collections.singletonList(futures);
1204 }, DJC_MAX_RETRIES);
1206 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1207 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1211 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1212 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1213 final VpnInterface vpnInterface, final String vpnName,
1214 final String interfaceName, final Interface interfaceState) {
1215 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1216 vpnName, vpnInterface.getDpnId());
1217 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1218 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName + vpnName,
1220 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1221 ListenableFuture<Void> configFuture = txRunner
1222 .callWithNewWriteOnlyTransactionAndSubmit(writeConfigTxn -> {
1223 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeOperTxn -> {
1224 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1225 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1226 interfaceName, vpnName);
1227 BigInteger dpId = BigInteger.ZERO;
1229 String gwMacAddress = null;
1230 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1231 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1232 final Optional<VpnInterfaceOpDataEntry> optVpnInterface =
1233 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1234 if (interfaceState != null) {
1236 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1237 } catch (NumberFormatException | IllegalStateException e) {
1238 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1239 + " data store for interface {} on dpn {} for vpn {} Fetching"
1240 + " from vpn interface op data store. ", interfaceName,
1241 vpnInterface.getDpnId(), vpnName, e);
1242 dpId = BigInteger.ZERO;
1244 ifIndex = interfaceState.getIfIndex();
1245 gwMacAddress = interfaceState.getPhysAddress().getValue();
1247 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1248 + " from vpn interface op.", interfaceName);
1249 if (optVpnInterface.isPresent()) {
1250 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1251 dpId = vpnOpInterface.getDpnId();
1252 ifIndex = vpnOpInterface.getLportTag().intValue();
1253 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1255 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1256 + " as interfaceState and vpn interface op is not"
1257 + " available", interfaceName, vpnName);
1261 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1262 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1263 writeConfigTxn, writeOperTxn, writeInvTxn);
1265 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1267 interfaceName, vpnInterface.getDpnId(), vpnName);
1271 futures.add(configFuture);
1272 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1274 }, DJC_MAX_RETRIES);
1277 protected void processVpnInterfaceDown(BigInteger dpId,
1278 String interfaceName,
1281 VpnInterfaceOpDataEntry vpnOpInterface,
1282 boolean isInterfaceStateDown,
1283 WriteTransaction writeConfigTxn,
1284 WriteTransaction writeOperTxn,
1285 WriteTransaction writeInvTxn) {
1286 if (vpnOpInterface == null) {
1287 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1288 + " as it is not available in operational data store", interfaceName, dpId);
1291 final String vpnName = vpnOpInterface.getVpnInstanceName();
1292 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1293 interfaceName, vpnName);
1294 if (!isInterfaceStateDown) {
1295 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1296 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1298 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1299 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1300 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1301 if (interfaceManager.isExternalInterface(interfaceName)) {
1302 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1303 NwConstants.DEL_FLOW);
1305 if (!isBgpVpnInternetVpn) {
1306 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1308 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1309 + " successful", interfaceName, dpId, vpnName);
1311 // Interface is retained in the DPN, but its Link Down.
1312 // Only withdraw the prefixes for this interface from BGP
1313 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1317 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1318 final String vpnName, final long vpnId, String gwMac,
1319 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1320 final WriteTransaction writeInvTxn) {
1322 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1323 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1324 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1325 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1327 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1328 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1329 interfaceName, dpnId, vpnName, primaryRd);
1330 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1331 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1332 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1333 interfaceName, dpnId, vpnName, nextHops);
1334 for (Adjacency nextHop : nextHops) {
1335 if (nextHop.isPhysNetworkFunc()) {
1336 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1337 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1338 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1339 null/*writeCfgTxn*/);
1341 String rd = nextHop.getVrfId();
1342 List<String> nhList;
1343 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1344 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1346 // This is a primary adjacency
1347 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1348 : Collections.emptyList();
1349 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1350 interfaceName, writeInvTxn);
1352 if (!nhList.isEmpty()) {
1353 if (rd.equals(vpnName)) {
1354 //this is an internal vpn - the rd is assigned to the vpn instance name;
1355 //remove from FIB directly
1356 nhList.forEach((nh) -> removeAdjacencyFromInternalVpn(nextHop, vpnName,
1357 interfaceName, dpnId, writeConfigTxn));
1359 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd, interfaceName,
1363 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1364 + " interface {}", nextHop.getIpAddress(), rd,
1365 nextHop.getAdjacencyType().toString(), interfaceName);
1366 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
1367 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1370 String ip = nextHop.getIpAddress().split("/")[0];
1371 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1372 if (vpnVipToPort != null) {
1373 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip);
1374 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed adjacency for Interface {}"
1375 + " ip {} on dpn {} for vpn {} from VpnPortData Entry", vpnVipToPort.getPortName(),
1376 ip, dpnId, vpnName);
1380 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1381 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1382 + " Removing it.", interfaceName, vpnName, dpnId);
1383 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1387 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1388 String interfaceName, BigInteger dpnId,
1389 WriteTransaction writeConfigTxn) {
1391 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1393 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1394 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1395 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1399 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1400 BigInteger dpnId, String rd, String interfaceName,
1401 WriteTransaction writeConfigTxn) {
1402 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1403 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1404 nhList.forEach((nh) -> {
1405 //IRT: remove routes from other vpns importing it
1406 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1407 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1408 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1409 String vpnRd = vpn.getVrfId();
1410 if (vpnRd != null) {
1411 fibManager.removeOrUpdateFibEntry(vpnRd,
1412 nextHop.getIpAddress(), nh, writeConfigTxn);
1413 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1414 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1415 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1416 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1422 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1423 int lportTag, String gwMac, String interfaceName,
1424 WriteTransaction writeInvTxn) {
1425 final Uuid subnetId = nextHop.getSubnetId();
1426 if (nextHop.getSubnetGatewayMacAddress() == null) {
1427 // A valid mac-address was not available for this subnet-gateway-ip
1428 // So a connected-mac-address was used for this subnet and we need
1429 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1430 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1431 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1433 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, subnetId);
1436 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1437 String interfaceName) {
1438 // This is either an extra-route (or) a learned IP via subnet-route
1439 List<String> nhList = null;
1440 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1441 if (nextHopIp == null || nextHopIp.isEmpty()) {
1442 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1443 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1444 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1446 nhList = Collections.emptyList();
1448 nhList = Collections.singletonList(nextHopIp);
1453 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1454 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1455 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1456 // else use connected interface
1457 if (gwPort != null && gwPort.isSubnetIp()) {
1458 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1459 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1460 return Optional.of(gwPort.getMacAddress());
1462 return Optional.absent();
1466 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1467 final VpnInterface update) {
1468 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1469 update.getDpnId(), original.getVpnInstanceNames(),
1470 update.getVpnInstanceNames());
1471 final String vpnInterfaceName = update.getName();
1472 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1473 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1474 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1475 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1476 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1477 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1478 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1480 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1481 //handles switching between <internal VPN - external VPN>
1482 for (VpnInstanceNames vpnInterfaceVpnInstance : original.getVpnInstanceNames()) {
1483 String oldVpnName = vpnInterfaceVpnInstance.getVpnName();
1484 if (oldVpnName != null && (update.getVpnInstanceNames() == null
1485 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnName, update.getVpnInstanceNames()))) {
1486 UpdateData updateData = new UpdateData(identifier, original, update);
1487 vpnInterfacesUpdateQueue.add(updateData);
1488 LOG.info("update: UpdateData on VPNInterface {} on dpn {} update upon VPN swap from oldVpn(s) {}"
1489 + "to newVpn(s) {} added to update queue",
1490 updateData.getOriginal().getName(), dpnId,
1491 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1492 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1496 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1497 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1498 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1499 if (newVpnName != null && (original.getVpnInstanceNames() == null
1500 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(newVpnName,
1501 original.getVpnInstanceNames()))) {
1502 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1503 InstanceIdentifier<VpnInterfaceOpDataEntry> opIdentifier = VpnUtil
1504 .getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1505 if (canHandleNewVpnInterface(identifier, update, newVpnName)) {
1506 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1507 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1508 addVpnInterfaceToVpn(opIdentifier, update, copyOldAdjs, copyNewAdjs, identifier, newVpnName);
1511 UpdateData updateData = new UpdateData(identifier, original, update);
1512 vpnInterfacesUpdateQueue.add(updateData);
1513 LOG.info("update: UpdateData on VPNInterface {} on dpn {} update upon VPN swap from oldVpn(s) {}"
1514 + "to newVpn(s) {} added to update queue",
1515 updateData.getOriginal().getName(), dpnId,
1516 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1517 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1522 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1523 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1524 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1525 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1526 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1527 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1528 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName + newVpnName, () -> {
1529 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1530 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1531 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1532 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1533 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1534 update.getName(), newVpnName);
1535 //handle both addition and removal of adjacencies
1536 //currently, new adjacency may be an extra route
1537 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1538 if (!oldAdjs.equals(newAdjs)) {
1539 for (Adjacency adj : copyNewAdjs) {
1540 if (copyOldAdjs.contains(adj)) {
1541 copyOldAdjs.remove(adj);
1543 // add new adjacency - right now only extra route will hit this path
1544 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1545 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1546 dpnId, writeOperTxn, writeConfigTxn);
1548 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to vpn "
1549 + "interface {} on vpn {} dpnId {}",
1550 adj.getIpAddress(), adj.getNextHopIpList(),
1551 adj.getLabel(), adj.getSubnetId(), update.getName(),
1555 for (Adjacency adj : copyOldAdjs) {
1556 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1557 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1558 writeOperTxn, writeConfigTxn);
1560 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1561 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj.getNextHopIpList(),
1562 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1565 ListenableFuture<Void> operFuture = writeOperTxn.submit();
1568 } catch (ExecutionException e) {
1569 LOG.error("Exception encountered while submitting operational future for update"
1570 + " VpnInterface {} on vpn {}: {}", vpnInterfaceName, newVpnName, e);
1573 List<ListenableFuture<Void>> futures = new ArrayList<>();
1574 futures.add(writeConfigTxn.submit());
1575 LOG.info("update: vpn interface updated for interface {} oldVpn(s) {} newVpn {}"
1576 + "processed successfully", update.getName(),
1577 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()), newVpnName);
1581 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1582 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1587 @SuppressWarnings("checkstyle:IllegalCatch")
1588 private class VpnInterfaceUpdateTimerTask implements Runnable {
1589 private final Logger log = LoggerFactory.getLogger(VpnInterfaceUpdateTimerTask.class);
1595 } catch (ReadFailedException | RuntimeException e) {
1596 LOG.error("VpnInterfaceUpdateTimerTask failed", e);
1600 private void doRun() throws ReadFailedException {
1601 List<UpdateData> processQueue = new ArrayList<>();
1602 List<UpdateData> updateDataList = new ArrayList<>();
1603 vpnInterfacesUpdateQueue.drainTo(processQueue);
1604 int maxInterfaceList = 0;
1606 for (UpdateData updData : processQueue) {
1607 final VpnInterfaceKey key = updData.getIdentifier()
1608 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1609 final String interfaceName = key.getName();
1610 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1611 for (VpnInstanceNames vpnInterfaceVpnInstance : updData.getOriginal().getVpnInstanceNames()) {
1612 String oldVpnName = vpnInterfaceVpnInstance.getVpnName();
1613 if (updData.getUpdate().getVpnInstanceNames() != null
1614 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnName,
1615 updData.getUpdate().getVpnInstanceNames())) {
1618 log.info("run: VPN Interface update event - intfName {} remove vpnName {} running"
1619 + " config-driven swap removal", updData.getOriginal().getName(), oldVpnName);
1620 maxInterfaceList ++;
1621 removeVpnInterfaceCall(updData.getIdentifier(), updData.getOriginal(),
1622 oldVpnName, interfaceName);
1623 log.info("run: Processed Remove for update on VPNInterface {} upon VPN swap from old vpn {}"
1624 + " to newVpn(s) {}", updData.getOriginal().getName(),
1625 oldVpnName, VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData
1626 .getUpdate().getVpnInstanceNames()));
1628 updateDataList.add(updData);
1630 /* Decide the max-wait time based on number of VpnInterfaces.
1631 * max-wait-time is num-of-interface * 4seconds (random choice).
1632 * Every 2sec poll VpnToDpnList. If VpnInterface is removed ,
1633 * remove it from vpnInterfaceList.
1636 maxInterfaceList * (int) (VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS / 1000);
1638 Iterator<UpdateData> updateDataIterator = updateDataList.iterator();
1639 UpdateData updateDataSet;
1640 while (waitTime < maxWaitTime) {
1642 Thread.sleep(2000); // sleep for 2sec
1643 } catch (InterruptedException e) {
1647 while (updateDataIterator.hasNext()) {
1648 boolean interfaceIsRemoved = true;
1649 updateDataSet = updateDataIterator.next();
1650 for (VpnInstanceNames vpnInterfaceVpnInstance : updateDataSet.getOriginal().getVpnInstanceNames()) {
1651 String oldVpnName = vpnInterfaceVpnInstance.getVpnName();
1652 if (oldVpnName != null && updateDataSet.getUpdate().getVpnInstanceNames() != null
1653 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnName,
1654 updateDataSet.getUpdate().getVpnInstanceNames())) {
1658 boolean isPresent = isVpnIntfPresentInVpnToDpnList(updateDataSet.getOriginal(), oldVpnName);
1660 interfaceIsRemoved = false;
1663 if (interfaceIsRemoved) {
1664 updateDataIterator.remove();
1667 if (updateDataList.isEmpty()) {
1668 log.info("run: All VpnInterfaces are successfully removed from OLD VPN after time {}", waitTime);
1671 waitTime += 2; //Increment linearly by 2sec.
1674 if (updateDataList.size() > 0) {
1675 log.error("run: VpnInterfacesList not removed from old Vpn even after waiting {}", waitTime);
1677 for (UpdateData updData : processQueue) {
1678 if (updateDataList.contains(updData)) {
1679 log.error("run: Failed to swap VpnInterface {} from oldVpn {} to target VPN {}"
1680 + "as it has not been cleaned up from the oldVpn", updData.getOriginal().getName(),
1681 VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData.getOriginal()
1682 .getVpnInstanceNames()),
1683 VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData.getUpdate()
1684 .getVpnInstanceNames()));
1687 for (VpnInstanceNames vpnInterfaceVpnInstance : updData.getUpdate().getVpnInstanceNames()) {
1688 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1689 if (updData.getOriginal().getVpnInstanceNames() != null
1690 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(newVpnName,
1691 updData.getOriginal().getVpnInstanceNames())) {
1694 log.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven"
1695 + " swap addition", updData.getUpdate().getName(), newVpnName);
1696 final Adjacencies origAdjs = updData.getOriginal().getAugmentation(Adjacencies.class);
1697 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency() != null
1698 ? origAdjs.getAdjacency() : new ArrayList<>();
1699 final Adjacencies updateAdjs = updData.getUpdate().getAugmentation(Adjacencies.class);
1700 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency() != null
1701 ? updateAdjs.getAdjacency() : new ArrayList<>();
1703 addVpnInterfaceCall(updData.getIdentifier(), updData.getUpdate(),
1704 oldAdjs, newAdjs, newVpnName);
1705 log.info("run: Processed Add for update on VPNInterface {} from oldVpn(s) {} to newVpn {}"
1706 + " upon VPN swap", updData.getUpdate().getName(),
1707 VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData.getOriginal()
1708 .getVpnInstanceNames()), newVpnName);
1713 private boolean isVpnIntfPresentInVpnToDpnList(VpnInterface vpnInterface, String vpnName)
1714 throws ReadFailedException {
1715 BigInteger dpnId = vpnInterface.getDpnId();
1716 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1717 log.trace("isVpnIntfPresentInVpnToDpnList: GOT rd {} for VpnInterface {} VpnInstance {} ", rd ,
1718 vpnInterface.getName(), vpnName);
1724 Optional<VpnInstanceOpDataEntry> maybeVpnInstanceOpData = vpnInstanceOpDataEntryCache.get(
1725 VpnUtil.getVpnInstanceOpDataIdentifier(rd));
1726 if (maybeVpnInstanceOpData.isPresent()) {
1727 log.trace("isVpnIntfPresentInVpnToDpnList: GOT VpnInstanceOp {} for rd {} ",
1728 maybeVpnInstanceOpData.get(), rd);
1729 List<VpnToDpnList> dpnToVpns = maybeVpnInstanceOpData.get().getVpnToDpnList();
1730 if (dpnToVpns != null) {
1731 for (VpnToDpnList dpn : dpnToVpns) {
1732 if (dpn.getDpnId().equals(dpnId)) {
1733 return dpn.getVpnInterfaces().stream().anyMatch(
1734 vpnInterfaces -> vpnInterface.getName().equals(vpnInterfaces.getInterfaceName()));
1736 log.info("isVpnIntfPresentInVpnToDpnList: VpnInterface {} not present in DpnId {} vpn {}",
1737 vpnInterface.getName(), dpn.getDpnId(), vpnName);
1746 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1747 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1748 synchronized (label.toString().intern()) {
1749 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1750 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1751 Optional<LabelRouteInfo> opResult = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
1752 if (opResult.isPresent()) {
1753 LabelRouteInfo labelRouteInfo =
1754 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1755 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, labelRouteInfo);
1758 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label, nextHopIpList);
1761 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1762 SubnetRoute route, WriteTransaction writeConfigTxn) {
1764 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1765 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, null /* parentVpnRd */)
1766 .addAugmentation(SubnetRoute.class, route).build();
1767 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1768 InstanceIdentifierBuilder<VrfTables> idBuilder =
1769 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1770 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1771 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1772 if (writeConfigTxn != null) {
1773 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1775 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1777 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1778 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1781 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1782 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1783 WriteTransaction writeConfigTxn) {
1785 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1786 LogicalDatastoreType.OPERATIONAL, identifier);
1788 if (optVpnInterface.isPresent()) {
1789 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1790 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1791 String vpnName = currVpnIntf.getVpnInstanceName();
1792 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1793 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1794 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker,
1795 LogicalDatastoreType.OPERATIONAL, adjPath);
1796 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1797 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1798 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1799 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1800 List<Adjacency> adjacencies;
1801 if (optAdjacencies.isPresent()) {
1802 adjacencies = optAdjacencies.get().getAdjacency();
1804 // This code will be hit in case of first PNF adjacency
1805 adjacencies = new ArrayList<>();
1807 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1808 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1809 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1810 Adjacency operationalAdjacency = null;
1811 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()) {
1812 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1813 : RouteOrigin.STATIC;
1814 String nh = adj.getNextHopIpList().get(0);
1815 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1816 synchronized (vpnPrefixKey.intern()) {
1817 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1818 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1819 if (rdToAllocate.isPresent()) {
1820 input.setRd(rdToAllocate.get());
1821 operationalAdjacency = populator.createOperationalAdjacency(input);
1822 int label = operationalAdjacency.getLabel().intValue();
1823 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1824 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1825 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1826 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1827 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1828 vpnName, label, currVpnIntf.getName(), dpnId);
1830 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}", vpnName,
1834 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1835 // Keeping the MPLS check for now.
1836 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1837 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1838 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1839 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1840 vpnsToImportRoute.forEach(vpn -> {
1841 if (vpn.getVrfId() != null) {
1842 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1843 dataBroker, vpn.getVpnId(), vpnId, prefix,
1844 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1846 rds -> vpnManager.addExtraRoute(
1847 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1848 adj.getIpAddress(), nh, rds,
1849 currVpnIntf.getVpnInstanceName(),
1850 l3vni, RouteOrigin.SELF_IMPORTED,
1851 currVpnIntf.getName(), opAdjacency, encapType, writeConfigTxn));
1856 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1857 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1858 currVpnIntf.getName(), vpnName);
1860 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1863 LogicalDatastoreType.OPERATIONAL,
1864 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1865 adj.getSubnetId().getValue()), prefix),
1866 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1867 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1869 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1870 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */, 0 /*l3vni*/,
1871 null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1873 input.setRd(adj.getVrfId());
1875 if (operationalAdjacency == null) {
1876 operationalAdjacency = populator.createOperationalAdjacency(input);
1878 adjacencies.add(operationalAdjacency);
1879 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1880 VpnInterfaceOpDataEntry newVpnIntf =
1881 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1882 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1883 currVpnIntf.getGatewayMacAddress());
1885 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1889 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1890 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1891 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1894 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1895 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1896 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1897 LogicalDatastoreType.OPERATIONAL, identifier);
1899 if (optVpnInterface.isPresent()) {
1900 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1902 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1903 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1904 if (optAdjacencies.isPresent()) {
1905 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1907 if (!adjacencies.isEmpty()) {
1908 LOG.trace("delAdjFromVpnInterface: Adjacencies are " + adjacencies);
1909 Iterator<Adjacency> adjIt = adjacencies.iterator();
1910 while (adjIt.hasNext()) {
1911 Adjacency adjElem = adjIt.next();
1912 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1913 String rd = adjElem.getVrfId();
1916 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1917 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1918 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1919 currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove(),
1920 currVpnIntf.getLportTag(), currVpnIntf.getGatewayMacAddress());
1922 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1923 if (adj.getNextHopIpList() != null) {
1924 for (String nh : adj.getNextHopIpList()) {
1925 deleteExtraRouteFromCurrentAndImportingVpns(
1926 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1927 currVpnIntf.getName(), writeConfigTxn);
1929 } else if (adj.isPhysNetworkFunc()) {
1930 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet [}",
1931 adj.getIpAddress(), adj.getSubnetId());
1932 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1940 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1941 dpnId, adj.getVrfId());
1943 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1944 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1949 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1950 String rd, String intfName, WriteTransaction writeConfigTxn) {
1951 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1952 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1953 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1954 String vpnRd = vpn.getVrfId();
1955 if (vpnRd != null) {
1956 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
1961 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1962 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1963 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1964 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1967 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1968 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1969 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1972 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1973 WriteTransaction writeOperTxn) {
1974 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1975 if (dpId.equals(BigInteger.ZERO)) {
1976 LOG.error("addToNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1977 + " association model", vpnInterfaceName, routerName);
1981 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1983 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1984 .OPERATIONAL, routerDpnListIdentifier);
1985 RouterInterfaces routerInterface =
1986 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1987 vpnInterfaceName).build();
1988 if (optionalRouterDpnList.isPresent()) {
1989 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1990 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1992 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1993 builder.setRouterId(routerName);
1994 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1995 builder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1996 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1997 getRouterId(routerName),
1998 builder.build(), true);
2002 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
2003 WriteTransaction writeOperTxn) {
2004 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
2005 if (dpId.equals(BigInteger.ZERO)) {
2006 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
2007 + " dissociation model", vpnInterfaceName, routerName);
2011 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
2012 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
2013 .OPERATIONAL, routerDpnListIdentifier);
2014 if (optionalRouterDpnList.isPresent()) {
2015 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
2016 RouterInterfaces routerInterface =
2017 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
2018 vpnInterfaceName).build();
2020 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
2021 if (routerInterfaces.isEmpty()) {
2022 if (writeOperTxn != null) {
2023 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
2025 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
2028 if (writeOperTxn != null) {
2029 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
2030 RouterInterfaces.class,
2031 new RouterInterfacesKey(vpnInterfaceName)));
2033 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL,
2034 routerDpnListIdentifier.child(
2035 RouterInterfaces.class,
2036 new RouterInterfacesKey(vpnInterfaceName)));
2043 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
2044 WriteTransaction writeOperTxn) {
2045 if (dpId.equals(BigInteger.ZERO)) {
2046 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
2047 + " dissociation model", vpnInterfaceName, routerName);
2051 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
2052 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
2053 .OPERATIONAL, routerDpnListIdentifier);
2054 if (optionalRouterDpnList.isPresent()) {
2055 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
2056 RouterInterfaces routerInterface =
2057 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
2058 vpnInterfaceName).build();
2059 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
2060 if (routerInterfaces.isEmpty()) {
2061 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
2063 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
2064 RouterInterfaces.class,
2065 new RouterInterfacesKey(vpnInterfaceName)));
2071 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
2072 WriteTransaction writeConfigTxn, String vpnName) {
2073 if (vpnInterface == null) {
2076 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
2078 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
2079 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
2082 for (Adjacency adj : adjs) {
2083 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2084 String primaryInterfaceIp = adj.getIpAddress();
2085 String macAddress = adj.getMacAddress();
2086 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
2088 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
2089 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
2091 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
2092 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
2093 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
2094 routerInt, label, writeConfigTxn);
2095 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
2096 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
2101 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
2102 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
2103 primaryRd, vpnName);
2106 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
2107 WriteTransaction writeConfigTxn, String vpnName) {
2108 Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
2109 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
2111 List<Adjacency> adjsList = adjs.getAdjacency();
2112 for (Adjacency adj : adjsList) {
2113 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2114 String primaryInterfaceIp = adj.getIpAddress();
2115 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
2116 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
2117 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
2118 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
2123 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
2124 vpnInterface.getName(), rd);
2128 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
2129 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
2130 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
2131 vpnName, intefaceData.vpnInterface.getName());
2134 final VpnInterfaceKey key = intefaceData.identifier
2135 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
2136 final String interfaceName = key.getName();
2137 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
2138 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
2139 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
2140 intefaceData.identifier, vpnName);
2144 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
2145 VpnInterface vpnInterface, String vpnName) {
2146 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
2148 if (vpnInterfaces == null) {
2149 vpnInterfaces = new ConcurrentLinkedQueue<>();
2151 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2152 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2153 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2154 vpnInterface.getName(), vpnName);
2157 public boolean isVpnInstanceReady(String vpnInstanceName) {
2158 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnInstanceName);
2159 if (vpnRd == null) {
2162 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
2164 return vpnInstanceOpDataEntry != null;
2167 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2168 synchronized (vpnInstanceName.intern()) {
2169 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2170 unprocessedVpnInterfaces.get(vpnInstanceName);
2171 if (vpnInterfaces != null) {
2172 while (!vpnInterfaces.isEmpty()) {
2173 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2174 if (hasVpnInstanceCreatedSuccessfully) {
2175 processSavedInterface(savedInterface, vpnInstanceName);
2176 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2177 savedInterface.vpnInterface.getName(), vpnInstanceName);
2179 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2180 savedInterface.vpnInterface.getName(), vpnInstanceName);
2184 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2189 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2190 VpnInterface vpnInterface) {
2191 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2192 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2193 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2194 if (vpnInterfaces != null) {
2195 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2196 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2197 + "unprocessed list", vpnInterface.getName(),
2198 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2201 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2202 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2207 public void vpnInstanceIsReady(String vpnInstanceName) {
2208 processSavedInterfaces(vpnInstanceName, true);
2211 public void vpnInstanceFailed(String vpnInstanceName) {
2212 processSavedInterfaces(vpnInstanceName, false);
2215 private static class UnprocessedVpnInterfaceData {
2216 InstanceIdentifier<VpnInterface> identifier;
2217 VpnInterface vpnInterface;
2219 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2220 this.identifier = identifier;
2221 this.vpnInterface = vpnInterface;
2225 public int hashCode() {
2226 final int prime = 31;
2228 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2229 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2234 public boolean equals(Object obj) {
2241 if (getClass() != obj.getClass()) {
2244 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2245 if (identifier == null) {
2246 if (other.identifier != null) {
2249 } else if (!identifier.equals(other.identifier)) {
2252 if (vpnInterface == null) {
2253 if (other.vpnInterface != null) {
2256 } else if (!vpnInterface.equals(other.vpnInterface)) {
2263 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2264 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
2265 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
2266 if (vpnInstanceOpData == null) {
2269 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2270 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2273 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2274 vpnToDpnLists.forEach(vpnToDpnList -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2275 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2276 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2277 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = VpnUtil.read(dataBroker,
2278 LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2279 if (!vpnInterfaceOptional.isPresent()) {
2282 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2283 vpnInterface.getInterfaceName());
2284 if (configVpnAdjacencies == null) {
2285 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2288 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2289 .getAugmentation(AdjacenciesOp.class).getAdjacency();
2290 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2291 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2292 // in operational DS. These unprocessed adjacencies will be handled below.
2293 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2294 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2295 configVpnAdjacencies.stream()
2296 .filter(adjacency -> operationVpnAdjacencies.stream()
2297 .noneMatch(operationalAdjacency ->
2298 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2299 .forEach(adjacency -> {
2300 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2301 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName() + vpnName,
2303 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
2304 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
2305 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2306 addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd, adjacency,
2307 vpnInterfaceOptional.get().getDpnId(), writeConfigTxn, writeOperTxn);
2308 ListenableFuture<Void> operFuture = writeOperTxn.submit();
2311 } catch (ExecutionException | InterruptedException e) {
2312 LOG.error("Exception encountered while submitting operational"
2313 + " future for vpnInterface {}", vpnInterface, e);
2315 List<ListenableFuture<Void>> futures = new ArrayList<>();
2316 futures.add(writeConfigTxn.submit());
2319 return Collections.emptyList();
2326 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2327 private final String interfaceName;
2328 private final boolean add;
2329 private final String txnDestination;
2331 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2332 this.interfaceName = interfaceName;
2334 this.txnDestination = transactionDest;
2338 public void onSuccess(Void voidObj) {
2340 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2341 interfaceName, txnDestination);
2343 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2348 public void onFailure(Throwable throwable) {
2350 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}"
2351 + " with exception: {}", interfaceName, txnDestination, throwable);
2353 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed with exception: {}", interfaceName,
2355 VpnUtil.unsetScheduledToRemoveForVpnInterface(dataBroker, interfaceName);