2 * Copyright (c) 2015 - 2016 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.Function;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.base.Predicate;
14 import com.google.common.base.Predicates;
15 import com.google.common.collect.FluentIterable;
16 import com.google.common.collect.Iterators;
17 import com.google.common.util.concurrent.CheckedFuture;
18 import com.google.common.util.concurrent.FutureCallback;
19 import com.google.common.util.concurrent.Futures;
20 import com.google.common.util.concurrent.JdkFutureAdapters;
21 import com.google.common.util.concurrent.ListenableFuture;
22 import java.math.BigInteger;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.concurrent.Callable;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.ExecutionException;
31 import java.util.concurrent.ExecutorService;
32 import java.util.concurrent.Executors;
33 import java.util.concurrent.Future;
34 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
35 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
36 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
37 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
38 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
41 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
42 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
43 import org.opendaylight.genius.mdsalutil.ActionInfo;
44 import org.opendaylight.genius.mdsalutil.ActionType;
45 import org.opendaylight.genius.mdsalutil.FlowEntity;
46 import org.opendaylight.genius.mdsalutil.InstructionInfo;
47 import org.opendaylight.genius.mdsalutil.InstructionType;
48 import org.opendaylight.genius.mdsalutil.MDSALUtil;
49 import org.opendaylight.genius.mdsalutil.MatchFieldType;
50 import org.opendaylight.genius.mdsalutil.MatchInfo;
51 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
52 import org.opendaylight.genius.mdsalutil.NwConstants;
53 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
54 import org.opendaylight.genius.utils.ServiceIndex;
55 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
56 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
57 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
58 import org.opendaylight.netvirt.vpnmanager.intervpnlink.InterVpnLinkUtil;
59 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
60 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRouteBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
132 import org.opendaylight.yangtools.concepts.ListenerRegistration;
133 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
134 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
135 import org.opendaylight.yangtools.yang.common.RpcError;
136 import org.opendaylight.yangtools.yang.common.RpcResult;
137 import org.slf4j.Logger;
138 import org.slf4j.LoggerFactory;
140 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
141 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
142 private ListenerRegistration<DataChangeListener> listenerRegistration;
143 private final DataBroker dataBroker;
144 private final IBgpManager bgpManager;
145 private final IFibManager fibManager;
146 private final IMdsalApiManager mdsalManager;
147 private final IdManagerService idManager;
148 private final OdlArputilService arpManager;
149 private final OdlInterfaceRpcService ifaceMgrRpcService;
150 private final NotificationPublishService notificationPublishService;
151 private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
152 private ExecutorService executorService = Executors.newSingleThreadExecutor();
154 public VpnInterfaceManager(final DataBroker dataBroker,
155 final IBgpManager bgpManager,
156 final OdlArputilService arpManager,
157 final IdManagerService idManager,
158 final IMdsalApiManager mdsalManager,
159 final IFibManager fibManager,
160 final OdlInterfaceRpcService ifaceMgrRpcService,
161 final NotificationPublishService notificationPublishService) {
162 super(VpnInterface.class);
163 this.dataBroker = dataBroker;
164 this.bgpManager = bgpManager;
165 this.arpManager = arpManager;
166 this.idManager = idManager;
167 this.mdsalManager = mdsalManager;
168 this.fibManager = fibManager;
169 this.ifaceMgrRpcService = ifaceMgrRpcService;
170 this.notificationPublishService = notificationPublishService;
173 public void start() {
174 LOG.info("{} start", getClass().getSimpleName());
175 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
176 getWildCardPath(), this, DataChangeScope.SUBTREE);
179 private InstanceIdentifier<VpnInterface> getWildCardPath() {
180 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
184 public void close() throws Exception {
185 if (listenerRegistration != null) {
186 listenerRegistration.close();
187 listenerRegistration = null;
189 LOG.info("{} close", getClass().getSimpleName());
192 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
193 return InstanceIdentifier.create(InterfacesState.class)
194 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
198 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
199 LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
200 LOG.info("VPN Interface add event - intfName {}" ,vpnInterface.getName());
201 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
202 final String interfaceName = key.getName();
204 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
205 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
206 if(interfaceState != null){
208 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
209 final int ifIndex = interfaceState.getIfIndex();
210 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
211 dataStoreCoordinator.enqueueJob("VPNINTERFACE-"+ interfaceName,
212 new Callable<List<ListenableFuture<Void>>>() {
214 public List<ListenableFuture<Void>> call() throws Exception {
215 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
216 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
217 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
218 processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeConfigTxn, writeOperTxn, writeInvTxn);
219 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
220 futures.add(writeOperTxn.submit());
221 futures.add(writeConfigTxn.submit());
222 futures.add(writeInvTxn.submit());
226 }catch (Exception e){
227 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
231 LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
235 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface,
236 final int lPortTag, boolean isInterfaceUp,
237 WriteTransaction writeConfigTxn,
238 WriteTransaction writeOperTxn,
239 WriteTransaction writeInvTxn) {
241 final String interfaceName = vpnInterface.getName();
242 if (!isInterfaceUp) {
243 final String vpnName = vpnInterface.getVpnInstanceName();
244 LOG.info("Binding vpn service to interface {} ", interfaceName);
245 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
246 if (vpnId == VpnConstants.INVALID_ID) {
247 LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
250 boolean waitForVpnInterfaceOpRemoval = false;
251 VpnInterface opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, vpnInterface.getName());
252 if (opVpnInterface != null ) {
253 String opVpnName = opVpnInterface.getVpnInstanceName();
254 String primaryInterfaceIp = null;
255 if(opVpnName.equals(vpnName)) {
256 // Please check if the primary VRF Entry does not exist for VPNInterface
257 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
259 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
260 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
262 LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained", interfaceName);
265 for (Adjacency adj : adjs) {
266 if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
267 primaryInterfaceIp = adj.getIpAddress();
271 if (primaryInterfaceIp == null) {
272 LOG.info("VPN Interface {} addition failed as primary adjacency "
273 + "for this vpn interface could not be obtained", interfaceName);
276 // Get the rd of the vpn instance
277 String rd = getRouteDistinguisher(opVpnName);
278 rd = (rd == null) ? opVpnName : rd;
279 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, rd, primaryInterfaceIp);
281 LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
284 waitForVpnInterfaceOpRemoval = true;
286 LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}",
287 interfaceName, vpnName, opVpnName);
290 if (!waitForVpnInterfaceOpRemoval) {
291 // Add the VPNInterface and quit
292 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
293 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
294 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
298 // FIB didn't get a chance yet to clean up this VPNInterface
299 // Let us give it a chance here !
300 LOG.info("Trying to add VPN Interface {}, but waiting for FIB to clean up! ", interfaceName);
302 Runnable notifyTask = new VpnNotifyTask();
303 vpnIntfMap.put(interfaceName, notifyTask);
304 synchronized (notifyTask) {
306 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
307 } catch (InterruptedException e) {
311 vpnIntfMap.remove(interfaceName);
314 opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
315 if (opVpnInterface != null) {
316 LOG.error("VPN Interface {} removal by FIB did not complete on time, bailing addition ...", interfaceName);
319 // VPNInterface got removed, proceed with Add
320 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
321 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
322 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
324 // Interface is retained in the DPN, but its Link Up.
325 // Advertise prefixes again for this interface to BGP
326 advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
332 // private class UpdateDpnToVpnWorker implements Callable<List<ListenableFuture<Void>>> {
335 // String interfaceName;
339 // public UpdateDpnToVpnWorker(BigInteger dpnId, String vpnName, String interfaceName,
340 // int lPortTag, boolean addToDpn) {
341 // this.dpnId= dpnId;
342 // this.vpnName = vpnName;
343 // this.interfaceName = interfaceName;
344 // this.lPortTag = lPortTag;
345 // this.addToDpn = addToDpn;
349 // public List<ListenableFuture<Void>> call() throws Exception {
350 // // If another renderer(for eg : CSS) needs to be supported, check can be performed here
351 // // to call the respective helpers.
352 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
353 // updateDpnDbs(dpnId, vpnName, interfaceName, addToDpn, writeTxn);
354 // List<ListenableFuture<Void>> futures = new ArrayList<>();
355 // futures.add(writeTxn.submit());
356 // ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
357 // Futures.addCallback(listenableFuture,
358 // new UpdateDpnToVpnCallback(dpnId, vpnName, interfaceName, lPortTag, addToDpn));
365 // * JobCallback class is used as a future callback for
366 // * main and rollback workers to handle success and failure.
368 // private class UpdateDpnToVpnCallback implements FutureCallback<List<Void>> {
371 // String interfaceName;
375 // public UpdateDpnToVpnCallback(BigInteger dpnId, String vpnName, String interfaceName,
376 // int lPortTag, boolean addToDpn) {
377 // this.dpnId= dpnId;
378 // this.vpnName = vpnName;
379 // this.interfaceName = interfaceName;
380 // this.lPortTag = lPortTag;
381 // this.addToDpn = addToDpn;
386 // * This implies that all the future instances have returned success. -- TODO: Confirm this
389 // public void onSuccess(List<Void> voids) {
390 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
391 // bindService(dpnId, vpnName, interfaceName, lPortTag, writeTxn);
392 // processVpnInterfaceAdjacencies(dpnId, vpnName, interfaceName, writeTxn);
393 // writeTxn.submit();
398 // * @param throwable
399 // * This method is used to handle failure callbacks.
400 // * If more retry needed, the retrycount is decremented and mainworker is executed again.
401 // * After retries completed, rollbackworker is executed.
402 // * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
406 // public void onFailure(Throwable throwable) {
407 // LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
414 private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
417 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
418 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
420 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
422 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
423 intf.getName(), intf.getVpnInstanceName());
426 if (rd.equals(intf.getVpnInstanceName())) {
427 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} as it is in " +
428 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
433 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} in vpn {} with rd {} ", intf.getName(),
434 intf.getVpnInstanceName(), rd);
436 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
437 if (nextHopIp == null){
438 LOG.trace("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} is null, returning", intf.getName());
442 if (adjacencies.isPresent()) {
443 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
445 if (!nextHops.isEmpty()) {
446 LOG.trace("NextHops are " + nextHops);
447 for (Adjacency nextHop : nextHops) {
448 long label = nextHop.getLabel();
450 LOG.info("VPN ADVERTISE: Adding Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
451 bgpManager.advertisePrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
452 LOG.info("VPN ADVERTISE: Added Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
453 } catch(Exception e) {
454 LOG.error("Failed to advertise prefix {} in vpn {} with rd {} for interface {} ",
455 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
462 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
464 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
465 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
467 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
469 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
470 intf.getName(), intf.getVpnInstanceName());
473 if (rd.equals(intf.getVpnInstanceName())) {
474 LOG.info("withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in " +
475 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
479 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", intf.getName(),
480 intf.getVpnInstanceName(), rd);
481 if (adjacencies.isPresent()) {
482 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
484 if (!nextHops.isEmpty()) {
485 LOG.trace("NextHops are " + nextHops);
486 for (Adjacency nextHop : nextHops) {
488 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
489 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
490 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
491 } catch(Exception e) {
492 LOG.error("Failed to withdraw prefix {} in vpn {} with rd {} for interface {} ",
493 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
500 public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
501 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
503 dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
505 if(!dpId.equals(BigInteger.ZERO)) {
507 createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
509 removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
513 private void bindService(BigInteger dpId, final String vpnInstanceName, final String vpnInterfaceName,
514 int lPortTag, WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
515 final int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
516 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
518 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
519 dataStoreCoordinator.enqueueJob(vpnInterfaceName,
520 new Callable<List<ListenableFuture<Void>>>() {
522 public List<ListenableFuture<Void>> call() throws Exception {
523 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
524 int instructionKey = 0;
525 List<Instruction> instructions = new ArrayList<Instruction>();
527 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(
528 MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
529 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
533 InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
534 NwConstants.L3VPN_SERVICE_INDEX, priority,
535 NwConstants.COOKIE_VM_INGRESS_TABLE, instructions);
536 writeTxn.put(LogicalDatastoreType.CONFIGURATION,
537 InterfaceUtils.buildServiceId(vpnInterfaceName, NwConstants.L3VPN_SERVICE_INDEX), serviceInfo, true);
538 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
539 futures.add(writeTxn.submit());
543 makeArpFlow(dpId, NwConstants.L3VPN_SERVICE_INDEX, lPortTag, vpnInterfaceName,
544 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeInvTxn);
545 makeArpFlow(dpId, NwConstants.L3VPN_SERVICE_INDEX, lPortTag, vpnInterfaceName,
546 vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeInvTxn);
550 private void processVpnInterfaceAdjacencies(BigInteger dpnId, String vpnName, String interfaceName,
551 WriteTransaction writeConfigTxn,
552 WriteTransaction writeOperTxn) {
553 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
555 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
556 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
558 if (adjacencies.isPresent()) {
559 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
560 List<Adjacency> value = new ArrayList<>();
562 // Get the rd of the vpn instance
563 String rd = getRouteDistinguisher(vpnName);
565 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
566 if (nextHopIp == null){
567 LOG.error("NextHop for interface {} is null", interfaceName);
571 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
573 LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
574 for (Adjacency nextHop : nextHops) {
575 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
576 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
577 VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
579 List<String> adjNextHop = nextHop.getNextHopIpList();
580 value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
581 (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
582 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
584 if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
585 LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
587 LogicalDatastoreType.OPERATIONAL,
588 VpnUtil.getPrefixToInterfaceIdentifier(
589 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
590 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
592 //Extra route adjacency
593 LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName);
595 LogicalDatastoreType.OPERATIONAL,
596 VpnUtil.getVpnToExtrarouteIdentifier(
597 (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
598 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
602 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
604 VpnInterface opInterface = VpnUtil.getVpnInterface(interfaceName, vpnName, aug, dpnId, Boolean.FALSE);
605 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
606 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, true);
607 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
609 for (Adjacency nextHop : aug.getAdjacency()) {
610 long label = nextHop.getLabel();
612 addToLabelMapper(label, dpnId, nextHop.getIpAddress(), Arrays.asList(nextHopIp), vpnId,
613 interfaceName, null,false, rd, writeOperTxn);
614 addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label, writeConfigTxn);
615 //TODO: ERT - check for VPNs importing my route
616 for (VpnInstance vpn : vpnsToImportRoute) {
617 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
619 LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
620 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), Arrays.asList(nextHopIp), (int) label,
621 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
625 // ### add FIB route directly
626 fibManager.addOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), Arrays.asList(nextHopIp),
627 (int) label, RouteOrigin.STATIC, writeConfigTxn);
633 private List<VpnInstance> getVpnsImportingMyRoute(final String vpnName) {
634 List<VpnInstance> vpnsToImportRoute = new ArrayList<>();
636 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
637 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
638 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
639 final VpnInstance vpnInstance;
640 if (optVpnInstance.isPresent()) {
641 vpnInstance = optVpnInstance.get();
643 LOG.debug("Could not retrieve vpn instance {} to check for vpns importing the routes", vpnName);
644 return vpnsToImportRoute;
647 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
649 public boolean apply(VpnInstance input) {
650 return !input.getVpnInstanceName().equals(vpnName);
654 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
656 public boolean apply(VpnInstance input) {
657 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ExportExtcommunity),
658 getRts(input, VpnTarget.VrfRTType.ImportExtcommunity));
659 return Iterators.size(commonRTs.iterator()) > 0;
663 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
665 public String apply(VpnInstance vpnInstance) {
666 //return vpnInstance.getVpnInstanceName();
667 return vpnInstance.getIpv4Family().getRouteDistinguisher();
671 vpnsToImportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(dataBroker)).
673 filter(matchRTs).toList();
674 return vpnsToImportRoute;
677 private List<VpnInstance> getVpnsExportingMyRoute(final String vpnName) {
678 List<VpnInstance> vpnsToExportRoute = new ArrayList<>();
680 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
681 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
682 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
683 final VpnInstance vpnInstance;
684 if (optVpnInstance.isPresent()) {
685 vpnInstance = optVpnInstance.get();
687 LOG.debug("Could not retrieve vpn instance {} to check for vpns exporting the routes", vpnName);
688 return vpnsToExportRoute;
691 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
693 public boolean apply(VpnInstance input) {
694 return !input.getVpnInstanceName().equals(vpnName);
698 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
700 public boolean apply(VpnInstance input) {
701 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ImportExtcommunity),
702 getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
703 return Iterators.size(commonRTs.iterator()) > 0;
707 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
709 public String apply(VpnInstance vpnInstance) {
710 return vpnInstance.getVpnInstanceName();
714 vpnsToExportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(dataBroker)).
716 filter(matchRTs).toList();
717 return vpnsToExportRoute;
720 private <T> Iterable<T> intersection(final Collection<T> collection1, final Collection<T> collection2) {
721 final Predicate<T> inPredicate = Predicates.<T>in(collection2);
722 return new Iterable<T>() {
724 public Iterator<T> iterator() {
725 return Iterators.filter(collection1.iterator(), inPredicate);
730 private List<String> getRts(VpnInstance vpnInstance, VpnTarget.VrfRTType rtType) {
731 String name = vpnInstance.getVpnInstanceName();
732 List<String> rts = new ArrayList<>();
733 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
734 if (vpnConfig == null) {
735 LOG.trace("vpn config is not available for {}", name);
738 VpnTargets targets = vpnConfig.getVpnTargets();
739 if (targets == null) {
740 LOG.trace("vpn targets not available for {}", name);
743 List<VpnTarget> vpnTargets = targets.getVpnTarget();
744 if (vpnTargets == null) {
745 LOG.trace("vpnTarget values not available for {}", name);
748 for (VpnTarget target : vpnTargets) {
749 //TODO: Check for RT type is Both
750 if(target.getVrfRTType().equals(rtType) ||
751 target.getVrfRTType().equals(VpnTarget.VrfRTType.Both)) {
752 String rtValue = target.getVrfRTValue();
759 private List<String> getExportRts(VpnInstance vpnInstance) {
760 List<String> exportRts = new ArrayList<>();
761 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
762 VpnTargets targets = vpnConfig.getVpnTargets();
763 List<VpnTarget> vpnTargets = targets.getVpnTarget();
764 for (VpnTarget target : vpnTargets) {
765 if (target.getVrfRTType().equals(VpnTarget.VrfRTType.ExportExtcommunity)) {
766 String rtValue = target.getVrfRTValue();
767 exportRts.add(rtValue);
773 private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
774 long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow,
775 WriteTransaction writeConfigTxn){
776 List<MatchInfo> matches = new ArrayList<MatchInfo>();
777 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, MetaDataUtil.getVpnIdMetadata(vpnId));
778 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
779 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
781 // Matching Arp reply flows
782 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
783 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
784 metadata, metadataMask }));
786 matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
788 // Instruction to punt to controller
789 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
790 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
791 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
792 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
793 Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
795 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
797 // Install the flow entry in L3_INTERFACE_TABLE
798 String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
799 NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
800 FlowEntity flowEntity;
801 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
802 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
803 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
805 Flow flow = flowEntity.getFlowBuilder().build();
806 String flowId = flowEntity.getFlowId();
807 FlowKey flowKey = new FlowKey( new FlowId(flowId));
808 Node nodeDpn = buildDpnNode(dpId);
810 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
811 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
812 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
814 if (writeConfigTxn != null) {
815 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
816 LOG.debug("Creating ARP Flow for interface {}", vpnInterfaceName);
817 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
819 LOG.debug("Deleting ARP Flow for interface {}", vpnInterfaceName);
820 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
823 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
824 LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
825 mdsalManager.installFlow(flowEntity);
827 LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
828 mdsalManager.removeFlow(flowEntity);
833 //TODO: How to handle the below code, its a copy paste from MDSALManager.java
834 private Node buildDpnNode(BigInteger dpnId) {
835 NodeId nodeId = new NodeId("openflow:" + dpnId);
836 Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
841 private String getRouteDistinguisher(String vpnName) {
842 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
843 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
844 Optional<VpnInstance> vpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
846 if(vpnInstance.isPresent()) {
847 VpnInstance instance = vpnInstance.get();
848 VpnAfConfig config = instance.getIpv4Family();
849 rd = config.getRouteDistinguisher();
855 * JobCallback class is used as a future callback for
856 * main and rollback workers to handle success and failure.
858 private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
864 public DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
865 this.entered = entered;
867 this.vpnName = vpnName;
873 * This implies that all the future instances have returned success. -- TODO: Confirm this
876 public void onSuccess(List<Void> voids) {
878 publishAddNotification(dpnId, vpnName, rd);
880 publishRemoveNotification(dpnId, vpnName, rd);
887 * This method is used to handle failure callbacks.
888 * If more retry needed, the retrycount is decremented and mainworker is executed again.
889 * After retries completed, rollbackworker is executed.
890 * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
893 public void onFailure(Throwable throwable) {
894 LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
898 private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
899 String routeDistinguisher = getRouteDistinguisher(vpnName);
900 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
901 Boolean newDpnOnVpn = Boolean.FALSE;
903 synchronized (vpnName.intern()) {
904 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
905 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
906 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
907 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data
908 .entry.vpn.to.dpn.list.VpnInterfaces
909 vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
911 if (dpnInVpn.isPresent()) {
912 VpnToDpnList vpnToDpnList = dpnInVpn.get();
913 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
914 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
915 if (vpnInterfaces == null) {
916 vpnInterfaces = new ArrayList<>();
918 vpnInterfaces.add(vpnInterface);
919 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
920 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
922 if (writeTxn != null) {
923 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
925 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
927 /* If earlier state was inactive, it is considered new DPN coming back to the
930 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
931 newDpnOnVpn = Boolean.TRUE;
934 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
935 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
936 vpnInterfaces.add(vpnInterface);
937 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
938 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
940 if (writeTxn != null) {
941 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
943 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
945 newDpnOnVpn = Boolean.TRUE;
947 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
950 } catch (InterruptedException | ExecutionException e) {
951 LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
952 throw new RuntimeException(e.getMessage());
956 * Informing the Fib only after writeTxn is submitted successfuly.
959 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
960 fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, true /* entered */));
964 private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
965 Boolean lastDpnOnVpn = Boolean.FALSE;
966 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
967 synchronized (vpnName.intern()) {
968 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
969 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
970 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
971 if (dpnInVpn.isPresent()) {
972 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
973 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
974 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
975 currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
977 if (vpnInterfaces.remove(currVpnInterface)) {
978 if (vpnInterfaces.isEmpty()) {
979 List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
980 if (ipAddresses == null || ipAddresses.isEmpty()) {
981 VpnToDpnListBuilder dpnInVpnBuilder =
982 new VpnToDpnListBuilder(dpnInVpn.get())
983 .setDpnState(VpnToDpnList.DpnState.Inactive)
984 .setVpnInterfaces(null);
985 if (writeTxn != null) {
986 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
988 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build());
990 lastDpnOnVpn = Boolean.TRUE;
992 LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
995 if (writeTxn != null) {
996 writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
997 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
998 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
999 new VpnInterfacesKey(intfName)));
1001 VpnUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
1002 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
1003 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
1004 new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
1009 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
1012 } catch (InterruptedException | ExecutionException e) {
1013 LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
1014 throw new RuntimeException(e.getMessage());
1018 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
1019 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
1023 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1024 List<VpnInstance> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1025 for (VpnInstance vpn : vpnsToExportRoute) {
1026 String rd = vpn.getIpv4Family().getRouteDistinguisher();
1027 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getIpv4Family().getRouteDistinguisher());
1028 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1029 if (vrfEntries != null) {
1030 for (VrfEntry vrfEntry : vrfEntries) {
1032 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.STATIC) {
1035 String prefix = vrfEntry.getDestPrefix();
1036 long label = vrfEntry.getLabel();
1037 List<String> nextHops = vrfEntry.getNextHopAddressList();
1038 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1039 for (String nh : nextHops) {
1040 if (route != null) {
1041 LOG.info("Importing subnet route fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
1042 importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route, writeConfigTxn);
1044 LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
1045 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, prefix, Arrays.asList(nh), (int)label,
1046 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
1049 } catch (Exception e) {
1050 LOG.error("Exception occurred while importing route with prefix {} label {} nexthop {} from vpn {} to vpn {}", vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), vpn.getVpnInstanceName(), vpnName);
1053 writeConfigTxn.submit();
1055 LOG.info("No vrf entries to import from vpn {} with rd {}", vpn.getVpnInstanceName(), vpn.getIpv4Family().getRouteDistinguisher());
1060 private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeConfigTxn) {
1062 LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1063 fibManager.addOrUpdateFibEntry(dataBroker, rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC, writeConfigTxn);
1064 bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
1065 LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1066 } catch(Exception e) {
1067 LOG.error("Add prefix failed", e);
1072 public void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1073 LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
1074 LOG.info("VPN Interface remove event - intfName {}" ,vpnInterface.getName());
1075 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1076 final String interfaceName = key.getName();
1078 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1079 final Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1080 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
1081 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1082 if (optVpnInterface.isPresent()){
1083 BigInteger dpnId = BigInteger.ZERO;
1084 Boolean dpnIdRetrieved = Boolean.FALSE;
1085 if(interfaceState != null){
1087 dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1088 dpnIdRetrieved = Boolean.TRUE;
1089 }catch (Exception e){
1090 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", interfaceName, e);
1093 LOG.error("Unable to retrieve interfaceState for interface {} , quitting ", interfaceName);
1096 final VpnInterface vpnOpInterface = optVpnInterface.get();
1097 if(dpnIdRetrieved == Boolean.FALSE){
1098 LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
1099 dpnId = vpnOpInterface.getDpnId();
1101 final int ifIndex = interfaceState.getIfIndex();
1102 final BigInteger dpId = dpnId;
1103 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1104 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1105 new Callable<List<ListenableFuture<Void>>>() {
1107 public List<ListenableFuture<Void>> call() throws Exception {
1108 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1109 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1110 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
1111 processVpnInterfaceDown(dpId, interfaceName, ifIndex, false, true, writeConfigTxn, writeOperTxn, writeInvTxn);
1112 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
1113 futures.add(writeOperTxn.submit());
1114 futures.add(writeConfigTxn.submit());
1115 futures.add(writeInvTxn.submit());
1121 LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
1125 protected void processVpnInterfaceDown(BigInteger dpId,
1126 String interfaceName,
1128 boolean isInterfaceStateDown,
1129 boolean isConfigRemoval,
1130 WriteTransaction writeConfigTxn,
1131 WriteTransaction writeOperTxn,
1132 WriteTransaction writeInvTxn) {
1133 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1134 if (!isInterfaceStateDown) {
1135 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1136 if(vpnInterface == null){
1137 LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
1140 final String vpnName = vpnInterface.getVpnInstanceName();
1141 if(!vpnInterface.isScheduledForRemove()){
1142 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE, writeOperTxn);
1143 removeAdjacenciesFromVpn(dpId, interfaceName, vpnInterface.getVpnInstanceName(), writeConfigTxn);
1144 LOG.info("Unbinding vpn service from interface {} ", interfaceName);
1145 unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval, writeConfigTxn, writeInvTxn);
1147 LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
1152 // Interface is retained in the DPN, but its Link Down.
1153 // Only withdraw the prefixes for this interface from BGP
1154 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1155 if(vpnInterface == null){
1156 LOG.info("Unable to withdraw adjacencies for vpn interface {} from BGP as it is not available in operational data store", interfaceName);
1159 withdrawAdjacenciesForVpnFromBgp(identifier, vpnInterface);
1164 private void waitForFibToRemoveVpnPrefix(String interfaceName) {
1165 // FIB didn't get a chance yet to clean up this VPNInterface
1166 // Let us give it a chance here !
1167 LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
1169 Runnable notifyTask = new VpnNotifyTask();
1170 vpnIntfMap.put(interfaceName, notifyTask);
1171 synchronized (notifyTask) {
1173 notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
1174 } catch (InterruptedException e) {
1178 vpnIntfMap.remove(interfaceName);
1182 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final String interfaceName, final String vpnName,
1183 WriteTransaction writeConfigTxn) {
1185 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1186 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1187 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1189 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1190 LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", interfaceName,
1192 if (adjacencies.isPresent()) {
1193 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1195 if (!nextHops.isEmpty()) {
1196 LOG.trace("NextHops are " + nextHops);
1197 for (Adjacency nextHop : nextHops) {
1198 List<String> nhList = new ArrayList<String>();
1199 if (nextHop.getMacAddress() == null || nextHop.getMacAddress().isEmpty()) {
1200 // This is either an extra-route (or) a learned IP via subnet-route
1201 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1202 if (nextHopIp == null || nextHopIp.isEmpty()) {
1203 LOG.error("Unable to obtain nextHopIp for extra-route/learned-route in rd {} prefix {}",
1204 rd, nextHop.getIpAddress());
1207 nhList = Arrays.asList(nextHopIp);
1209 // This is a primary adjacency
1210 nhList = nextHop.getNextHopIpList();
1212 if (rd.equals(vpnName)) {
1213 //this is an internal vpn - the rd is assigned to the vpn instance name;
1214 //remove from FIB directly
1215 for(String nh : nhList) {
1216 fibManager.removeOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), nh, writeConfigTxn);
1219 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1220 for (String nh : nhList) {
1221 //IRT: remove routes from other vpns importing it
1222 removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeConfigTxn);
1223 for (VpnInstance vpn : vpnsToImportRoute) {
1224 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
1225 if (vpnRd != null) {
1226 LOG.info("Removing Exported route with rd {} prefix {} from VPN {}", vpnRd, nextHop.getIpAddress(), vpn.getVpnInstanceName());
1227 fibManager.removeOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), nh, writeConfigTxn);
1232 String ip = nextHop.getIpAddress().split("/")[0];
1233 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
1235 if (vpnPortipToPort != null && !vpnPortipToPort.isConfig()) {
1236 LOG.trace("VpnInterfaceManager removing adjacency for Interface {} ip {} from VpnPortData Entry",
1237 vpnPortipToPort.getPortName(),ip);
1238 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip);
1246 private void unbindService(BigInteger dpId, String vpnInstanceName, final String vpnInterfaceName,
1247 int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval,
1248 WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
1249 short l3vpn_service_index = ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX);
1250 if (!isInterfaceStateDown && isConfigRemoval) {
1251 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1252 dataStoreCoordinator.enqueueJob(vpnInterfaceName,
1253 new Callable<List<ListenableFuture<Void>>>() {
1255 public List<ListenableFuture<Void>> call() throws Exception {
1256 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
1257 writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
1258 InterfaceUtils.buildServiceId(vpnInterfaceName,
1259 NwConstants.L3VPN_SERVICE_INDEX));
1261 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
1262 futures.add(writeTxn.submit());
1267 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
1268 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1269 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeInvTxn);
1270 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1271 vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeInvTxn);
1275 private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeConfigTxn) {
1277 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
1278 fibManager.removeOrUpdateFibEntry(dataBroker, rd, prefix, nextHop, writeConfigTxn);
1279 bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
1280 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, prefix);
1281 } catch(Exception e) {
1282 LOG.error("Delete prefix failed", e);
1287 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
1288 LOG.trace("Updating VPN Interface : key {}, original value={}, update value={}", identifier, original, update);
1289 LOG.info("VPN Interface update event - intfName {}" ,update.getName());
1290 String oldVpnName = original.getVpnInstanceName();
1291 String newVpnName = update.getVpnInstanceName();
1292 BigInteger dpnId = update.getDpnId();
1293 List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
1294 List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
1295 if (oldAdjs == null) {
1296 oldAdjs = new ArrayList<>();
1298 if (newAdjs == null) {
1299 newAdjs = new ArrayList<>();
1301 //handles switching between <internal VPN - external VPN>
1302 if (!oldVpnName.equals(newVpnName)) {
1303 remove(identifier, original);
1304 waitForFibToRemoveVpnPrefix(update.getName());
1305 add(identifier, update);
1307 //handle both addition and removal of adjacencies
1308 //currently, new adjacency may be an extra route
1309 if (!oldAdjs.equals(newAdjs)) {
1310 for (Adjacency adj : newAdjs) {
1311 if (oldAdjs.contains(adj)) {
1312 oldAdjs.remove(adj);
1314 // add new adjacency - right now only extra route will hit this path
1315 addNewAdjToVpnInterface(identifier, adj, dpnId);
1318 for (Adjacency adj : oldAdjs) {
1319 delAdjFromVpnInterface(identifier, adj, dpnId);
1324 public void processArpRequest(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
1325 .IpAddress srcIP, PhysAddress srcMac, org.opendaylight.yang.gen.v1.urn.ietf
1326 .params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP, PhysAddress targetMac, String srcInterface){
1327 //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
1328 SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
1329 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
1330 final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
1331 Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
1332 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
1334 public void onFailure(Throwable error) {
1335 LOG.error("Error - {}", msgFormat, error);
1339 public void onSuccess(RpcResult<Void> result) {
1340 if(!result.isSuccessful()) {
1341 LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
1343 LOG.debug("Successful RPC Result - {}", msgFormat);
1349 private String getErrorText(Collection<RpcError> errors) {
1350 StringBuilder errorText = new StringBuilder();
1351 for(RpcError error : errors) {
1352 errorText.append(",").append(error.getErrorType()).append("-")
1353 .append(error.getMessage());
1355 return errorText.toString();
1358 private void addToLabelMapper(Long label, BigInteger dpnId, String prefix, List<String> nextHopIpList, Long vpnId,
1359 String vpnInterfaceName, Long elanTag, boolean isSubnetRoute, String rd,
1360 WriteTransaction writeOperTxn) {
1361 Preconditions.checkNotNull(label, "label cannot be null or empty!");
1362 Preconditions.checkNotNull(prefix, "prefix cannot be null or empty!");
1363 Preconditions.checkNotNull(vpnId, "vpnId cannot be null or empty!");
1364 Preconditions.checkNotNull(rd, "rd cannot be null or empty!");
1365 if (!isSubnetRoute) {
1366 // NextHop must be present for non-subnetroute entries
1367 Preconditions.checkNotNull(nextHopIpList, "nextHopIp cannot be null or empty!");
1369 LOG.info("Adding to label mapper : label {} dpn {} prefix {} nexthoplist {} vpnid {} vpnIntfcName {} rd {}", label, dpnId, prefix, nextHopIpList, vpnId, vpnInterfaceName, rd);
1370 if (dpnId != null) {
1371 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1372 .child(LabelRouteInfo.class, new LabelRouteInfoKey((long)label)).build();
1373 LabelRouteInfoBuilder lriBuilder = new LabelRouteInfoBuilder();
1374 lriBuilder.setLabel(label).setDpnId(dpnId).setPrefix(prefix).setNextHopIpList(nextHopIpList).setParentVpnid(vpnId)
1375 .setIsSubnetRoute(isSubnetRoute);
1376 if (elanTag != null) {
1377 lriBuilder.setElanTag(elanTag);
1379 if (vpnInterfaceName != null) {
1380 lriBuilder.setVpnInterfaceName(vpnInterfaceName);
1382 lriBuilder.setParentVpnRd(rd);
1383 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
1384 if (vpnInstanceOpDataEntry != null) {
1385 List<String> vpnInstanceNames = Arrays.asList(vpnInstanceOpDataEntry.getVpnInstanceName());
1386 lriBuilder.setVpnInstanceList(vpnInstanceNames);
1388 LabelRouteInfo lri = lriBuilder.build();
1389 LOG.trace("Adding route info to label map: {}", lri);
1390 if (writeOperTxn != null) {
1391 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, lriIid, lri, true);
1393 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, lri);
1396 LOG.trace("Can't add entry to label map for lable {},dpnId is null", label);
1400 public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
1401 long elantag, BigInteger dpnId, WriteTransaction writeTxn) {
1402 SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
1403 RouteOrigin origin = RouteOrigin.STATIC; // Only case when a route is considered as directly connected
1404 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1405 .setLabel((long)label).setOrigin(origin.getValue())
1406 .addAugmentation(SubnetRoute.class, route).build();
1408 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, elantag);
1410 //TODO: What should be parentVpnId? Get it from RD?
1411 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1412 addToLabelMapper((long)label, dpnId, prefix, Arrays.asList(nextHop), vpnId, null, elantag, true, rd, null);
1413 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1415 InstanceIdentifierBuilder<VrfTables> idBuilder =
1416 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1417 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1419 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1420 setVrfEntry(vrfEntryList).build();
1422 if (writeTxn != null) {
1423 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1425 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1428 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1429 if (vpnsToImportRoute.size() > 0) {
1430 VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1431 .setLabel((long) label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
1432 .addAugmentation(SubnetRoute.class, route).build();
1433 List<VrfEntry> importingVrfEntryList = Arrays.asList(importingVrfEntry);
1434 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1435 LOG.info("Exporting subnet route rd {} prefix {} nexthop {} label {} to vpn {}", rd, prefix, nextHop, label, vpnInstance.getVpnInstanceName());
1436 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1437 InstanceIdentifier<VrfTables> importingVrfTableId = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(importingRd)).build();
1438 VrfTables importingVrfTable = new VrfTablesBuilder().setRouteDistinguisher(importingRd).setVrfEntry(importingVrfEntryList).build();
1439 if (writeTxn != null) {
1440 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable, true);
1442 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
1448 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1449 SubnetRoute route, WriteTransaction writeConfigTxn) {
1451 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1452 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1453 .setLabel((long)label).setOrigin(origin.getValue())
1454 .addAugmentation(SubnetRoute.class, route).build();
1455 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, route.getElantag());
1456 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1457 InstanceIdentifierBuilder<VrfTables> idBuilder =
1458 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1459 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1460 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1461 setVrfEntry(vrfEntryList).build();
1462 if (writeConfigTxn != null) {
1463 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1465 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1469 public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
1470 fibManager.removeFibEntry(dataBroker, rd, prefix, null);
1471 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1472 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1473 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1474 LOG.info("Deleting imported subnet route rd {} prefix {} from vpn {}", rd, prefix, vpnInstance.getVpnInstanceName());
1475 fibManager.removeFibEntry(dataBroker, importingRd, prefix, null);
1479 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1481 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1483 if (optVpnInterface.isPresent()) {
1484 VpnInterface currVpnIntf = optVpnInterface.get();
1485 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1486 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1487 rd = (rd != null) ? rd : currVpnIntf.getVpnInstanceName();
1488 InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
1489 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, adjPath);
1491 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1492 VpnUtil.getNextHopLabelKey(rd, prefix));
1494 List<Adjacency> adjacencies;
1495 if (optAdjacencies.isPresent()) {
1496 adjacencies = optAdjacencies.get().getAdjacency();
1498 //This code will not be hit since VM adjacency will always be there
1499 adjacencies = new ArrayList<>();
1502 adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIpList(adj.getNextHopIpList())
1503 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
1505 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1506 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove());
1508 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1509 for (String nh : adj.getNextHopIpList()) {
1510 addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
1511 currVpnIntf.getName());
1516 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1517 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1519 if (optVpnInterface.isPresent()) {
1520 VpnInterface currVpnIntf = optVpnInterface.get();
1522 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1523 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1524 if (optAdjacencies.isPresent()) {
1525 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1527 if (!adjacencies.isEmpty()) {
1528 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1529 rd = (rd != null) ? rd :currVpnIntf.getVpnInstanceName();
1530 LOG.trace("Adjacencies are " + adjacencies);
1531 Iterator<Adjacency> adjIt = adjacencies.iterator();
1532 while (adjIt.hasNext()) {
1533 Adjacency adjElem = adjIt.next();
1534 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1537 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1538 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
1539 currVpnIntf.getVpnInstanceName(),
1540 aug, dpnId, currVpnIntf.isScheduledForRemove());
1542 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1544 for (String nh : adj.getNextHopIpList()) {
1545 delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
1546 currVpnIntf.getName());
1558 protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label,
1561 //add extra route to vpn mapping; advertise with nexthop as tunnel ip
1564 LogicalDatastoreType.OPERATIONAL,
1565 VpnUtil.getVpnToExtrarouteIdentifier( (rd != null) ? rd : routerID, destination),
1566 VpnUtil.getVpnToExtraroute(destination, Arrays.asList(nextHop)));
1568 BigInteger dpnId = null;
1569 if (intfName != null && !intfName.isEmpty()) {
1570 dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1571 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1572 if (nextHopIp == null || nextHopIp.isEmpty()) {
1573 LOG.error("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1574 intfName, destination);
1577 nextHop = nextHopIp;
1579 List<String> nextHopIpList = Arrays.asList(nextHop);
1581 /* Label mapper is required only for BGP VPN and not for Internal VPN */
1582 addToLabelMapper((long) label, dpnId, destination, nextHopIpList, VpnUtil.getVpnId(dataBroker, routerID),
1583 intfName, null, false, rd, null);
1586 // TODO (eperefr): This is a limitation to be stated in docs. When configuring static route to go to
1587 // another VPN, there can only be one nexthop or, at least, the nexthop to the interVpnLink should be in
1589 Optional<InterVpnLink> optInterVpnLink = InterVpnLinkUtil.getInterVpnLinkByEndpointIp(dataBroker, nextHop);
1590 if ( optInterVpnLink.isPresent() ) {
1591 InterVpnLink interVpnLink = optInterVpnLink.get();
1592 // If the nexthop is the endpoint of Vpn2, then prefix must be advertised to Vpn1 in DC-GW, with nexthops
1593 // pointing to the DPNs where Vpn1 is instantiated. LFIB in these DPNS must have a flow entry, with lower
1594 // priority, where if Label matches then sets the lportTag of the Vpn2 endpoint and goes to LportDispatcher
1595 // This is like leaking one of the Vpn2 routes towards Vpn1
1596 boolean nexthopIsVpn2 = ( interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nextHop) );
1597 String srcVpnUuid = (nexthopIsVpn2) ? interVpnLink.getSecondEndpoint().getVpnUuid().getValue()
1598 : interVpnLink.getFirstEndpoint().getVpnUuid().getValue();
1599 String dstVpnUuid = (nexthopIsVpn2) ? interVpnLink.getFirstEndpoint().getVpnUuid().getValue()
1600 : interVpnLink.getSecondEndpoint().getVpnUuid().getValue();
1601 String dstVpnRd = VpnUtil.getVpnRd(dataBroker, dstVpnUuid);
1602 long newLabel = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1603 VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
1604 InterVpnLinkUtil.leakRoute(dataBroker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
1607 addPrefixToBGP(rd, destination, nextHop, label, null);
1609 // ### add FIB route directly
1610 fibManager.addOrUpdateFibEntry(dataBroker, routerID, destination, Arrays.asList(nextHop), label, RouteOrigin.STATIC, null);
1615 protected void delExtraRoute(String destination, String nextHop, String rd, String routerID, String intfName) {
1616 if (intfName != null && !intfName.isEmpty()) {
1617 BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1618 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1619 if (nextHopIp == null || nextHopIp.isEmpty()) {
1620 LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1621 intfName, destination);
1623 nextHop = nextHopIp;
1627 removePrefixFromBGP(rd, destination, nextHop, null);
1629 // ### add FIB route directly
1630 fibManager.removeOrUpdateFibEntry(dataBroker, routerID, destination, nextHop, null);
1634 void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1635 LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
1636 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1637 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
1638 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1639 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1641 public void onFailure(Throwable error) {
1642 LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
1646 public void onSuccess(Object arg) {
1647 LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
1652 void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1653 LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
1654 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1655 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
1656 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1657 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1659 public void onFailure(Throwable error) {
1660 LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
1664 public void onSuccess(Object arg) {
1665 LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
1670 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1671 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1672 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1673 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1676 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1677 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1678 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1681 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1682 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1683 if(dpId.equals(BigInteger.ZERO)) {
1684 LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
1687 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1689 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1690 .OPERATIONAL, routerDpnListIdentifier);
1691 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1692 if (optionalRouterDpnList.isPresent()) {
1693 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1694 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1696 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1697 builder.setRouterId(routerName);
1698 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1699 List<RouterInterfaces> routerInterfaces = new ArrayList<>();
1700 routerInterfaces.add(routerInterface);
1701 builder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
1702 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1703 getRouterId(routerName),
1704 builder.build(), true);
1708 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1709 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1710 if(dpId.equals(BigInteger.ZERO)) {
1711 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1714 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1715 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1716 .OPERATIONAL, routerDpnListIdentifier);
1717 if (optionalRouterDpnList.isPresent()) {
1718 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1719 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1721 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1722 if (routerInterfaces.isEmpty()) {
1723 if (writeOperTxn != null) {
1724 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1726 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1729 if (writeOperTxn != null) {
1730 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1731 RouterInterfaces.class,
1732 new RouterInterfacesKey(vpnInterfaceName)));
1734 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1735 RouterInterfaces.class,
1736 new RouterInterfacesKey(vpnInterfaceName)));
1743 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1744 WriteTransaction writeOperTxn) {
1745 if(dpId.equals(BigInteger.ZERO)) {
1746 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1749 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1750 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1751 .OPERATIONAL, routerDpnListIdentifier);
1752 if (optionalRouterDpnList.isPresent()) {
1753 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1754 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1755 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1756 if (routerInterfaces.isEmpty()) {
1757 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1759 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1760 RouterInterfaces.class,
1761 new RouterInterfacesKey(vpnInterfaceName)));
1767 void notifyTaskIfRequired(String intfName) {
1768 Runnable notifyTask = vpnIntfMap.remove(intfName);
1769 if (notifyTask == null) {
1772 executorService.execute(notifyTask);