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;
40 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
41 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
42 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
43 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
44 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
45 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
46 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
47 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
48 import org.opendaylight.genius.mdsalutil.MDSALUtil;
49 import org.opendaylight.genius.mdsalutil.NWUtil;
50 import org.opendaylight.genius.mdsalutil.NwConstants;
51 import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
52 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
53 import org.opendaylight.infrautils.caches.CacheProvider;
54 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
55 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
56 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
57 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
58 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
59 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
60 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
61 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
62 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
63 import org.opendaylight.netvirt.vpnmanager.arp.responder.ArpResponderHandler;
64 import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput;
65 import org.opendaylight.netvirt.vpnmanager.populator.intfc.VpnPopulator;
66 import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterfaceBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
116 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
117 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
118 import org.slf4j.Logger;
119 import org.slf4j.LoggerFactory;
122 public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInterface, VpnInterfaceManager> {
124 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
125 private static final int VPN_INF_UPDATE_TIMER_TASK_DELAY = 1000;
126 private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
127 private static final short DJC_MAX_RETRIES = 3;
129 private final DataBroker dataBroker;
130 private final ManagedNewTransactionRunner txRunner;
131 private final IBgpManager bgpManager;
132 private final IFibManager fibManager;
133 private final IMdsalApiManager mdsalManager;
134 private final IdManagerService idManager;
135 private final OdlInterfaceRpcService ifaceMgrRpcService;
136 private final VpnFootprintService vpnFootprintService;
137 private final IInterfaceManager interfaceManager;
138 private final IVpnManager vpnManager;
139 private final ArpResponderHandler arpResponderHandler;
140 private final JobCoordinator jobCoordinator;
142 private final ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<>();
144 private final BlockingQueue<UpdateData> vpnInterfacesUpdateQueue = new LinkedBlockingQueue<>();
145 private final ScheduledExecutorService vpnInfUpdateTaskExecutor = Executors.newScheduledThreadPool(1);
147 private final Map<String, ConcurrentLinkedQueue<UnprocessedVpnInterfaceData>> unprocessedVpnInterfaces =
148 new ConcurrentHashMap<>();
150 private final DataObjectCache<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryCache;
153 public VpnInterfaceManager(final DataBroker dataBroker,
154 final IBgpManager bgpManager,
155 final IdManagerService idManager,
156 final IMdsalApiManager mdsalManager,
157 final IFibManager fibManager,
158 final OdlInterfaceRpcService ifaceMgrRpcService,
159 final VpnFootprintService vpnFootprintService,
160 final IInterfaceManager interfaceManager,
161 final IVpnManager vpnManager,
162 final ArpResponderHandler arpResponderHandler,
163 final JobCoordinator jobCoordinator,
164 final CacheProvider cacheProvider) {
165 super(VpnInterface.class, VpnInterfaceManager.class);
167 this.dataBroker = dataBroker;
168 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
169 this.bgpManager = bgpManager;
170 this.idManager = idManager;
171 this.mdsalManager = mdsalManager;
172 this.fibManager = fibManager;
173 this.ifaceMgrRpcService = ifaceMgrRpcService;
174 this.vpnFootprintService = vpnFootprintService;
175 this.interfaceManager = interfaceManager;
176 this.vpnManager = vpnManager;
177 this.arpResponderHandler = arpResponderHandler;
178 this.jobCoordinator = jobCoordinator;
179 vpnInfUpdateTaskExecutor.scheduleWithFixedDelay(new VpnInterfaceUpdateTimerTask(),
180 0, VPN_INF_UPDATE_TIMER_TASK_DELAY, TIME_UNIT);
182 vpnInstanceOpDataEntryCache = new DataObjectCache<>(VpnInstanceOpDataEntry.class, dataBroker,
183 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
184 VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class).build(), cacheProvider);
187 public Runnable isNotifyTaskQueued(String intfName) {
188 return vpnIntfMap.remove(intfName);
192 public void start() {
193 LOG.info("{} start", getClass().getSimpleName());
194 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
199 public void close() {
201 vpnInfUpdateTaskExecutor.shutdown();
202 vpnInstanceOpDataEntryCache.close();
206 protected InstanceIdentifier<VpnInterface> getWildCardPath() {
207 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
211 protected VpnInterfaceManager getDataTreeChangeListener() {
212 return VpnInterfaceManager.this;
216 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
217 LOG.info("add: intfName {} onto vpnName {}",
218 vpnInterface.getName(),
219 VpnHelper.getVpnInterfaceVpnInstanceNamesString(vpnInterface.getVpnInstanceNames()));
220 addVpnInterface(identifier, vpnInterface, null, null);
223 private boolean canHandleNewVpnInterface(final InstanceIdentifier<VpnInterface> identifier,
224 final VpnInterface vpnInterface, String vpnName) {
225 synchronized (vpnName.intern()) {
226 if (isVpnInstanceReady(vpnName)) {
229 addToUnprocessedVpnInterfaces(identifier, vpnInterface, vpnName);
234 // TODO Clean up the exception handling
235 @SuppressWarnings("checkstyle:IllegalCatch")
236 private void addVpnInterface(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
237 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs) {
238 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
239 String vpnName = vpnInterfaceVpnInstance.getVpnName();
240 addVpnInterfaceCall(identifier, vpnInterface, oldAdjs, newAdjs, vpnName);
244 private void addVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface,
245 final List<Adjacency> oldAdjs, final List<Adjacency> newAdjs, String vpnName) {
246 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
247 final String interfaceName = key.getName();
249 if (!canHandleNewVpnInterface(identifier, vpnInterface, vpnName)) {
250 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
251 vpnName, vpnInterface.getName());
254 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
255 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
256 List<Adjacency> copyOldAdjs = null;
257 if (oldAdjs != null) {
258 copyOldAdjs = new ArrayList<>();
259 copyOldAdjs.addAll(oldAdjs);
261 List<Adjacency> copyNewAdjs = null;
262 if (newAdjs != null) {
263 copyNewAdjs = new ArrayList<>();
264 copyNewAdjs.addAll(newAdjs);
266 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, vpnInterface, copyOldAdjs, copyNewAdjs, identifier, vpnName);
269 private void addVpnInterfaceToVpn(final InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier,
270 final VpnInterface vpnInterface, final List<Adjacency> oldAdjs,
271 final List<Adjacency> newAdjs,
272 final InstanceIdentifier<VpnInterface> identifier, String vpnName) {
273 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
274 final String interfaceName = key.getName();
275 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
276 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
277 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
278 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
279 if (interfaceState != null) {
281 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
282 final int ifIndex = interfaceState.getIfIndex();
283 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName + vpnName, () -> {
284 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
285 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
286 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
287 LOG.info("addVpnInterface: VPN Interface add event - intfName {} vpnName {} on dpn {}" ,
288 vpnInterface.getName(), vpnName, vpnInterface.getDpnId());
289 processVpnInterfaceUp(dpnId, vpnInterface, primaryRd, ifIndex, false, writeConfigTxn,
290 writeOperTxn, writeInvTxn, interfaceState, vpnName);
291 if (oldAdjs != null && !oldAdjs.equals(newAdjs)) {
292 LOG.info("addVpnInterface: Adjacency changed upon VPNInterface {}"
293 + " Update for swapping VPN {} case.", interfaceName, vpnName);
294 if (newAdjs != null) {
295 for (Adjacency adj : newAdjs) {
296 if (oldAdjs.contains(adj)) {
299 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
301 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd,
302 adj, dpnId, writeOperTxn, writeConfigTxn);
307 for (Adjacency adj : oldAdjs) {
308 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(
310 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
311 writeOperTxn, writeConfigTxn);
315 ListenableFuture<Void> operFuture = writeOperTxn.submit();
318 } catch (ExecutionException e) {
319 LOG.error("addVpnInterface: Exception encountered while submitting operational future for"
320 + " addVpnInterface {} on vpn {}: {}", vpnInterface.getName(), vpnName, e);
323 List<ListenableFuture<Void>> futures = new ArrayList<>();
324 ListenableFuture<Void> configFuture = writeConfigTxn.submit();
325 futures.add(configFuture);
326 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, true, "Config"));
327 futures.add(writeInvTxn.submit());
328 LOG.info("addVpnInterface: Addition of interface {} in VPN {} on dpn {}"
329 + " processed successfully", interfaceName, vpnName, dpnId);
332 } catch (NumberFormatException | IllegalStateException e) {
333 LOG.error("addVpnInterface: Unable to retrieve dpnId from interface operational data store for "
334 + "interface {}. Interface addition on vpn {} failed", interfaceName,
338 } else if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
339 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName() + vpnName,
341 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
342 createFibEntryForRouterInterface(primaryRd, vpnInterface, interfaceName,
343 writeConfigTxn, vpnName);
344 LOG.info("addVpnInterface: Router interface {} for vpn {} on dpn {}", interfaceName,
345 vpnName, vpnInterface.getDpnId());
346 ListenableFuture<Void> futures = writeConfigTxn.submit();
347 String errorText = "addVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
348 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
349 ListenableFutures.addErrorLogging(futures, LOG, errorText);
350 return Collections.singletonList(futures);
353 LOG.info("addVpnInterface: Handling addition of VPN interface {} on vpn {} skipped as interfaceState"
354 + " is not available", interfaceName, vpnName);
357 LOG.error("addVpnInterface: Handling addition of VPN interface {} on vpn {} dpn {} skipped"
358 + " as vpn is pending delete", interfaceName, vpnName,
359 vpnInterface.getDpnId());
363 // "Unconditional wait" and "Wait not in loop" wrt the VpnNotifyTask below - suppressing the FB violation -
364 // see comments below.
365 @SuppressFBWarnings({"UW_UNCOND_WAIT", "WA_NOT_IN_LOOP"})
366 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface, final String primaryRd,
367 final int lportTag, boolean isInterfaceUp,
368 WriteTransaction writeConfigTxn,
369 WriteTransaction writeOperTxn,
370 WriteTransaction writeInvTxn,
371 Interface interfaceState,
372 final String vpnName) {
373 final String interfaceName = vpnInterface.getName();
374 Optional<VpnInterfaceOpDataEntry> optOpVpnInterface = VpnUtil.getVpnInterfaceOpDataEntry(dataBroker,
375 interfaceName, vpnName);
376 VpnInterfaceOpDataEntry opVpnInterface = optOpVpnInterface.isPresent() ? optOpVpnInterface.get() : null;
377 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
378 if (!isInterfaceUp) {
379 LOG.info("processVpnInterfaceUp: Binding vpn service to interface {} onto dpn {} for vpn {}",
380 interfaceName, dpId, vpnName);
381 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
382 if (vpnId == VpnConstants.INVALID_ID) {
383 LOG.warn("processVpnInterfaceUp: VpnInstance to VPNId mapping not available for VpnName {}"
384 + " processing vpninterface {} on dpn {}, bailing out now.", vpnName, interfaceName,
389 boolean waitForVpnInterfaceOpRemoval = false;
390 if (opVpnInterface != null && !opVpnInterface.isScheduledForRemove()) {
391 String opVpnName = opVpnInterface.getVpnInstanceName();
392 String primaryInterfaceIp = null;
393 if (opVpnName.equals(vpnName)) {
394 // Please check if the primary VRF Entry does not exist for VPNInterface
395 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
397 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
398 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
400 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} failed as adjacencies"
401 + " for this vpn interface could not be obtained", interfaceName, dpId,
405 for (Adjacency adj : adjs) {
406 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
407 primaryInterfaceIp = adj.getIpAddress();
411 if (primaryInterfaceIp == null) {
412 LOG.error("processVpnInterfaceUp: VPN Interface {} addition on dpn {} for vpn {} failed"
413 + " as primary adjacency for this vpn interface could not be obtained", interfaceName,
417 // Get the rd of the vpn instance
418 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, primaryRd, primaryInterfaceIp);
420 LOG.error("processVpnInterfaceUp: VPN Interface {} on dpn {} for vpn {} already provisioned ,"
421 + " bailing out from here.", interfaceName, dpId, vpnName);
424 waitForVpnInterfaceOpRemoval = true;
426 LOG.error("processVpnInterfaceUp: vpn interface {} to go to configured vpn {} on dpn {},"
427 + " but in operational vpn {}", interfaceName, vpnName, dpId, opVpnName);
430 if (!waitForVpnInterfaceOpRemoval) {
431 // Add the VPNInterface and quit
432 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
433 null/*ipAddressSourceValuePair*/,
435 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
436 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
437 if (!isBgpVpnInternetVpn) {
438 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false /*isTunnelInterface*/,
441 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {}", interfaceName,
443 if (interfaceManager.isExternalInterface(interfaceName)) {
444 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
445 NwConstants.ADD_FLOW);
450 // FIB didn't get a chance yet to clean up this VPNInterface
451 // Let us give it a chance here !
452 LOG.info("processVpnInterfaceUp: Trying to add VPN Interface {} on dpn {} for vpn {},"
453 + " but waiting for FIB to clean up! ", interfaceName, dpId, vpnName);
455 Runnable notifyTask = new VpnNotifyTask();
456 synchronized (notifyTask) {
457 // Per FB's "Unconditional wait" violation, the code should really verify that the condition it
458 // intends to wait for is not already satisfied before calling wait. However the VpnNotifyTask is
459 // published here while holding the lock on it so this path will hit the wait before notify can be
461 vpnIntfMap.put(interfaceName, notifyTask);
463 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
464 } catch (InterruptedException e) {
469 vpnIntfMap.remove(interfaceName);
472 if (opVpnInterface != null) {
473 LOG.warn("processVpnInterfaceUp: VPN Interface {} removal on dpn {} for vpn {}"
474 + " by FIB did not complete on time," + " bailing addition ...", interfaceName,
476 VpnUtil.unsetScheduledToRemoveForVpnInterface(dataBroker, interfaceName);
479 // VPNInterface got removed, proceed with Add
480 LOG.info("processVpnInterfaceUp: Continuing to plumb vpn interface {} onto dpn {} for vpn {}",
481 interfaceName, dpId, vpnName);
482 vpnFootprintService.updateVpnToDpnMapping(dpId, vpnName, primaryRd, interfaceName,
483 null/*ipAddressSourceValuePair*/,
485 processVpnInterfaceAdjacencies(dpId, lportTag, vpnName, primaryRd, interfaceName,
486 vpnId, writeConfigTxn, writeOperTxn, writeInvTxn, interfaceState);
487 if (!isBgpVpnInternetVpn) {
488 VpnUtil.bindService(vpnName, interfaceName, dataBroker, false/*isTunnelInterface*/, jobCoordinator);
490 LOG.info("processVpnInterfaceUp: Plumbed vpn interface {} onto dpn {} for vpn {} after waiting for"
491 + " FIB to clean up", interfaceName, dpId, vpnName);
492 if (interfaceManager.isExternalInterface(interfaceName)) {
493 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId,
494 lportTag, writeInvTxn, NwConstants.ADD_FLOW);
497 // Interface is retained in the DPN, but its Link Up.
498 // Advertise prefixes again for this interface to BGP
499 InstanceIdentifier<VpnInterface> identifier =
500 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName());
501 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
502 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
503 advertiseAdjacenciesForVpnToBgp(primaryRd, dpId, vpnInterfaceOpIdentifier, vpnName, interfaceName);
504 // Perform similar operation as interface add event for extraroutes.
505 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
506 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
507 if (!optAdjacencies.isPresent()) {
508 LOG.trace("No config adjacencies present for vpninterface {}", vpnInterface);
511 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
512 for (Adjacency adjacency : adjacencies) {
513 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
516 // if BGPVPN Internet, filter only IPv6 Adjacencies
517 if (isBgpVpnInternetVpn && !VpnUtil.isAdjacencyEligibleToVpnInternet(
518 dataBroker, adjacency)) {
521 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adjacency,
522 dpId, writeOperTxn, writeConfigTxn);
527 private void processExternalVpnInterface(String interfaceName, String vpnName, long vpnId, BigInteger dpId,
528 int lportTag, WriteTransaction writeInvTxn, int addOrRemove) {
531 // vpn instance of ext-net interface is the network-id
532 extNetworkId = new Uuid(vpnName);
533 } catch (IllegalArgumentException e) {
534 LOG.error("processExternalVpnInterface: VPN instance {} is not Uuid. Processing external vpn interface {}"
535 + " on dpn {} failed", vpnName, interfaceName, dpId);
539 List<Uuid> routerIds = VpnUtil.getExternalNetworkRouterIds(dataBroker, extNetworkId);
540 if (routerIds == null || routerIds.isEmpty()) {
541 LOG.info("processExternalVpnInterface: No router is associated with {}."
542 + " Bailing out of processing external vpn interface {} on dpn {} for vpn {}",
543 extNetworkId.getValue(), interfaceName, dpId, vpnName);
547 LOG.info("processExternalVpnInterface: Router-ids {} associated with exernal vpn-interface {} on dpn {}"
548 + " for vpn {}", routerIds, interfaceName, dpId, vpnName);
549 for (Uuid routerId : routerIds) {
550 String routerName = routerId.getValue();
551 BigInteger primarySwitch = VpnUtil.getPrimarySwitchForRouter(dataBroker, routerName);
552 if (Objects.equals(primarySwitch, dpId)) {
553 Routers router = VpnUtil.getExternalRouter(dataBroker, routerName);
554 if (router != null) {
555 if (addOrRemove == NwConstants.ADD_FLOW) {
556 vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName,
557 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()), router.getExtGwMacAddress(),
558 dpId, interfaceName, lportTag, writeInvTxn);
560 vpnManager.removeArpResponderFlowsToExternalNetworkIps(routerName,
561 VpnUtil.getIpsListFromExternalIps(router.getExternalIps()),
562 dpId, interfaceName, lportTag);
565 LOG.error("processExternalVpnInterface: No external-router found for router-id {}. Bailing out of"
566 + " processing external vpn-interface {} on dpn {} for vpn {}", routerName,
567 interfaceName, dpId, vpnName);
573 // TODO Clean up the exception handling
574 @SuppressWarnings("checkstyle:IllegalCatch")
575 private void advertiseAdjacenciesForVpnToBgp(final String rd, BigInteger dpnId,
576 final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
577 String vpnName, String interfaceName) {
579 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} on dpn {} in vpn {}",
580 interfaceName, dpnId, vpnName);
583 if (rd.equals(vpnName)) {
584 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} on dpn {}"
585 + " as it is in internal vpn{} with rd {}", interfaceName, dpnId, vpnName, rd);
589 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} on dpn {} in vpn {} with rd {} ",
590 interfaceName, dpnId, vpnName, rd);
592 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
593 if (nextHopIp == null) {
594 LOG.error("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} on dpn {} is null,"
595 + " returning from advertising route with rd {} vpn {} to bgp", interfaceName, dpnId,
601 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
602 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
603 if (adjacencies.isPresent()) {
604 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
606 if (!nextHops.isEmpty()) {
607 LOG.debug("advertiseAdjacenciesForVpnToBgp: NextHops are {} for interface {} on dpn {} for vpn {}"
608 + " rd {}", nextHops, interfaceName, dpnId, vpnName, rd);
609 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
610 long l3vni = vpnInstanceOpData.getL3vni();
611 VrfEntry.EncapType encapType = VpnUtil.isL3VpnOverVxLan(l3vni)
612 ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
613 for (Adjacency nextHop : nextHops) {
614 if (nextHop.getAdjacencyType() == AdjacencyType.ExtraRoute) {
617 String gatewayMac = null;
619 if (VpnUtil.isL3VpnOverVxLan(l3vni)) {
620 final VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
621 vpnInstanceOpData.getVpnInstanceName(), nextHop.getIpAddress());
622 gatewayMac = arpResponderHandler.getGatewayMacAddressForInterface(gwPort, interfaceName).get();
624 label = nextHop.getLabel();
627 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Adding Fib Entry rd {} prefix {}"
628 + " nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
629 bgpManager.advertisePrefix(rd, nextHop.getMacAddress(), nextHop.getIpAddress(), nextHopIp,
630 encapType, (int)label, l3vni, 0 /*l2vni*/,
632 LOG.info("VPN ADVERTISE: advertiseAdjacenciesForVpnToBgp: Added Fib Entry rd {} prefix {}"
633 + " nexthop {} label {} for interface {} on dpn {} for vpn {}", rd,
634 nextHop.getIpAddress(), nextHopIp, label, interfaceName, dpnId, vpnName);
635 } catch (Exception e) {
636 LOG.error("advertiseAdjacenciesForVpnToBgp: Failed to advertise prefix {} in vpn {} with rd {}"
637 + " for interface {} on dpn {}", nextHop.getIpAddress(),
638 vpnName, rd, interfaceName, dpnId, e);
645 // TODO Clean up the exception handling
646 @SuppressWarnings("checkstyle:IllegalCatch")
647 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterfaceOpDataEntry> identifier,
648 String vpnName, String interfaceName, WriteTransaction writeConfigTxn) {
650 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
651 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
653 String rd = VpnUtil.getVpnRd(dataBroker, interfaceName);
655 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
656 interfaceName, vpnName);
659 if (rd.equals(vpnName)) {
661 "withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in "
662 + "internal vpn{} with rd {}", interfaceName, vpnName, rd);
666 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", interfaceName,
668 if (adjacencies.isPresent()) {
669 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
671 if (!nextHops.isEmpty()) {
672 LOG.trace("withdrawAdjacenciesForVpnFromBgp: NextHops are {} for interface {} in vpn {} rd {}",
673 nextHops, interfaceName, vpnName, rd);
674 for (Adjacency nextHop : nextHops) {
676 if (nextHop.getAdjacencyType() != AdjacencyType.ExtraRoute) {
677 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removing Fib Entry rd {}"
678 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
679 interfaceName, vpnName);
680 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
681 LOG.info("VPN WITHDRAW: withdrawAdjacenciesForVpnFromBgp: Removed Fib Entry rd {}"
682 + " prefix {} for interface {} in vpn {}", rd, nextHop.getIpAddress(),
683 interfaceName, vpnName);
685 // Perform similar operation as interface delete event for extraroutes.
686 String allocatedRd = nextHop.getVrfId();
687 for (String nh : nextHop.getNextHopIpList()) {
688 deleteExtraRouteFromCurrentAndImportingVpns(
689 vpnName, nextHop.getIpAddress(), nh, allocatedRd, interfaceName, writeConfigTxn);
692 } catch (Exception e) {
693 LOG.error("withdrawAdjacenciesForVpnFromBgp: Failed to withdraw prefix {} in vpn {} with rd {}"
694 + " for interface {} ", nextHop.getIpAddress(), vpnName, rd, interfaceName, e);
701 @SuppressWarnings("checkstyle:IllegalCatch")
702 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, final int lportTag, String vpnName,
703 String primaryRd, String interfaceName, final long vpnId,
704 WriteTransaction writeConfigTxn,
705 WriteTransaction writeOperTxn,
706 final WriteTransaction writeInvTxn,
707 Interface interfaceState) {
708 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
710 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
711 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
712 if (!adjacencies.isPresent()) {
713 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, null/*adjacencies*/, lportTag,
714 null/*gwMac*/, writeOperTxn);
718 // Get the rd of the vpn instance
719 String nextHopIp = null;
721 nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
722 } catch (Exception e) {
723 LOG.error("processVpnInterfaceAdjacencies: Unable to retrieve endpoint ip address for "
724 + "dpnId {} for vpnInterface {} vpnName {}", dpnId, interfaceName, vpnName);
726 List<String> nhList = new ArrayList<>();
727 if (nextHopIp != null) {
728 nhList.add(nextHopIp);
729 LOG.debug("processVpnInterfaceAdjacencies: NextHop for interface {} on dpn {} in vpn {} is {}",
730 interfaceName, dpnId, vpnName, nhList);
732 Optional<String> gwMac = Optional.absent();
733 String vpnInterfaceSubnetGwMacAddress = null;
734 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
735 Long l3vni = vpnInstanceOpData.getL3vni();
736 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(l3vni);
737 VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre;
738 VpnPopulator registeredPopulator = L3vpnRegistry.getRegisteredPopulator(encapType);
739 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
740 List<Adjacency> value = new ArrayList<>();
741 for (Adjacency nextHop : nextHops) {
742 String rd = primaryRd;
743 String nexthopIpValue = nextHop.getIpAddress().split("/")[0];
744 if (vpnInstanceOpData.getBgpvpnType() == VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet
745 && NWUtil.isIpv4Address(nexthopIpValue)) {
746 String prefix = nextHop.getIpAddress() == null ? "null" :
747 VpnUtil.getIpPrefix(nextHop.getIpAddress());
748 LOG.debug("processVpnInterfaceAdjacencies: UnsupportedOperation : Not Adding prefix {} to interface {}"
749 + " as InternetVpn has an IPV4 address {}", prefix, interfaceName, vpnName);
752 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
753 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
754 Prefixes.PrefixCue prefixCue = nextHop.isPhysNetworkFunc()
755 ? Prefixes.PrefixCue.PhysNetFunc : Prefixes.PrefixCue.None;
756 LOG.debug("processVpnInterfaceAdjacencies: Adding prefix {} to interface {} with nextHops {} on dpn {}"
757 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
759 LogicalDatastoreType.OPERATIONAL,
760 VpnUtil.getPrefixToInterfaceIdentifier(
761 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
762 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix, nextHop.getSubnetId(),
764 final Uuid subnetId = nextHop.getSubnetId();
766 String gatewayIp = nextHop.getSubnetGatewayIp();
767 if (gatewayIp == null) {
768 Optional<String> gatewayIpOptional = VpnUtil.getVpnSubnetGatewayIp(dataBroker, subnetId);
769 if (gatewayIpOptional.isPresent()) {
770 gatewayIp = gatewayIpOptional.get();
774 if (gatewayIp != null) {
775 gwMac = getMacAddressForSubnetIp(vpnName, interfaceName, gatewayIp);
776 if (gwMac.isPresent()) {
777 // A valid mac-address is available for this subnet-gateway-ip
778 // Use this for programming ARP_RESPONDER table here. And save this
779 // info into vpnInterface operational, so it can used in VrfEntryProcessor
780 // to populate L3_GW_MAC_TABLE there.
781 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
782 gatewayIp, gwMac.get());
783 vpnInterfaceSubnetGwMacAddress = gwMac.get();
785 // A valid mac-address is not available for this subnet-gateway-ip
786 // Use the connected-mac-address to configure ARP_RESPONDER Table.
787 // Save this connected-mac-address as gateway-mac-address for the
788 // VrfEntryProcessor to use this later to populate the L3_GW_MAC_TABLE.
789 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
790 if (gwMac.isPresent()) {
791 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
792 vpnId, writeInvTxn, NwConstants.ADD_FLOW, gwMac.get());
793 arpResponderHandler.addArpResponderFlow(dpnId, lportTag, interfaceName,
794 gatewayIp, gwMac.get());
796 LOG.error("processVpnInterfaceAdjacencies: Gateway MAC for subnet ID {} could not be "
797 + "obtained, cannot create ARP responder flow for interface name {}, vpnName {}, "
799 interfaceName, vpnName, gatewayIp);
803 LOG.warn("processVpnInterfaceAdjacencies: Gateway IP for subnet ID {} could not be obtained, "
804 + "cannot create ARP responder flow for interface name {}, vpnName {}",
805 subnetId, interfaceName, vpnName);
806 gwMac = InterfaceUtils.getMacAddressFromInterfaceState(interfaceState);
808 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} to interface {} with nextHops {} on dpn {}"
809 + " for vpn {}", prefix, interfaceName, nhList, dpnId, vpnName);
811 //Extra route adjacency
812 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
813 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
814 synchronized (vpnPrefixKey.intern()) {
815 java.util.Optional<String> rdToAllocate = VpnUtil
816 .allocateRdForExtraRouteAndUpdateUsedRdsMap(dataBroker, vpnId, null,
817 prefix, vpnName, nextHop.getNextHopIpList().get(0), dpnId);
818 if (rdToAllocate.isPresent()) {
819 rd = rdToAllocate.get();
820 LOG.info("processVpnInterfaceAdjacencies: The rd {} is allocated for the extraroute {}",
823 LOG.error("processVpnInterfaceAdjacencies: No rds to allocate extraroute {}", prefix);
827 LOG.info("processVpnInterfaceAdjacencies: Added prefix {} and nextHopList {} as extra-route for vpn{}"
828 + " interface {} on dpn {}", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName,
829 interfaceName, dpnId);
831 // Please note that primary adjacency will use a subnet-gateway-mac-address that
832 // can be different from the gateway-mac-address within the VRFEntry as the
833 // gateway-mac-address is a superset.
834 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
835 : RouteOrigin.STATIC;
836 L3vpnInput input = new L3vpnInput().setNextHop(nextHop).setRd(rd).setVpnName(vpnName)
837 .setInterfaceName(interfaceName).setNextHopIp(nextHopIp).setPrimaryRd(primaryRd)
838 .setSubnetGatewayMacAddress(vpnInterfaceSubnetGwMacAddress).setRouteOrigin(origin);
839 Adjacency operationalAdjacency = null;
841 operationalAdjacency = registeredPopulator.createOperationalAdjacency(input);
842 } catch (NullPointerException e) {
843 LOG.error("processVpnInterfaceAdjacencies: failed to create operational adjacency: input: {}, {}",
844 input, e.getMessage());
847 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
848 vpnManager.addExtraRoute(vpnName, nextHop.getIpAddress(), nextHop.getNextHopIpList().get(0), rd,
849 vpnName, l3vni, origin,
850 interfaceName, operationalAdjacency, encapType, writeConfigTxn);
852 value.add(operationalAdjacency);
855 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
856 addVpnInterfaceToOperational(vpnName, interfaceName, dpnId, aug, lportTag,
857 gwMac.isPresent() ? gwMac.get() : null, writeOperTxn);
859 L3vpnInput input = new L3vpnInput().setNextHopIp(nextHopIp).setL3vni(l3vni).setPrimaryRd(primaryRd)
860 .setGatewayMac(gwMac.orNull()).setInterfaceName(interfaceName)
861 .setVpnName(vpnName).setDpnId(dpnId).setEncapType(encapType);
863 for (Adjacency nextHop : aug.getAdjacency()) {
864 // Adjacencies other than primary Adjacencies are handled in the addExtraRoute call above.
865 if (nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
866 RouteOrigin origin = nextHop.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
867 : RouteOrigin.STATIC;
868 input.setNextHop(nextHop).setRd(nextHop.getVrfId()).setRouteOrigin(origin);
869 registeredPopulator.populateFib(input, writeConfigTxn);
874 private void addVpnInterfaceToOperational(String vpnName, String interfaceName, BigInteger dpnId, AdjacenciesOp aug,
875 long lportTag, String gwMac, WriteTransaction writeOperTxn) {
876 VpnInterfaceOpDataEntry opInterface =
877 VpnUtil.getVpnInterfaceOpDataEntry(interfaceName, vpnName, aug, dpnId, Boolean.FALSE, lportTag, gwMac);
878 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId = VpnUtil
879 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
880 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
881 WriteTransaction.CREATE_MISSING_PARENTS);
882 LOG.info("addVpnInterfaceToOperational: Added VPN Interface {} on dpn {} vpn {} to operational datastore",
883 interfaceName, dpnId, vpnName);
886 // TODO Clean up the exception handling
887 @SuppressWarnings("checkstyle:IllegalCatch")
888 public void updateVpnInterfaceOnTepAdd(VpnInterfaceOpDataEntry vpnInterface,
889 StateTunnelList stateTunnelList,
890 WriteTransaction writeConfigTxn,
891 WriteTransaction writeOperTxn) {
893 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
894 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
895 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
896 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
897 if (adjList.isEmpty()) {
898 LOG.trace("updateVpnInterfaceOnTepAdd: Adjacencies are empty for vpnInterface {} on dpn {}",
899 vpnInterface, srcDpnId);
902 String prefix = null;
904 List<Adjacency> value = new ArrayList<>();
905 boolean isNextHopAddReqd = false;
906 String vpnName = vpnInterface.getVpnInstanceName();
907 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
908 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
909 LOG.info("updateVpnInterfaceOnTepAdd: AdjacencyList for interface {} on dpn {} vpn {} is {}",
910 vpnInterface.getName(), vpnInterface.getDpnId(),
911 vpnInterface.getVpnInstanceName(), adjList);
912 for (Adjacency adj : adjList) {
913 String rd = adj.getVrfId();
914 rd = rd != null ? rd : vpnName;
915 prefix = adj.getIpAddress();
916 label = adj.getLabel();
917 List<String> nhList = Collections.singletonList(srcTepIp);
918 List<String> nextHopList = adj.getNextHopIpList();
919 // If TEP is added , update the nexthop of primary adjacency.
920 // Secondary adj nexthop is already pointing to primary adj IP address.
921 if (nextHopList != null && !nextHopList.isEmpty() && nextHopList.get(0).equalsIgnoreCase(srcTepIp)) {
922 /* everything right already */
924 isNextHopAddReqd = true;
927 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
928 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
930 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
931 if (!vrfEntryOptional.isPresent()) {
934 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
935 if (!nhList.contains(srcTepIp)) {
936 nhList.add(srcTepIp);
937 isNextHopAddReqd = true;
942 if (isNextHopAddReqd) {
943 updateLabelMapper(label, nhList);
944 LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
945 + " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
946 vpnInterface.getVpnInstanceName(), vpnId, rd, vpnInterface.getName());
947 // Update the VRF entry with nextHop
948 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
949 label, true, writeConfigTxn);
951 //Get the list of VPN's importing this route(prefix) .
952 // Then update the VRF entry with nhList
953 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
954 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
955 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
956 String vpnRd = vpn.getVrfId();
958 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
959 srcTepIp, label, true, writeConfigTxn);
960 LOG.info("updateVpnInterfaceOnTepAdd: Exported route with rd {} prefix {} nhList {} label {}"
961 + " interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix, nhList, label,
962 vpnInterface.getName(), srcDpnId, vpnName,
963 vpn.getVpnInstanceName(), vpnRd);
966 // Advertise the prefix to BGP only for external vpn
967 // since there is a nexthop change.
969 if (!rd.equalsIgnoreCase(vpnName)) {
970 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, nhList,
971 VrfEntry.EncapType.Mplsgre, (int)label, 0 /*evi*/, 0 /*l2vni*/,
972 null /*gatewayMacAddress*/);
974 LOG.info("updateVpnInterfaceOnTepAdd: Advertised rd {} prefix {} nhList {} label {}"
975 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label, vpnInterface.getName(),
977 } catch (Exception ex) {
978 LOG.error("updateVpnInterfaceOnTepAdd: Exception when advertising prefix {} nh {} label {}"
979 + " on rd {} for interface {} on dpn {} vpn {} as {}", prefix, nhList, label, rd,
980 vpnInterface.getName(), srcDpnId,
985 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
986 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
987 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
988 .addAugmentation(AdjacenciesOp.class, aug).build();
989 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
990 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
991 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
992 WriteTransaction.CREATE_MISSING_PARENTS);
993 LOG.info("updateVpnInterfaceOnTepAdd: interface {} updated successully on tep add on dpn {} vpn {}",
994 vpnInterface.getName(), srcDpnId, vpnName);
998 // TODO Clean up the exception handling
999 @SuppressWarnings("checkstyle:IllegalCatch")
1000 public void updateVpnInterfaceOnTepDelete(VpnInterfaceOpDataEntry vpnInterface,
1001 StateTunnelList stateTunnelList,
1002 WriteTransaction writeConfigTxn,
1003 WriteTransaction writeOperTxn) {
1005 AdjacenciesOp adjacencies = vpnInterface.getAugmentation(AdjacenciesOp.class);
1006 List<Adjacency> adjList = adjacencies != null ? adjacencies.getAdjacency() : new ArrayList<>();
1007 String prefix = null;
1009 boolean isNextHopRemoveReqd = false;
1010 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
1011 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
1012 String vpnName = vpnInterface.getVpnInstanceName();
1013 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1014 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1015 if (adjList != null) {
1016 List<Adjacency> value = new ArrayList<>();
1017 LOG.info("updateVpnInterfaceOnTepDelete: AdjacencyList for interface {} on dpn {} vpn {} is {}",
1018 vpnInterface.getName(), vpnInterface.getDpnId(),
1019 vpnInterface.getVpnInstanceName(), adjList);
1020 for (Adjacency adj : adjList) {
1021 List<String> nhList = new ArrayList<>();
1022 String rd = adj.getVrfId();
1023 rd = rd != null ? rd : vpnName;
1024 prefix = adj.getIpAddress();
1025 List<String> nextHopList = adj.getNextHopIpList();
1026 label = adj.getLabel();
1027 if (nextHopList != null && !nextHopList.isEmpty()) {
1028 isNextHopRemoveReqd = true;
1030 // If TEP is deleted , remove the nexthop from primary adjacency.
1031 // Secondary adj nexthop will continue to point to primary adj IP address.
1032 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1033 value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
1035 Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
1036 if (!vrfEntryOptional.isPresent()) {
1039 nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
1040 if (nhList.contains(srcTepIp)) {
1041 nhList.remove(srcTepIp);
1042 isNextHopRemoveReqd = true;
1047 if (isNextHopRemoveReqd) {
1048 updateLabelMapper(label, nhList);
1049 LOG.info("updateVpnInterfaceOnTepDelete: Updated label mapper : label {} dpn {} prefix {}"
1050 + " nexthoplist {} vpn {} vpnid {} rd {} interface {}", label, srcDpnId,
1051 prefix, nhList, vpnName,
1052 vpnId, rd, vpnInterface.getName());
1053 // Update the VRF entry with removed nextHop
1054 fibManager.updateRoutePathForFibEntry(primaryRd, prefix, srcTepIp,
1055 label, false, writeConfigTxn);
1057 //Get the list of VPN's importing this route(prefix) .
1058 // Then update the VRF entry with nhList
1059 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1060 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1061 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1062 String vpnRd = vpn.getVrfId();
1063 if (vpnRd != null) {
1064 fibManager.updateRoutePathForFibEntry(vpnRd, prefix,
1065 srcTepIp, label, false, writeConfigTxn);
1066 LOG.info("updateVpnInterfaceOnTepDelete: Exported route with rd {} prefix {} nhList {}"
1067 + " label {} interface {} dpn {} from vpn {} to VPN {} vpnRd {}", rd, prefix,
1068 nhList, label, vpnInterface.getName(), srcDpnId,
1070 vpn.getVpnInstanceName(), vpnRd);
1074 // Withdraw prefix from BGP only for external vpn.
1076 if (!rd.equalsIgnoreCase(vpnName)) {
1077 bgpManager.withdrawPrefix(rd, prefix);
1079 LOG.info("updateVpnInterfaceOnTepDelete: Withdrawn rd {} prefix {} nhList {} label {}"
1080 + " for interface {} on dpn {} vpn {}", rd, prefix, nhList, label,
1081 vpnInterface.getName(), srcDpnId,
1083 } catch (Exception ex) {
1084 LOG.error("updateVpnInterfaceOnTepDelete: Exception when withdrawing prefix {} nh {} label {}"
1085 + " on rd {} for interface {} on dpn {} vpn {} as {}", prefix, nhList, label, rd,
1086 vpnInterface.getName(), srcDpnId,
1091 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(value);
1092 VpnInterfaceOpDataEntry opInterface = new VpnInterfaceOpDataEntryBuilder(vpnInterface)
1093 .setKey(new VpnInterfaceOpDataEntryKey(vpnInterface.getName(), vpnName))
1094 .addAugmentation(AdjacenciesOp.class, aug).build();
1095 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1096 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getName(), vpnName);
1097 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface,
1098 WriteTransaction.CREATE_MISSING_PARENTS);
1099 LOG.info("updateVpnInterfaceOnTepDelete: interface {} updated successully on tep delete on dpn {} vpn {}",
1100 vpnInterface.getName(), srcDpnId, vpnName);
1104 private List<VpnInstanceOpDataEntry> getVpnsExportingMyRoute(final String vpnName) {
1105 List<VpnInstanceOpDataEntry> vpnsToExportRoute = new ArrayList<>();
1107 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1108 final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
1109 if (vpnInstanceOpDataEntry == null) {
1110 LOG.debug("getVpnsExportingMyRoute: Could not retrieve vpn instance op data for {}"
1111 + " to check for vpns exporting the routes", vpnName);
1112 return vpnsToExportRoute;
1115 Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1116 if (input.getVpnInstanceName() == null) {
1117 LOG.error("getVpnsExportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name",
1121 return !input.getVpnInstanceName().equals(vpnName);
1124 Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1125 Iterable<String> commonRTs =
1126 VpnUtil.intersection(VpnUtil.getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ImportExtcommunity),
1127 VpnUtil.getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
1128 return Iterators.size(commonRTs.iterator()) > 0;
1132 VpnUtil.getAllVpnInstanceOpData(dataBroker).stream().filter(excludeVpn).filter(matchRTs).collect(
1133 Collectors.toList());
1134 return vpnsToExportRoute;
1137 // TODO Clean up the exception handling
1138 @SuppressWarnings("checkstyle:IllegalCatch")
1139 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1140 List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1141 for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
1142 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getVrfId());
1143 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1144 if (vrfEntries != null) {
1145 for (VrfEntry vrfEntry : vrfEntries) {
1147 if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(
1148 RouteOrigin.value(vrfEntry.getOrigin()))) {
1149 LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}"
1150 + " is not a controller managed non intervpn link route. Ignoring.",
1151 vpn.getVrfId(), vrfEntry.getDestPrefix());
1154 String prefix = vrfEntry.getDestPrefix();
1155 String gwMac = vrfEntry.getGatewayMacAddress();
1156 vrfEntry.getRoutePaths().forEach(routePath -> {
1157 String nh = routePath.getNexthopAddress();
1158 int label = routePath.getLabel().intValue();
1159 if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(
1160 vrfEntry.getOrigin()))) {
1161 LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}"
1162 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1164 fibManager.addOrUpdateFibEntry(vpnRd, null /*macAddress*/, prefix,
1165 Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label,
1166 0 /*l3vni*/, gwMac, null /*parentVpnRd*/, RouteOrigin.SELF_IMPORTED,
1169 LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} prefix {}"
1170 + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label,
1172 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1173 importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, writeConfigTxn);
1176 } catch (RuntimeException e) {
1177 LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}"
1178 + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(),
1179 vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
1182 writeConfigTxn.submit();
1184 LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}",
1185 vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
1190 @SuppressWarnings("checkstyle:IllegalCatch")
1192 public void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1193 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1194 final String interfaceName = key.getName();
1195 for (VpnInstanceNames vpnInterfaceVpnInstance : vpnInterface.getVpnInstanceNames()) {
1196 String vpnName = vpnInterfaceVpnInstance.getVpnName();
1197 removeVpnInterfaceCall(identifier, vpnInterface, vpnName, interfaceName);
1201 private void removeVpnInterfaceCall(final InstanceIdentifier<VpnInterface> identifier,
1202 final VpnInterface vpnInterface, final String vpnName,
1203 final String interfaceName) {
1204 if (Boolean.TRUE.equals(vpnInterface.isRouterInterface())) {
1205 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getName() + vpnName, () -> {
1206 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1207 deleteFibEntryForRouterInterface(vpnInterface, writeConfigTxn, vpnName);
1208 LOG.info("remove: Router interface {} for vpn {}", interfaceName, vpnName);
1209 ListenableFuture<Void> futures = writeConfigTxn.submit();
1210 String errorText = "removeVpnInterfaceCall: Exception encountered while submitting writeConfigTxn"
1211 + " for interface " + vpnInterface.getName() + " on vpn " + vpnName;
1212 ListenableFutures.addErrorLogging(futures, LOG, errorText);
1213 return Collections.singletonList(futures);
1214 }, DJC_MAX_RETRIES);
1216 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1217 removeVpnInterfaceFromVpn(identifier, vpnInterface, vpnName, interfaceName, interfaceState);
1221 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
1222 private void removeVpnInterfaceFromVpn(final InstanceIdentifier<VpnInterface> identifier,
1223 final VpnInterface vpnInterface, final String vpnName,
1224 final String interfaceName, final Interface interfaceState) {
1225 LOG.info("remove: VPN Interface remove event - intfName {} vpn {} dpn {}" ,vpnInterface.getName(),
1226 vpnName, vpnInterface.getDpnId());
1227 removeInterfaceFromUnprocessedList(identifier, vpnInterface);
1228 jobCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName + vpnName,
1230 List<ListenableFuture<Void>> futures = new ArrayList<>(3);
1231 ListenableFuture<Void> configFuture = txRunner
1232 .callWithNewWriteOnlyTransactionAndSubmit(writeConfigTxn -> {
1233 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeOperTxn -> {
1234 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(writeInvTxn -> {
1235 LOG.info("remove: - intfName {} onto vpnName {} running config-driven",
1236 interfaceName, vpnName);
1237 BigInteger dpId = BigInteger.ZERO;
1239 String gwMacAddress = null;
1240 InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
1241 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1242 final Optional<VpnInterfaceOpDataEntry> optVpnInterface =
1243 VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1244 if (interfaceState != null) {
1246 dpId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1247 } catch (NumberFormatException | IllegalStateException e) {
1248 LOG.error("remove: Unable to retrieve dpnId from interface operational"
1249 + " data store for interface {} on dpn {} for vpn {} Fetching"
1250 + " from vpn interface op data store. ", interfaceName,
1251 vpnInterface.getDpnId(), vpnName, e);
1252 dpId = BigInteger.ZERO;
1254 ifIndex = interfaceState.getIfIndex();
1255 gwMacAddress = interfaceState.getPhysAddress().getValue();
1257 LOG.info("remove: Interface state not available for {}. Trying to fetch data"
1258 + " from vpn interface op.", interfaceName);
1259 if (optVpnInterface.isPresent()) {
1260 VpnInterfaceOpDataEntry vpnOpInterface = optVpnInterface.get();
1261 dpId = vpnOpInterface.getDpnId();
1262 ifIndex = vpnOpInterface.getLportTag().intValue();
1263 gwMacAddress = vpnOpInterface.getGatewayMacAddress();
1265 LOG.error("remove: Handling removal of VPN interface {} for vpn {} skipped"
1266 + " as interfaceState and vpn interface op is not"
1267 + " available", interfaceName, vpnName);
1271 processVpnInterfaceDown(dpId, interfaceName, ifIndex, gwMacAddress,
1272 optVpnInterface.isPresent() ? optVpnInterface.get() : null, false,
1273 writeConfigTxn, writeOperTxn, writeInvTxn);
1275 "remove: Removal of vpn interface {} on dpn {} for vpn {} processed "
1277 interfaceName, vpnInterface.getDpnId(), vpnName);
1281 futures.add(configFuture);
1282 Futures.addCallback(configFuture, new PostVpnInterfaceWorker(interfaceName, false, "Config"));
1284 }, DJC_MAX_RETRIES);
1287 protected void processVpnInterfaceDown(BigInteger dpId,
1288 String interfaceName,
1291 VpnInterfaceOpDataEntry vpnOpInterface,
1292 boolean isInterfaceStateDown,
1293 WriteTransaction writeConfigTxn,
1294 WriteTransaction writeOperTxn,
1295 WriteTransaction writeInvTxn) {
1296 if (vpnOpInterface == null) {
1297 LOG.error("processVpnInterfaceDown: Unable to process delete/down for interface {} on dpn {}"
1298 + " as it is not available in operational data store", interfaceName, dpId);
1301 final String vpnName = vpnOpInterface.getVpnInstanceName();
1302 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil.getVpnInterfaceOpDataEntryIdentifier(
1303 interfaceName, vpnName);
1304 if (!isInterfaceStateDown) {
1305 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1306 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE,
1308 final boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, vpnName);
1309 removeAdjacenciesFromVpn(dpId, lportTag, interfaceName, vpnName,
1310 vpnId, gwMac, writeConfigTxn, writeOperTxn, writeInvTxn);
1311 if (interfaceManager.isExternalInterface(interfaceName)) {
1312 processExternalVpnInterface(interfaceName, vpnName, vpnId, dpId, lportTag, writeInvTxn,
1313 NwConstants.DEL_FLOW);
1315 if (!isBgpVpnInternetVpn) {
1316 VpnUtil.unbindService(dataBroker, interfaceName, isInterfaceStateDown, jobCoordinator);
1318 LOG.info("processVpnInterfaceDown: Unbound vpn service from interface {} on dpn {} for vpn {}"
1319 + " successful", interfaceName, dpId, vpnName);
1321 // Interface is retained in the DPN, but its Link Down.
1322 // Only withdraw the prefixes for this interface from BGP
1323 withdrawAdjacenciesForVpnFromBgp(identifier, vpnName, interfaceName, writeConfigTxn);
1327 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final int lportTag, final String interfaceName,
1328 final String vpnName, final long vpnId, String gwMac,
1329 WriteTransaction writeConfigTxn, final WriteTransaction writeOperTxn,
1330 final WriteTransaction writeInvTxn) {
1332 InstanceIdentifier<VpnInterfaceOpDataEntry> identifier = VpnUtil
1333 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
1334 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1335 Optional<AdjacenciesOp> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1337 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
1338 LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
1339 interfaceName, dpnId, vpnName, primaryRd);
1340 if (adjacencies.isPresent() && !adjacencies.get().getAdjacency().isEmpty()) {
1341 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1342 LOG.info("removeAdjacenciesFromVpn: NextHops for interface {} on dpn {} for vpn {} are {}",
1343 interfaceName, dpnId, vpnName, nextHops);
1344 for (Adjacency nextHop : nextHops) {
1345 if (nextHop.isPhysNetworkFunc()) {
1346 LOG.info("removeAdjacenciesFromVpn: Removing PNF FIB entry rd {} prefix {}",
1347 nextHop.getSubnetId().getValue(), nextHop.getIpAddress());
1348 fibManager.removeFibEntry(nextHop.getSubnetId().getValue(), nextHop.getIpAddress(),
1349 null/*writeCfgTxn*/);
1351 String rd = nextHop.getVrfId();
1352 List<String> nhList;
1353 if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
1354 nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
1356 // This is a primary adjacency
1357 nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
1358 : Collections.emptyList();
1359 removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
1360 interfaceName, writeInvTxn);
1362 if (!nhList.isEmpty()) {
1363 if (rd.equals(vpnName)) {
1364 //this is an internal vpn - the rd is assigned to the vpn instance name;
1365 //remove from FIB directly
1366 nhList.forEach((nh) -> removeAdjacencyFromInternalVpn(nextHop, vpnName,
1367 interfaceName, dpnId, writeConfigTxn));
1369 removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd, interfaceName,
1373 LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
1374 + " interface {}", nextHop.getIpAddress(), rd,
1375 nextHop.getAdjacencyType().toString(), interfaceName);
1376 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
1377 fibManager.removeFibEntry(primaryRd, nextHop.getIpAddress(), writeConfigTxn);
1380 String ip = nextHop.getIpAddress().split("/")[0];
1381 LearntVpnVipToPort vpnVipToPort = VpnUtil.getLearntVpnVipToPort(dataBroker, vpnName, ip);
1382 if (vpnVipToPort != null) {
1383 VpnUtil.removeLearntVpnVipToPort(dataBroker, vpnName, ip);
1384 LOG.info("removeAdjacenciesFromVpn: VpnInterfaceManager removed adjacency for Interface {}"
1385 + " ip {} on dpn {} for vpn {} from VpnPortData Entry", vpnVipToPort.getPortName(),
1386 ip, dpnId, vpnName);
1390 // this vpn interface has no more adjacency left, so clean up the vpn interface from Operational DS
1391 LOG.info("removeAdjacenciesFromVpn: Vpn Interface {} on vpn {} dpn {} has no adjacencies."
1392 + " Removing it.", interfaceName, vpnName, dpnId);
1393 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, identifier);
1397 private Consumer<String> removeAdjacencyFromInternalVpn(Adjacency nextHop, String vpnName,
1398 String interfaceName, BigInteger dpnId,
1399 WriteTransaction writeConfigTxn) {
1401 fibManager.removeOrUpdateFibEntry(vpnName, nextHop.getIpAddress(), nh,
1403 LOG.info("removeAdjacenciesFromVpn: removed/updated FIB with rd {} prefix {}"
1404 + " nexthop {} for interface {} on dpn {} for internal vpn {}",
1405 vpnName, nextHop.getIpAddress(), nh, interfaceName, dpnId, vpnName);
1409 private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
1410 BigInteger dpnId, String rd, String interfaceName,
1411 WriteTransaction writeConfigTxn) {
1412 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1413 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1414 nhList.forEach((nh) -> {
1415 //IRT: remove routes from other vpns importing it
1416 vpnManager.removePrefixFromBGP(primaryRd, rd, vpnName, nextHop.getIpAddress(),
1417 nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn);
1418 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1419 String vpnRd = vpn.getVrfId();
1420 if (vpnRd != null) {
1421 fibManager.removeOrUpdateFibEntry(vpnRd,
1422 nextHop.getIpAddress(), nh, writeConfigTxn);
1423 LOG.info("removeAdjacenciesFromVpn: Removed Exported route with rd {}"
1424 + " prefix {} nextHop {} from VPN {} parentVpn {}"
1425 + " for interface {} on dpn {}", vpnRd, nextHop.getIpAddress(), nh,
1426 vpn.getVpnInstanceName(), vpnName, interfaceName, dpnId);
1432 private void removeGwMacAndArpResponderFlows(Adjacency nextHop, long vpnId, BigInteger dpnId,
1433 int lportTag, String gwMac, String interfaceName,
1434 WriteTransaction writeInvTxn) {
1435 final Uuid subnetId = nextHop.getSubnetId();
1436 if (nextHop.getSubnetGatewayMacAddress() == null) {
1437 // A valid mac-address was not available for this subnet-gateway-ip
1438 // So a connected-mac-address was used for this subnet and we need
1439 // to remove the flows for the same here from the L3_GW_MAC_TABLE.
1440 VpnUtil.setupGwMacIfExternalVpn(dataBroker, mdsalManager, dpnId, interfaceName,
1441 vpnId, writeInvTxn, NwConstants.DEL_FLOW, gwMac);
1443 arpResponderHandler.removeArpResponderFlow(dpnId, lportTag, interfaceName, nextHop.getSubnetGatewayIp(),
1447 private List<String> getNextHopForNonPrimaryAdjacency(Adjacency nextHop, String vpnName, BigInteger dpnId,
1448 String interfaceName) {
1449 // This is either an extra-route (or) a learned IP via subnet-route
1450 List<String> nhList = null;
1451 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1452 if (nextHopIp == null || nextHopIp.isEmpty()) {
1453 LOG.error("removeAdjacenciesFromVpn: Unable to obtain nextHopIp for"
1454 + " extra-route/learned-route in rd {} prefix {} interface {} on dpn {}"
1455 + " for vpn {}", nextHop.getVrfId(), nextHop.getIpAddress(), interfaceName, dpnId,
1457 nhList = Collections.emptyList();
1459 nhList = Collections.singletonList(nextHopIp);
1464 private Optional<String> getMacAddressForSubnetIp(String vpnName, String ifName, String ipAddress) {
1465 VpnPortipToPort gwPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, ipAddress);
1466 //Check if a router gateway interface is available for the subnet gw is so then use Router interface
1467 // else use connected interface
1468 if (gwPort != null && gwPort.isSubnetIp()) {
1469 LOG.info("getGatewayMacAddressForSubnetIp: Retrieved gw Mac as {} for ip {} interface {} vpn {}",
1470 gwPort.getMacAddress(), ipAddress, ifName, vpnName);
1471 return Optional.of(gwPort.getMacAddress());
1473 return Optional.absent();
1477 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
1478 final VpnInterface update) {
1479 LOG.info("update: VPN Interface update event - intfName {} on dpn {} oldVpn {} newVpn {}" ,update.getName(),
1480 update.getDpnId(), original.getVpnInstanceNames(),
1481 update.getVpnInstanceNames());
1482 final String vpnInterfaceName = update.getName();
1483 final BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1484 final Adjacencies origAdjs = original.getAugmentation(Adjacencies.class);
1485 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency()
1486 != null ? origAdjs.getAdjacency() : new ArrayList<>();
1487 final Adjacencies updateAdjs = update.getAugmentation(Adjacencies.class);
1488 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency()
1489 != null ? updateAdjs.getAdjacency() : new ArrayList<>();
1491 LOG.info("VPN Interface update event - intfName {}", vpnInterfaceName);
1492 //handles switching between <internal VPN - external VPN>
1493 for (VpnInstanceNames vpnInterfaceVpnInstance : original.getVpnInstanceNames()) {
1494 String oldVpnName = vpnInterfaceVpnInstance.getVpnName();
1495 if (oldVpnName != null && (update.getVpnInstanceNames() == null
1496 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnName, update.getVpnInstanceNames()))) {
1497 UpdateData updateData = new UpdateData(identifier, original, update);
1498 vpnInterfacesUpdateQueue.add(updateData);
1499 LOG.info("update: UpdateData on VPNInterface {} on dpn {} update upon VPN swap from oldVpn(s) {}"
1500 + "to newVpn(s) {} added to update queue",
1501 updateData.getOriginal().getName(), dpnId,
1502 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1503 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1507 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1508 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1509 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1510 if (newVpnName != null && (original.getVpnInstanceNames() == null
1511 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(newVpnName,
1512 original.getVpnInstanceNames()))) {
1513 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1514 InstanceIdentifier<VpnInterfaceOpDataEntry> opIdentifier = VpnUtil
1515 .getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1516 if (canHandleNewVpnInterface(identifier, update, newVpnName)) {
1517 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1518 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1519 addVpnInterfaceToVpn(opIdentifier, update, copyOldAdjs, copyNewAdjs, identifier, newVpnName);
1522 UpdateData updateData = new UpdateData(identifier, original, update);
1523 vpnInterfacesUpdateQueue.add(updateData);
1524 LOG.info("update: UpdateData on VPNInterface {} on dpn {} update upon VPN swap from oldVpn(s) {}"
1525 + "to newVpn(s) {} added to update queue",
1526 updateData.getOriginal().getName(), dpnId,
1527 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()),
1528 VpnHelper.getVpnInterfaceVpnInstanceNamesString(update.getVpnInstanceNames()));
1533 for (VpnInstanceNames vpnInterfaceVpnInstance : update.getVpnInstanceNames()) {
1534 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1535 List<Adjacency> copyNewAdjs = new ArrayList<>(newAdjs);
1536 List<Adjacency> copyOldAdjs = new ArrayList<>(oldAdjs);
1537 String primaryRd = VpnUtil.getPrimaryRd(dataBroker, newVpnName);
1538 if (!VpnUtil.isVpnPendingDelete(dataBroker, primaryRd)) {
1539 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName + newVpnName, () -> {
1540 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1541 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1542 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier =
1543 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, newVpnName);
1544 LOG.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven",
1545 update.getName(), newVpnName);
1546 //handle both addition and removal of adjacencies
1547 //currently, new adjacency may be an extra route
1548 boolean isBgpVpnInternetVpn = VpnUtil.isBgpVpnInternet(dataBroker, newVpnName);
1549 if (!oldAdjs.equals(newAdjs)) {
1550 for (Adjacency adj : copyNewAdjs) {
1551 if (copyOldAdjs.contains(adj)) {
1552 copyOldAdjs.remove(adj);
1554 // add new adjacency - right now only extra route will hit this path
1555 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1556 addNewAdjToVpnInterface(vpnInterfaceOpIdentifier, primaryRd, adj,
1557 dpnId, writeOperTxn, writeConfigTxn);
1559 LOG.info("update: new Adjacency {} with nextHop {} label {} subnet {} added to vpn "
1560 + "interface {} on vpn {} dpnId {}",
1561 adj.getIpAddress(), adj.getNextHopIpList(),
1562 adj.getLabel(), adj.getSubnetId(), update.getName(),
1566 for (Adjacency adj : copyOldAdjs) {
1567 if (!isBgpVpnInternetVpn || VpnUtil.isAdjacencyEligibleToVpnInternet(dataBroker, adj)) {
1568 delAdjFromVpnInterface(vpnInterfaceOpIdentifier, adj, dpnId,
1569 writeOperTxn, writeConfigTxn);
1571 LOG.info("update: Adjacency {} with nextHop {} label {} subnet {} removed from"
1572 + " vpn interface {} on vpn {}", adj.getIpAddress(), adj.getNextHopIpList(),
1573 adj.getLabel(), adj.getSubnetId(), update.getName(), newVpnName);
1576 ListenableFuture<Void> operFuture = writeOperTxn.submit();
1579 } catch (ExecutionException e) {
1580 LOG.error("Exception encountered while submitting operational future for update"
1581 + " VpnInterface {} on vpn {}: {}", vpnInterfaceName, newVpnName, e);
1584 List<ListenableFuture<Void>> futures = new ArrayList<>();
1585 futures.add(writeConfigTxn.submit());
1586 LOG.info("update: vpn interface updated for interface {} oldVpn(s) {} newVpn {}"
1587 + "processed successfully", update.getName(),
1588 VpnHelper.getVpnInterfaceVpnInstanceNamesString(original.getVpnInstanceNames()), newVpnName);
1592 LOG.error("update: Ignoring update of vpnInterface {}, as newVpnInstance {} with primaryRd {}"
1593 + " is already marked for deletion", vpnInterfaceName, newVpnName, primaryRd);
1598 @SuppressWarnings("checkstyle:IllegalCatch")
1599 private class VpnInterfaceUpdateTimerTask implements Runnable {
1600 private final Logger log = LoggerFactory.getLogger(VpnInterfaceUpdateTimerTask.class);
1606 } catch (ReadFailedException | RuntimeException e) {
1607 LOG.error("VpnInterfaceUpdateTimerTask failed", e);
1611 private void doRun() throws ReadFailedException {
1612 List<UpdateData> processQueue = new ArrayList<>();
1613 List<UpdateData> updateDataList = new ArrayList<>();
1614 vpnInterfacesUpdateQueue.drainTo(processQueue);
1615 int maxInterfaceList = 0;
1617 for (UpdateData updData : processQueue) {
1618 final VpnInterfaceKey key = updData.getIdentifier()
1619 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1620 final String interfaceName = key.getName();
1621 Interface interfaceState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1622 for (VpnInstanceNames vpnInterfaceVpnInstance : updData.getOriginal().getVpnInstanceNames()) {
1623 String oldVpnName = vpnInterfaceVpnInstance.getVpnName();
1624 if (updData.getUpdate().getVpnInstanceNames() != null
1625 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnName,
1626 updData.getUpdate().getVpnInstanceNames())) {
1629 log.info("run: VPN Interface update event - intfName {} remove vpnName {} running"
1630 + " config-driven swap removal", updData.getOriginal().getName(), oldVpnName);
1631 maxInterfaceList ++;
1632 removeVpnInterfaceCall(updData.getIdentifier(), updData.getOriginal(),
1633 oldVpnName, interfaceName);
1634 log.info("run: Processed Remove for update on VPNInterface {} upon VPN swap from old vpn {}"
1635 + " to newVpn(s) {}", updData.getOriginal().getName(),
1636 oldVpnName, VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData
1637 .getUpdate().getVpnInstanceNames()));
1639 updateDataList.add(updData);
1641 /* Decide the max-wait time based on number of VpnInterfaces.
1642 * max-wait-time is num-of-interface * 4seconds (random choice).
1643 * Every 2sec poll VpnToDpnList. If VpnInterface is removed ,
1644 * remove it from vpnInterfaceList.
1647 maxInterfaceList * (int) (VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS / 1000);
1649 Iterator<UpdateData> updateDataIterator = updateDataList.iterator();
1650 UpdateData updateDataSet;
1651 while (waitTime < maxWaitTime) {
1653 Thread.sleep(2000); // sleep for 2sec
1654 } catch (InterruptedException e) {
1658 while (updateDataIterator.hasNext()) {
1659 boolean interfaceIsRemoved = true;
1660 updateDataSet = updateDataIterator.next();
1661 for (VpnInstanceNames vpnInterfaceVpnInstance : updateDataSet.getOriginal().getVpnInstanceNames()) {
1662 String oldVpnName = vpnInterfaceVpnInstance.getVpnName();
1663 if (oldVpnName != null && updateDataSet.getUpdate().getVpnInstanceNames() != null
1664 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnName,
1665 updateDataSet.getUpdate().getVpnInstanceNames())) {
1669 boolean isPresent = isVpnIntfPresentInVpnToDpnList(updateDataSet.getOriginal(), oldVpnName);
1671 interfaceIsRemoved = false;
1674 if (interfaceIsRemoved) {
1675 updateDataIterator.remove();
1678 if (updateDataList.isEmpty()) {
1679 log.info("run: All VpnInterfaces are successfully removed from OLD VPN after time {}", waitTime);
1682 waitTime += 2; //Increment linearly by 2sec.
1685 if (updateDataList.size() > 0) {
1686 log.error("run: VpnInterfacesList not removed from old Vpn even after waiting {}", waitTime);
1688 for (UpdateData updData : processQueue) {
1689 if (updateDataList.contains(updData)) {
1690 log.error("run: Failed to swap VpnInterface {} from oldVpn {} to target VPN {}"
1691 + "as it has not been cleaned up from the oldVpn", updData.getOriginal().getName(),
1692 VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData.getOriginal()
1693 .getVpnInstanceNames()),
1694 VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData.getUpdate()
1695 .getVpnInstanceNames()));
1698 for (VpnInstanceNames vpnInterfaceVpnInstance : updData.getUpdate().getVpnInstanceNames()) {
1699 String newVpnName = vpnInterfaceVpnInstance.getVpnName();
1700 if (updData.getOriginal().getVpnInstanceNames() != null
1701 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(newVpnName,
1702 updData.getOriginal().getVpnInstanceNames())) {
1705 log.info("VPN Interface update event - intfName {} onto vpnName {} running config-driven"
1706 + " swap addition", updData.getUpdate().getName(), newVpnName);
1707 final Adjacencies origAdjs = updData.getOriginal().getAugmentation(Adjacencies.class);
1708 final List<Adjacency> oldAdjs = origAdjs != null && origAdjs.getAdjacency() != null
1709 ? origAdjs.getAdjacency() : new ArrayList<>();
1710 final Adjacencies updateAdjs = updData.getUpdate().getAugmentation(Adjacencies.class);
1711 final List<Adjacency> newAdjs = updateAdjs != null && updateAdjs.getAdjacency() != null
1712 ? updateAdjs.getAdjacency() : new ArrayList<>();
1714 addVpnInterfaceCall(updData.getIdentifier(), updData.getUpdate(),
1715 oldAdjs, newAdjs, newVpnName);
1716 log.info("run: Processed Add for update on VPNInterface {} from oldVpn(s) {} to newVpn {}"
1717 + " upon VPN swap", updData.getUpdate().getName(),
1718 VpnHelper.getVpnInterfaceVpnInstanceNamesString(updData.getOriginal()
1719 .getVpnInstanceNames()), newVpnName);
1724 private boolean isVpnIntfPresentInVpnToDpnList(VpnInterface vpnInterface, String vpnName)
1725 throws ReadFailedException {
1726 BigInteger dpnId = vpnInterface.getDpnId();
1727 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1728 log.trace("isVpnIntfPresentInVpnToDpnList: GOT rd {} for VpnInterface {} VpnInstance {} ", rd ,
1729 vpnInterface.getName(), vpnName);
1735 Optional<VpnInstanceOpDataEntry> maybeVpnInstanceOpData = vpnInstanceOpDataEntryCache.get(
1736 VpnUtil.getVpnInstanceOpDataIdentifier(rd));
1737 if (maybeVpnInstanceOpData.isPresent()) {
1738 log.trace("isVpnIntfPresentInVpnToDpnList: GOT VpnInstanceOp {} for rd {} ",
1739 maybeVpnInstanceOpData.get(), rd);
1740 List<VpnToDpnList> dpnToVpns = maybeVpnInstanceOpData.get().getVpnToDpnList();
1741 if (dpnToVpns != null) {
1742 for (VpnToDpnList dpn : dpnToVpns) {
1743 if (dpn.getDpnId().equals(dpnId)) {
1744 return dpn.getVpnInterfaces().stream().anyMatch(
1745 vpnInterfaces -> vpnInterface.getName().equals(vpnInterfaces.getInterfaceName()));
1747 log.info("isVpnIntfPresentInVpnToDpnList: VpnInterface {} not present in DpnId {} vpn {}",
1748 vpnInterface.getName(), dpn.getDpnId(), vpnName);
1757 private void updateLabelMapper(Long label, List<String> nextHopIpList) {
1758 Preconditions.checkNotNull(label, "updateLabelMapper: label cannot be null or empty!");
1759 synchronized (label.toString().intern()) {
1760 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1761 .child(LabelRouteInfo.class, new LabelRouteInfoKey(label)).build();
1762 Optional<LabelRouteInfo> opResult = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid);
1763 if (opResult.isPresent()) {
1764 LabelRouteInfo labelRouteInfo =
1765 new LabelRouteInfoBuilder(opResult.get()).setNextHopIpList(nextHopIpList).build();
1766 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, labelRouteInfo);
1769 LOG.info("updateLabelMapper: Updated label rotue info for label {} with nextHopList {}", label, nextHopIpList);
1772 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1773 SubnetRoute route, WriteTransaction writeConfigTxn) {
1775 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1776 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label, nextHop, origin, null /* parentVpnRd */)
1777 .addAugmentation(SubnetRoute.class, route).build();
1778 List<VrfEntry> vrfEntryList = Collections.singletonList(vrfEntry);
1779 InstanceIdentifierBuilder<VrfTables> idBuilder =
1780 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1781 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1782 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build();
1783 if (writeConfigTxn != null) {
1784 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1786 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1788 LOG.info("SUBNETROUTE: importSubnetRouteForNewVpn: Created vrfEntry for rd {} prefix {} nexthop {} label {}"
1789 + " and elantag {}", rd, prefix, nextHop, label, route.getElantag());
1792 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, String primaryRd,
1793 Adjacency adj, BigInteger dpnId, WriteTransaction writeOperTxn,
1794 WriteTransaction writeConfigTxn) {
1796 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1797 LogicalDatastoreType.OPERATIONAL, identifier);
1799 if (optVpnInterface.isPresent()) {
1800 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1801 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1802 String vpnName = currVpnIntf.getVpnInstanceName();
1803 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
1804 InstanceIdentifier<AdjacenciesOp> adjPath = identifier.augmentation(AdjacenciesOp.class);
1805 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker,
1806 LogicalDatastoreType.OPERATIONAL, adjPath);
1807 boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni());
1808 VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan);
1809 long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni();
1810 VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType);
1811 List<Adjacency> adjacencies;
1812 if (optAdjacencies.isPresent()) {
1813 adjacencies = optAdjacencies.get().getAdjacency();
1815 // This code will be hit in case of first PNF adjacency
1816 adjacencies = new ArrayList<>();
1818 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1819 L3vpnInput input = new L3vpnInput().setNextHop(adj).setVpnName(vpnName)
1820 .setInterfaceName(currVpnIntf.getName()).setPrimaryRd(primaryRd).setRd(primaryRd);
1821 Adjacency operationalAdjacency = null;
1822 if (adj.getNextHopIpList() != null && !adj.getNextHopIpList().isEmpty()) {
1823 RouteOrigin origin = adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency ? RouteOrigin.LOCAL
1824 : RouteOrigin.STATIC;
1825 String nh = adj.getNextHopIpList().get(0);
1826 String vpnPrefixKey = VpnUtil.getVpnNamePrefixKey(vpnName, prefix);
1827 synchronized (vpnPrefixKey.intern()) {
1828 java.util.Optional<String> rdToAllocate = VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1829 dataBroker, vpnId, null, prefix, vpnName, nh, dpnId);
1830 if (rdToAllocate.isPresent()) {
1831 input.setRd(rdToAllocate.get());
1832 operationalAdjacency = populator.createOperationalAdjacency(input);
1833 int label = operationalAdjacency.getLabel().intValue();
1834 vpnManager.addExtraRoute(vpnName, adj.getIpAddress(), nh, rdToAllocate.get(),
1835 currVpnIntf.getVpnInstanceName(), l3vni, origin,
1836 currVpnIntf.getName(), operationalAdjacency, encapType, writeConfigTxn);
1837 LOG.info("addNewAdjToVpnInterface: Added extra route ip {} nh {} rd {} vpnname {} label {}"
1838 + " Interface {} on dpn {}", adj.getIpAddress(), nh, rdToAllocate.get(),
1839 vpnName, label, currVpnIntf.getName(), dpnId);
1841 LOG.error("addNewAdjToVpnInterface: No rds to allocate extraroute vpn {} prefix {}", vpnName,
1845 // iRT/eRT use case Will be handled in a new patchset for L3VPN Over VxLAN.
1846 // Keeping the MPLS check for now.
1847 if (encapType.equals(VrfEntryBase.EncapType.Mplsgre)) {
1848 final Adjacency opAdjacency = new AdjacencyBuilder(operationalAdjacency).build();
1849 List<VpnInstanceOpDataEntry> vpnsToImportRoute =
1850 VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1851 vpnsToImportRoute.forEach(vpn -> {
1852 if (vpn.getVrfId() != null) {
1853 VpnUtil.allocateRdForExtraRouteAndUpdateUsedRdsMap(
1854 dataBroker, vpn.getVpnId(), vpnId, prefix,
1855 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()), nh, dpnId)
1857 rds -> vpnManager.addExtraRoute(
1858 VpnUtil.getVpnName(dataBroker, vpn.getVpnId()),
1859 adj.getIpAddress(), nh, rds,
1860 currVpnIntf.getVpnInstanceName(),
1861 l3vni, RouteOrigin.SELF_IMPORTED,
1862 currVpnIntf.getName(), opAdjacency, encapType, writeConfigTxn));
1867 } else if (adj.isPhysNetworkFunc()) { // PNF adjacency.
1868 LOG.trace("addNewAdjToVpnInterface: Adding prefix {} to interface {} for vpn {}", prefix,
1869 currVpnIntf.getName(), vpnName);
1871 String parentVpnRd = getParentVpnRdForExternalSubnet(adj);
1874 LogicalDatastoreType.OPERATIONAL,
1875 VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker,
1876 adj.getSubnetId().getValue()), prefix),
1877 VpnUtil.getPrefixToInterface(BigInteger.ZERO, currVpnIntf.getName(), prefix,
1878 adj.getSubnetId(), Prefixes.PrefixCue.PhysNetFunc), true);
1880 fibManager.addOrUpdateFibEntry(adj.getSubnetId().getValue(), adj.getMacAddress(),
1881 adj.getIpAddress(), Collections.emptyList(), null /* EncapType */, 0 /* label */, 0 /*l3vni*/,
1882 null /* gw-mac */, parentVpnRd, RouteOrigin.LOCAL, writeConfigTxn);
1884 input.setRd(adj.getVrfId());
1886 if (operationalAdjacency == null) {
1887 operationalAdjacency = populator.createOperationalAdjacency(input);
1889 adjacencies.add(operationalAdjacency);
1890 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1891 VpnInterfaceOpDataEntry newVpnIntf =
1892 VpnUtil.getVpnInterfaceOpDataEntry(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(),
1893 aug, dpnId, currVpnIntf.isScheduledForRemove(), currVpnIntf.getLportTag(),
1894 currVpnIntf.getGatewayMacAddress());
1896 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1900 private String getParentVpnRdForExternalSubnet(Adjacency adj) {
1901 Subnets subnets = VpnUtil.getExternalSubnet(dataBroker, adj.getSubnetId());
1902 return subnets != null ? subnets.getExternalNetworkId().getValue() : null;
1905 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterfaceOpDataEntry> identifier, Adjacency adj,
1906 BigInteger dpnId, WriteTransaction writeOperTxn, WriteTransaction writeConfigTxn) {
1907 Optional<VpnInterfaceOpDataEntry> optVpnInterface = VpnUtil.read(dataBroker,
1908 LogicalDatastoreType.OPERATIONAL, identifier);
1910 if (optVpnInterface.isPresent()) {
1911 VpnInterfaceOpDataEntry currVpnIntf = optVpnInterface.get();
1913 InstanceIdentifier<AdjacenciesOp> path = identifier.augmentation(AdjacenciesOp.class);
1914 Optional<AdjacenciesOp> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1915 if (optAdjacencies.isPresent()) {
1916 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1918 if (!adjacencies.isEmpty()) {
1919 LOG.trace("delAdjFromVpnInterface: Adjacencies are " + adjacencies);
1920 Iterator<Adjacency> adjIt = adjacencies.iterator();
1921 while (adjIt.hasNext()) {
1922 Adjacency adjElem = adjIt.next();
1923 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1924 String rd = adjElem.getVrfId();
1927 AdjacenciesOp aug = VpnUtil.getVpnInterfaceOpDataEntryAugmentation(adjacencies);
1928 VpnInterfaceOpDataEntry newVpnIntf = VpnUtil
1929 .getVpnInterfaceOpDataEntry(currVpnIntf.getName(),
1930 currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove(),
1931 currVpnIntf.getLportTag(), currVpnIntf.getGatewayMacAddress());
1933 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf, true);
1934 if (adj.getNextHopIpList() != null) {
1935 for (String nh : adj.getNextHopIpList()) {
1936 deleteExtraRouteFromCurrentAndImportingVpns(
1937 currVpnIntf.getVpnInstanceName(), adj.getIpAddress(), nh, rd,
1938 currVpnIntf.getName(), writeConfigTxn);
1940 } else if (adj.isPhysNetworkFunc()) {
1941 LOG.info("delAdjFromVpnInterface: deleting PNF adjacency prefix {} subnet [}",
1942 adj.getIpAddress(), adj.getSubnetId());
1943 fibManager.removeFibEntry(adj.getSubnetId().getValue(), adj.getIpAddress(),
1951 LOG.info("delAdjFromVpnInterface: Removed adj {} on dpn {} rd {}", adj.getIpAddress(),
1952 dpnId, adj.getVrfId());
1954 LOG.error("delAdjFromVpnInterface: Cannnot DEL adjacency, since operational interface is "
1955 + "unavailable dpnId {} adjIP {} rd {}", dpnId, adj.getIpAddress(), adj.getVrfId());
1960 private void deleteExtraRouteFromCurrentAndImportingVpns(String vpnName, String destination, String nextHop,
1961 String rd, String intfName, WriteTransaction writeConfigTxn) {
1962 vpnManager.delExtraRoute(vpnName, destination, nextHop, rd, vpnName, intfName, writeConfigTxn);
1963 List<VpnInstanceOpDataEntry> vpnsToImportRoute = VpnUtil.getVpnsImportingMyRoute(dataBroker, vpnName);
1964 for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
1965 String vpnRd = vpn.getVrfId();
1966 if (vpnRd != null) {
1967 vpnManager.delExtraRoute(vpnName, destination, nextHop, vpnRd, vpnName, intfName, writeConfigTxn);
1972 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1973 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1974 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1975 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1978 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1979 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1980 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1983 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1984 WriteTransaction writeOperTxn) {
1985 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1986 if (dpId.equals(BigInteger.ZERO)) {
1987 LOG.error("addToNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
1988 + " association model", vpnInterfaceName, routerName);
1992 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1994 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1995 .OPERATIONAL, routerDpnListIdentifier);
1996 RouterInterfaces routerInterface =
1997 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
1998 vpnInterfaceName).build();
1999 if (optionalRouterDpnList.isPresent()) {
2000 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
2001 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
2003 RouterDpnListBuilder builder = new RouterDpnListBuilder();
2004 builder.setRouterId(routerName);
2005 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
2006 builder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
2007 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
2008 getRouterId(routerName),
2009 builder.build(), true);
2013 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
2014 WriteTransaction writeOperTxn) {
2015 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
2016 if (dpId.equals(BigInteger.ZERO)) {
2017 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
2018 + " dissociation model", vpnInterfaceName, routerName);
2022 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
2023 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
2024 .OPERATIONAL, routerDpnListIdentifier);
2025 if (optionalRouterDpnList.isPresent()) {
2026 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
2027 RouterInterfaces routerInterface =
2028 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
2029 vpnInterfaceName).build();
2031 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
2032 if (routerInterfaces.isEmpty()) {
2033 if (writeOperTxn != null) {
2034 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
2036 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
2039 if (writeOperTxn != null) {
2040 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
2041 RouterInterfaces.class,
2042 new RouterInterfacesKey(vpnInterfaceName)));
2044 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL,
2045 routerDpnListIdentifier.child(
2046 RouterInterfaces.class,
2047 new RouterInterfacesKey(vpnInterfaceName)));
2054 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
2055 WriteTransaction writeOperTxn) {
2056 if (dpId.equals(BigInteger.ZERO)) {
2057 LOG.error("removeFromNeutronRouterDpnsMap: Could not retrieve dp id for interface {} to handle router {}"
2058 + " dissociation model", vpnInterfaceName, routerName);
2062 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
2063 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
2064 .OPERATIONAL, routerDpnListIdentifier);
2065 if (optionalRouterDpnList.isPresent()) {
2066 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
2067 RouterInterfaces routerInterface =
2068 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(
2069 vpnInterfaceName).build();
2070 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
2071 if (routerInterfaces.isEmpty()) {
2072 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
2074 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
2075 RouterInterfaces.class,
2076 new RouterInterfacesKey(vpnInterfaceName)));
2082 protected void createFibEntryForRouterInterface(String primaryRd, VpnInterface vpnInterface, String interfaceName,
2083 WriteTransaction writeConfigTxn, String vpnName) {
2084 if (vpnInterface == null) {
2087 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
2089 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as adjacencies for"
2090 + " this vpn interface could not be obtained. vpn {}", interfaceName, vpnName);
2093 for (Adjacency adj : adjs) {
2094 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2095 String primaryInterfaceIp = adj.getIpAddress();
2096 String macAddress = adj.getMacAddress();
2097 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
2099 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
2100 VpnUtil.getNextHopLabelKey(primaryRd, prefix));
2102 RouterInterface routerInt = new RouterInterfaceBuilder().setUuid(vpnName)
2103 .setIpAddress(primaryInterfaceIp).setMacAddress(macAddress).build();
2104 fibManager.addFibEntryForRouterInterface(primaryRd, prefix,
2105 routerInt, label, writeConfigTxn);
2106 LOG.info("createFibEntryForRouterInterface: Router interface {} for vpn {} rd {} prefix {} label {}"
2107 + " macAddress {} processed successfully;", interfaceName, vpnName, primaryRd, prefix, label,
2112 LOG.error("createFibEntryForRouterInterface: VPN Interface {} of router addition failed as primary"
2113 + " adjacency for this vpn interface could not be obtained. rd {} vpnName {}", interfaceName,
2114 primaryRd, vpnName);
2117 protected void deleteFibEntryForRouterInterface(VpnInterface vpnInterface,
2118 WriteTransaction writeConfigTxn, String vpnName) {
2119 Adjacencies adjs = vpnInterface.getAugmentation(Adjacencies.class);
2120 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
2122 List<Adjacency> adjsList = adjs.getAdjacency();
2123 for (Adjacency adj : adjsList) {
2124 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2125 String primaryInterfaceIp = adj.getIpAddress();
2126 String prefix = VpnUtil.getIpPrefix(primaryInterfaceIp);
2127 fibManager.removeFibEntry(rd, prefix, writeConfigTxn);
2128 LOG.info("deleteFibEntryForRouterInterface: FIB for router interface {} deleted for vpn {} rd {}"
2129 + " prefix {}", vpnInterface.getName(), vpnName, rd, prefix);
2134 LOG.error("deleteFibEntryForRouterInterface: Adjacencies for vpninterface {} is null, rd: {}",
2135 vpnInterface.getName(), rd);
2139 private void processSavedInterface(UnprocessedVpnInterfaceData intefaceData, String vpnName) {
2140 if (!canHandleNewVpnInterface(intefaceData.identifier, intefaceData.vpnInterface, vpnName)) {
2141 LOG.error("add: VpnInstance {} for vpnInterface {} not ready, holding on ",
2142 vpnName, intefaceData.vpnInterface.getName());
2145 final VpnInterfaceKey key = intefaceData.identifier
2146 .firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
2147 final String interfaceName = key.getName();
2148 InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpIdentifier = VpnUtil
2149 .getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
2150 addVpnInterfaceToVpn(vpnInterfaceOpIdentifier, intefaceData.vpnInterface, null, null,
2151 intefaceData.identifier, vpnName);
2155 private void addToUnprocessedVpnInterfaces(InstanceIdentifier<VpnInterface> identifier,
2156 VpnInterface vpnInterface, String vpnName) {
2157 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces = unprocessedVpnInterfaces
2159 if (vpnInterfaces == null) {
2160 vpnInterfaces = new ConcurrentLinkedQueue<>();
2162 vpnInterfaces.add(new UnprocessedVpnInterfaceData(identifier, vpnInterface));
2163 unprocessedVpnInterfaces.put(vpnName, vpnInterfaces);
2164 LOG.info("addToUnprocessedVpnInterfaces: Saved unhandled vpn interface {} in vpn instance {}",
2165 vpnInterface.getName(), vpnName);
2168 public boolean isVpnInstanceReady(String vpnInstanceName) {
2169 String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnInstanceName);
2170 if (vpnRd == null) {
2173 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd);
2175 return vpnInstanceOpDataEntry != null;
2178 public void processSavedInterfaces(String vpnInstanceName, boolean hasVpnInstanceCreatedSuccessfully) {
2179 synchronized (vpnInstanceName.intern()) {
2180 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2181 unprocessedVpnInterfaces.get(vpnInstanceName);
2182 if (vpnInterfaces != null) {
2183 while (!vpnInterfaces.isEmpty()) {
2184 UnprocessedVpnInterfaceData savedInterface = vpnInterfaces.poll();
2185 if (hasVpnInstanceCreatedSuccessfully) {
2186 processSavedInterface(savedInterface, vpnInstanceName);
2187 LOG.info("processSavedInterfaces: Handle saved vpn interfaces {} in vpn instance {}",
2188 savedInterface.vpnInterface.getName(), vpnInstanceName);
2190 LOG.error("processSavedInterfaces: Cannot process vpn interface {} in vpn instance {}",
2191 savedInterface.vpnInterface.getName(), vpnInstanceName);
2195 LOG.info("processSavedInterfaces: No interfaces in queue for VPN {}", vpnInstanceName);
2200 private void removeInterfaceFromUnprocessedList(InstanceIdentifier<VpnInterface> identifier,
2201 VpnInterface vpnInterface) {
2202 synchronized (VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface).intern()) {
2203 ConcurrentLinkedQueue<UnprocessedVpnInterfaceData> vpnInterfaces =
2204 unprocessedVpnInterfaces.get(VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2205 if (vpnInterfaces != null) {
2206 if (vpnInterfaces.remove(new UnprocessedVpnInterfaceData(identifier, vpnInterface))) {
2207 LOG.info("removeInterfaceFromUnprocessedList: Removed vpn interface {} in vpn instance {} from "
2208 + "unprocessed list", vpnInterface.getName(),
2209 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2212 LOG.info("removeInterfaceFromUnprocessedList: No interfaces in queue for VPN {}",
2213 VpnHelper.getFirstVpnNameFromVpnInterface(vpnInterface));
2218 public void vpnInstanceIsReady(String vpnInstanceName) {
2219 processSavedInterfaces(vpnInstanceName, true);
2222 public void vpnInstanceFailed(String vpnInstanceName) {
2223 processSavedInterfaces(vpnInstanceName, false);
2226 private static class UnprocessedVpnInterfaceData {
2227 InstanceIdentifier<VpnInterface> identifier;
2228 VpnInterface vpnInterface;
2230 UnprocessedVpnInterfaceData(InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
2231 this.identifier = identifier;
2232 this.vpnInterface = vpnInterface;
2236 public int hashCode() {
2237 final int prime = 31;
2239 result = prime * result + (identifier == null ? 0 : identifier.hashCode());
2240 result = prime * result + (vpnInterface == null ? 0 : vpnInterface.hashCode());
2245 public boolean equals(Object obj) {
2252 if (getClass() != obj.getClass()) {
2255 UnprocessedVpnInterfaceData other = (UnprocessedVpnInterfaceData) obj;
2256 if (identifier == null) {
2257 if (other.identifier != null) {
2260 } else if (!identifier.equals(other.identifier)) {
2263 if (vpnInterface == null) {
2264 if (other.vpnInterface != null) {
2267 } else if (!vpnInterface.equals(other.vpnInterface)) {
2274 public void updateVpnInterfacesForUnProcessAdjancencies(String vpnName) {
2275 String primaryRd = VpnUtil.getVpnRd(dataBroker, vpnName);
2276 VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpData(dataBroker, primaryRd);
2277 if (vpnInstanceOpData == null) {
2280 List<VpnToDpnList> vpnToDpnLists = vpnInstanceOpData.getVpnToDpnList();
2281 if (vpnToDpnLists == null || vpnToDpnLists.isEmpty()) {
2284 LOG.debug("Update the VpnInterfaces for Unprocessed Adjancencies for vpnName:{}", vpnName);
2285 vpnToDpnLists.forEach(vpnToDpnList -> vpnToDpnList.getVpnInterfaces().forEach(vpnInterface -> {
2286 InstanceIdentifier<VpnInterfaceOpDataEntry> existingVpnInterfaceId =
2287 VpnUtil.getVpnInterfaceOpDataEntryIdentifier(vpnInterface.getInterfaceName(), vpnName);
2288 Optional<VpnInterfaceOpDataEntry> vpnInterfaceOptional = VpnUtil.read(dataBroker,
2289 LogicalDatastoreType.OPERATIONAL, existingVpnInterfaceId);
2290 if (!vpnInterfaceOptional.isPresent()) {
2293 List<Adjacency> configVpnAdjacencies = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker,
2294 vpnInterface.getInterfaceName());
2295 if (configVpnAdjacencies == null) {
2296 LOG.debug("There is no adjacency available for vpnInterface:{}", vpnInterface);
2299 List<Adjacency> operationVpnAdjacencies = vpnInterfaceOptional.get()
2300 .getAugmentation(AdjacenciesOp.class).getAdjacency();
2301 // Due to insufficient rds, some of the extra route wont get processed when it is added.
2302 // The unprocessed adjacencies will be present in config vpn interface DS but will be missing
2303 // in operational DS. These unprocessed adjacencies will be handled below.
2304 // To obtain unprocessed adjacencies, filtering is done by which the missing adjacencies in operational
2305 // DS are retrieved which is used to call addNewAdjToVpnInterface method.
2306 configVpnAdjacencies.stream()
2307 .filter(adjacency -> operationVpnAdjacencies.stream()
2308 .noneMatch(operationalAdjacency ->
2309 operationalAdjacency.getIpAddress().equals(adjacency.getIpAddress())))
2310 .forEach(adjacency -> {
2311 LOG.debug("Processing the vpnInterface{} for the Ajacency:{}", vpnInterface, adjacency);
2312 jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterface.getInterfaceName() + vpnName,
2314 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
2315 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
2316 if (VpnUtil.isAdjacencyEligibleToVpn(dataBroker, adjacency, vpnName)) {
2317 addNewAdjToVpnInterface(existingVpnInterfaceId, primaryRd, adjacency,
2318 vpnInterfaceOptional.get().getDpnId(), writeConfigTxn, writeOperTxn);
2319 ListenableFuture<Void> operFuture = writeOperTxn.submit();
2322 } catch (ExecutionException | InterruptedException e) {
2323 LOG.error("Exception encountered while submitting operational"
2324 + " future for vpnInterface {}", vpnInterface, e);
2326 List<ListenableFuture<Void>> futures = new ArrayList<>();
2327 futures.add(writeConfigTxn.submit());
2330 return Collections.emptyList();
2337 private class PostVpnInterfaceWorker implements FutureCallback<Void> {
2338 private final String interfaceName;
2339 private final boolean add;
2340 private final String txnDestination;
2342 PostVpnInterfaceWorker(String interfaceName, boolean add, String transactionDest) {
2343 this.interfaceName = interfaceName;
2345 this.txnDestination = transactionDest;
2349 public void onSuccess(Void voidObj) {
2351 LOG.debug("VpnInterfaceManager: VrfEntries for {} stored into destination {} successfully",
2352 interfaceName, txnDestination);
2354 LOG.debug("VpnInterfaceManager: VrfEntries for {} removed successfully", interfaceName);
2359 public void onFailure(Throwable throwable) {
2361 LOG.error("VpnInterfaceManager: VrfEntries for {} failed to store into destination {}"
2362 + " with exception: {}", interfaceName, txnDestination, throwable);
2364 LOG.error("VpnInterfaceManager: VrfEntries for {} removal failed with exception: {}", interfaceName,
2366 VpnUtil.unsetScheduledToRemoveForVpnInterface(dataBroker, interfaceName);