Merge "Multiple fixes in different module"
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnInterfaceManager.java
1 /*
2  * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.vpnmanager;
9
10 import com.google.common.util.concurrent.ThreadFactoryBuilder;
11 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
12 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
13 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
14
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.JdkFutureAdapters;
18
19 import org.opendaylight.controller.md.sal.binding.api.*;
20 import org.opendaylight.genius.mdsalutil.*;
21 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRouteBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
43 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;
44 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;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInputBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
57
58 import java.math.BigInteger;
59 import java.util.Collection;
60 import java.util.Iterator;
61 import java.util.List;
62 import java.util.ArrayList;
63 import java.util.concurrent.*;
64
65 import com.google.common.base.Optional;
66
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
71 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
72 import org.opendaylight.yangtools.concepts.ListenerRegistration;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
75 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
76 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
86 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
87 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
88 import org.opendaylight.yangtools.yang.common.RpcError;
89 import org.opendaylight.yangtools.yang.common.RpcResult;
90 import org.slf4j.Logger;
91 import org.slf4j.LoggerFactory;
92
93 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
94     private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
95     private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration;
96     private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
97         .setNameFormat("NV-VpnIntfMgr-%d").build();
98     private final DataBroker broker;
99     private final IBgpManager bgpManager;
100     private IFibManager fibManager;
101     private IMdsalApiManager mdsalManager;
102     private OdlInterfaceRpcService interfaceManager;
103     private ItmRpcService itmProvider;
104     private IdManagerService idManager;
105     private OdlArputilService arpManager;
106     private NeutronvpnService neuService;
107     private VpnSubnetRouteHandler vpnSubnetRouteHandler;
108     private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
109     private ExecutorService executorService = Executors.newSingleThreadExecutor();
110     private InterfaceStateChangeListener interfaceListener;
111     private VpnInterfaceOpListener vpnInterfaceOpListener;
112     private ArpNotificationHandler arpNotificationHandler;
113     protected enum UpdateRouteAction {
114         ADVERTISE_ROUTE, WITHDRAW_ROUTE
115     }
116     /**
117      * Responsible for listening to data change related to VPN Interface
118      * Bind VPN Service on the interface and informs the BGP service
119      *
120      * @param db - dataBroker service reference
121      */
122     public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) {
123         super(VpnInterface.class);
124         broker = db;
125         this.bgpManager = bgpManager;
126         interfaceListener = new InterfaceStateChangeListener(db, this);
127         vpnInterfaceOpListener = new VpnInterfaceOpListener();
128         arpNotificationHandler = new ArpNotificationHandler(this, broker);
129         notificationService.registerNotificationListener(arpNotificationHandler);
130         vpnSubnetRouteHandler = new VpnSubnetRouteHandler(broker, bgpManager, this);
131         notificationService.registerNotificationListener(vpnSubnetRouteHandler);
132         registerListener(db);
133     }
134
135     public void setMdsalManager(IMdsalApiManager mdsalManager) {
136         this.mdsalManager = mdsalManager;
137     }
138
139     public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
140         this.interfaceManager = interfaceManager;
141         interfaceListener.setInterfaceManager(interfaceManager);
142     }
143
144     public void setITMProvider(ItmRpcService itmProvider) {
145         this.itmProvider = itmProvider;
146     }
147
148     public void setFibManager(IFibManager fibManager) {
149         this.fibManager = fibManager;
150     }
151
152     public IFibManager getFibManager() {
153         return this.fibManager;
154     }
155
156     public void setIdManager(IdManagerService idManager) {
157         this.idManager = idManager;
158         vpnSubnetRouteHandler.setIdManager(idManager);
159     }
160
161     public void setArpManager(OdlArputilService arpManager) {
162         this.arpManager = arpManager;
163     }
164
165     public void setNeutronvpnManager(NeutronvpnService neuService) { this.neuService = neuService; }
166
167     public VpnSubnetRouteHandler getVpnSubnetRouteHandler() {
168         return this.vpnSubnetRouteHandler;
169     }
170
171     @Override
172     public void close() throws Exception {
173         if (listenerRegistration != null) {
174             try {
175                 listenerRegistration.close();
176                 opListenerRegistration.close();
177             } catch (final Exception e) {
178                 LOG.error("Error when cleaning up DataChangeListener.", e);
179             }
180             listenerRegistration = null;
181             opListenerRegistration = null;
182         }
183         LOG.info("VPN Interface Manager Closed");
184     }
185
186     private void registerListener(final DataBroker db) {
187         try {
188             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
189                     getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
190             opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
191                                                                    getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
192         } catch (final Exception e) {
193             LOG.error("VPN Service DataChange listener registration fail!", e);
194             throw new IllegalStateException("VPN Service registration Listener failed.", e);
195         }
196     }
197
198     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
199         return InstanceIdentifier.create(InterfacesState.class)
200             .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
201     }
202
203     @Override
204     protected void add(final InstanceIdentifier<VpnInterface> identifier,
205             final VpnInterface vpnInterface) {
206         LOG.trace("VPN Interface key: {} , value: {}", identifier, vpnInterface );
207         addInterface(identifier, vpnInterface);
208     }
209
210     private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
211                               final VpnInterface vpnInterface) {
212         LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
213         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
214         String interfaceName = key.getName();
215
216         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
217             InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
218         if (interfaceState != null) {
219             // Interface state is up
220             processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex());
221         } else {
222             LOG.trace("VPN interfaces are not yet operational.");
223         }
224     }
225
226     protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag) {
227
228         VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
229         if(vpnInterface == null) {
230             LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
231             return;
232         }
233         String vpnName = vpnInterface.getVpnInstanceName();
234         LOG.info("Binding vpn service to interface {} ", interfaceName);
235         long vpnId = VpnUtil.getVpnId(broker, vpnName);
236         if (vpnId == VpnConstants.INVALID_ID) {
237             LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
238             return;
239         }
240         boolean waitForVpnInterfaceOpRemoval = false;
241         int numAdjs = 0;
242         VpnInterface opVpnInterface = null;
243         synchronized (interfaceName.intern()) {
244             opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName());
245             if (opVpnInterface != null ) {
246                 String opVpnName = opVpnInterface.getVpnInstanceName();
247                 String primaryInterfaceIp = null;
248                 if(opVpnName.equals(vpnName)) {
249                     // Please check if the primary VRF Entry does not exist for VPNInterface
250                     // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
251                     // back to back
252                     // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
253                     List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(broker, interfaceName);
254                     if (adjs == null) {
255                         LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained",
256                                 interfaceName);
257                         return;
258                     }
259                     numAdjs = adjs.size();
260                     for (Adjacency adj : adjs) {
261                         if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
262                             primaryInterfaceIp = adj.getNextHopIp();
263                             break;
264                         }
265                     }
266                     if (primaryInterfaceIp == null) {
267                         LOG.info("VPN Interface {} addition failed as primary adjacency for this vpn interface could not be obtained",
268                                 interfaceName);
269                         return;
270                     }
271                     // Get the rd of the vpn instance
272                     String rd = getRouteDistinguisher(opVpnName);
273                     VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, primaryInterfaceIp);
274                     if (vrf != null) {
275                         LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
276                         return;
277                     }
278                     waitForVpnInterfaceOpRemoval = true;
279                 } else {
280                     LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}", interfaceName, vpnName, opVpnName);
281                 }
282             }
283             if (!waitForVpnInterfaceOpRemoval) {
284                 // Add the VPNInterface and quit
285                 bindService(dpId, vpnName, interfaceName, lPortTag);
286                 updateDpnDbs(dpId, vpnName, interfaceName, true);
287                 processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
288                 return;
289             }
290         }
291
292         // FIB didn't get a chance yet to clean up this VPNInterface
293         // Let us give it a chance here !
294         LOG.info("VPN Interface {} waiting for FIB to clean up! ", interfaceName);
295         try {
296             Runnable notifyTask = new VpnNotifyTask();
297             vpnIntfMap.put(interfaceName, notifyTask);
298             synchronized (notifyTask) {
299                 try {
300                     notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
301                 } catch (InterruptedException e) {
302                 }
303             }
304         } finally {
305             vpnIntfMap.remove(interfaceName);
306         }
307
308         opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
309         if (opVpnInterface != null) {
310             LOG.error("VPN Interface {} removal by FIB did not complete on time, bailing addition ...", interfaceName);
311             return;
312         }
313         // VPNInterface got removed, proceed with Add
314         synchronized (interfaceName.intern()) {
315             bindService(dpId, vpnName, interfaceName, lPortTag);
316             updateDpnDbs(dpId, vpnName, interfaceName, true);
317             processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
318         }
319     }
320
321     private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
322         long vpnId = VpnUtil.getVpnId(broker, vpnName);
323         if (dpId == null) {
324             dpId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
325         }
326         if(!dpId.equals(BigInteger.ZERO)) {
327             if(add)
328                 updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
329             else
330                 removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
331         }
332
333     }
334
335     private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
336         int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
337         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
338
339         int instructionKey = 0;
340         List<Instruction> instructions = new ArrayList<>();
341
342         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
343         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
344
345         BoundServices
346             serviceInfo =
347             InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
348                                             VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
349                                             VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
350         VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
351                           InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
352         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
353                     vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
354         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
355                 vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW);
356
357     }
358
359     private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
360         String intfName = intf.getName();
361
362         synchronized (intfName) {
363             // Read NextHops
364             InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
365             Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
366
367             if (adjacencies.isPresent()) {
368                 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
369                 List<Adjacency> value = new ArrayList<>();
370
371                 // Get the rd of the vpn instance
372                 String rd = getRouteDistinguisher(intf.getVpnInstanceName());
373
374                 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
375                 if (nextHopIp == null){
376                     LOG.error("NextHop for interface {} is null", intfName);
377                 }
378
379                 LOG.trace("NextHops are {}", nextHops);
380                 for (Adjacency nextHop : nextHops) {
381                     String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
382                     long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
383                             .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
384                     String adjNextHop = nextHop.getNextHopIp();
385                     value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIp((adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp)
386                             .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
387                     if(nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
388                         VpnUtil.syncUpdate(
389                                 broker,
390                                 LogicalDatastoreType.OPERATIONAL,
391                                 VpnUtil.getPrefixToInterfaceIdentifier(
392                                         VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
393                                 VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
394                     } else {
395                         //Extra route adjacency
396                         VpnUtil.syncUpdate(
397                                 broker,
398                                 LogicalDatastoreType.OPERATIONAL,
399                                 VpnUtil.getVpnToExtrarouteIdentifier(
400                                         (rd != null) ? rd : intf.getVpnInstanceName(), nextHop.getIpAddress()),
401                                 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIp()));
402
403                     }
404                 }
405
406                 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
407                 VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
408                 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
409                 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
410                 for (Adjacency nextHop : aug.getAdjacency()) {
411                     long label = nextHop.getLabel();
412                     //String adjNextHop = nextHop.getNextHopIp();
413                     if (rd != null) {
414                         addPrefixToBGP(rd, nextHop.getIpAddress(),
415                                             nextHopIp, label);
416                     } else {
417                         // ### add FIB route directly
418                         addFibEntryToDS(intf.getVpnInstanceName(), nextHop.getIpAddress(),
419                                             nextHopIp, (int) label);
420                     }
421                 }
422             }
423         }
424     }
425
426     private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
427                              long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
428         List<MatchInfo> matches = new ArrayList<>();
429         BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
430         BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
431                 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
432
433         // Matching Arp reply flows
434         matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
435         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
436                 metadata, metadataMask }));
437
438         matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
439
440         // Instruction to punt to controller
441         List<InstructionInfo> instructions = new ArrayList<>();
442         List<ActionInfo> actionsInfos = new ArrayList<>();
443         actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
444         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
445
446         // Install the flow entry in L3_INTERFACE_TABLE
447         String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
448                     NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
449         FlowEntity flowEntity;
450         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
451                 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
452                 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
453
454         if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
455             LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
456             mdsalManager.installFlow(flowEntity);
457         } else {
458             LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
459             mdsalManager.removeFlow(flowEntity);
460         }
461     }
462
463     private String getRouteDistinguisher(String vpnName) {
464         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
465                                       .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
466         Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
467         String rd = "";
468         if(vpnInstance.isPresent()) {
469             VpnInstance instance = vpnInstance.get();
470             VpnAfConfig config = instance.getIpv4Family();
471             rd = config.getRouteDistinguisher();
472         }
473         return rd;
474     }
475
476     private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
477         String routeDistinguisher = getRouteDistinguisher(vpnName);
478         String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
479         InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
480         Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
481         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
482             vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
483
484         if (dpnInVpn.isPresent()) {
485             VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
486                 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance
487                     .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
488                     new VpnInterfacesKey(intfName)), vpnInterface);
489         } else {
490             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
491                                     VpnUtil.getVpnInstanceOpDataIdentifier(rd),
492                                     VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId));
493             VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
494             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
495                 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces =  new ArrayList<>();
496             vpnInterfaces.add(vpnInterface);
497             VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
498                               vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
499
500             /**
501              * FIXME: DC Gateway tunnel should be built dynamically
502             //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
503             //if tunnel to DC GW does not exist, create it
504             //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
505             String dcGW = bgpManager.getDCGwIP();
506             if(dcGW != null && !dcGW.isEmpty())
507             {
508                 LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
509                 itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
510             }*/
511             fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
512         }
513     }
514
515     private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
516         //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
517         String rd = VpnUtil.getVpnRd(broker, vpnName);
518         InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
519         Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
520         if (dpnInVpn.isPresent()) {
521             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
522                 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
523             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
524                     currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
525
526             if (vpnInterfaces.remove(currVpnInterface)) {
527                 if (vpnInterfaces.isEmpty()) {
528                     VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
529                     fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
530                 } else {
531                     VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
532                         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
533                             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
534                             new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
535                 }
536             }
537         }
538     }
539
540     private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
541         try {
542             //FIXME: TBD once odl-fib yang has nexthoplist and related changes follow
543             //bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
544         } catch(Exception e) {
545             LOG.error("Add prefix failed", e);
546         }
547     }
548
549
550     private InstanceIdentifier<VpnInterface> getWildCardPath() {
551         return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
552     }
553
554     @Override
555     protected void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
556         LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
557         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
558         String interfaceName = key.getName();
559
560         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
561         Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
562         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
563             InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
564
565         if (existingVpnInterface.isPresent() && interfaceState != null) {
566             processVpnInterfaceDown(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex(), false);
567         } else {
568             LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
569         }
570     }
571
572     protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
573         VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
574         if(vpnInterface == null) {
575             LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
576             return;
577         }
578         String vpnName = vpnInterface.getVpnInstanceName();
579         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
580
581         synchronized (interfaceName.intern()) {
582             removeAdjacenciesFromVpn(identifier, vpnInterface);
583             LOG.info("Unbinding vpn service from interface {} ", interfaceName);
584             unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown);
585         }
586
587         // FIB didn't get a chance yet to clean up this VPNInterface
588         // Let us give it a chance here !
589         LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
590         try {
591             Runnable notifyTask = new VpnNotifyTask();
592             vpnIntfMap.put(interfaceName, notifyTask);
593             synchronized (notifyTask) {
594                 try {
595                     notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
596                 } catch (InterruptedException e) {
597                 }
598             }
599         } finally {
600             vpnIntfMap.remove(interfaceName);
601         }
602
603     }
604
605     private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
606         //Read NextHops
607         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
608         Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
609
610         String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
611         LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", intf.getName(),
612                 intf.getVpnInstanceName(), rd);
613         if (adjacencies.isPresent()) {
614             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
615
616             if (!nextHops.isEmpty()) {
617                 LOG.trace("NextHops are " + nextHops);
618                 for (Adjacency nextHop : nextHops) {
619                     // Commenting the release of ID here as it will be released by FIB
620                    /* VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
621                                       VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
622                     VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
623                                    VpnUtil.getPrefixToInterfaceIdentifier(
624                                        VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
625                                        nextHop.getIpAddress()),
626                                    VpnUtil.DEFAULT_CALLBACK);*/
627                     if (rd.equals(intf.getVpnInstanceName())) {
628                         //this is an internal vpn - the rd is assigned to the vpn instance name;
629                         //remove from FIB directly
630                         removeFibEntryFromDS(intf.getVpnInstanceName(), nextHop.getIpAddress());
631                     } else {
632                         removePrefixFromBGP(rd, nextHop.getIpAddress());
633                     }
634                 }
635             }
636         }
637     }
638
639
640     private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
641                                int lPortTag, boolean isInterfaceStateDown) {
642         if (!isInterfaceStateDown) {
643             MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
644                            InterfaceUtils.buildServiceId(vpnInterfaceName,
645                                                          VpnConstants.L3VPN_SERVICE_IDENTIFIER));
646         }
647         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
648         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
649                     vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
650         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
651                 vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW);
652     }
653
654
655     private void removePrefixFromBGP(String rd, String prefix) {
656         removeFibEntryFromDS(rd, prefix);
657         try {
658             bgpManager.withdrawPrefix(rd, prefix);
659         } catch(Exception e) {
660             LOG.error("Delete prefix failed", e);
661         }
662     }
663
664     @Override
665     protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
666         if (LOG.isTraceEnabled()) {
667             LOG.trace("Updating VPN Interface : key " + identifier + ",  original value=" + original + ", update " +
668                     "value=" + update);
669         }
670         String oldVpnName = original.getVpnInstanceName();
671         String newVpnName = update.getVpnInstanceName();
672         List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
673         List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
674         if (oldAdjs == null) {
675             oldAdjs = new ArrayList<>();
676         }
677         if (newAdjs == null) {
678             newAdjs = new ArrayList<>();
679         }
680         //handles switching between <internal VPN - external VPN>
681         if (!oldVpnName.equals(newVpnName)) {
682             remove(identifier, original);
683             add(identifier, update);
684         }
685         //handle both addition and removal of adjacencies
686         //currently, new adjacency may be an extra route
687         if (!oldAdjs.equals(newAdjs)) {
688             for (Adjacency adj : newAdjs) {
689                 if (oldAdjs.contains(adj)) {
690                     oldAdjs.remove(adj);
691                 } else {
692                     // add new adjacency - right now only extra route will hit this path
693                     addNewAdjToVpnInterface(identifier, adj);
694                 }
695             }
696             for (Adjacency adj : oldAdjs) {
697                 delAdjFromVpnInterface(identifier, adj);
698             }
699         }
700     }
701
702     public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, PhysAddress targetMac,String srcInterface){
703         //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
704         SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
705                 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
706         final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
707         Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
708         Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
709             @Override
710             public void onFailure(Throwable error) {
711                 LOG.error("Error - {}", msgFormat, error);
712             }
713
714             @Override
715             public void onSuccess(RpcResult<Void> result) {
716                 if(!result.isSuccessful()) {
717                     LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
718                 } else {
719                     LOG.debug("Successful RPC Result - {}", msgFormat);
720                 }
721             }
722         });
723     }
724
725     private String getErrorText(Collection<RpcError> errors) {
726         StringBuilder errorText = new StringBuilder();
727         for(RpcError error : errors) {
728             errorText.append(",").append(error.getErrorType()).append("-")
729                      .append(error.getMessage());
730         }
731         return errorText.toString();
732     }
733
734     private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
735         return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
736     }
737
738
739
740     public synchronized void addFibEntryToDS(String rd, String prefix,
741             String nexthop, int label) {
742
743         VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
744                     setNextHopAddress(nexthop).setLabel((long)label).build();
745         LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label);
746
747         List<VrfEntry> vrfEntryList = new ArrayList<>();
748         vrfEntryList.add(vrfEntry);
749
750         InstanceIdentifierBuilder<VrfTables> idBuilder =
751                     InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
752         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
753
754         VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
755                     setVrfEntry(vrfEntryList).build();
756
757         VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
758     }
759
760     public synchronized void addSubnetRouteFibEntryToDS(String rd, String prefix,
761                                                         String nexthop, int label,long elantag) {
762
763         SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
764
765         VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
766                 setNextHopAddress(nexthop).setLabel((long)label).addAugmentation(SubnetRoute.class,route).build();
767         LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nexthop, label, elantag);
768
769         List<VrfEntry> vrfEntryList = new ArrayList<VrfEntry>();
770         vrfEntryList.add(vrfEntry);
771
772         InstanceIdentifierBuilder<VrfTables> idBuilder =
773                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
774         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
775
776         VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
777                 setVrfEntry(vrfEntryList).build();
778
779         VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
780     }
781
782     public synchronized void removeFibEntryFromDS(String rd, String prefix) {
783
784         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
785
786         InstanceIdentifierBuilder<VrfEntry> idBuilder =
787             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
788         InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
789         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
790
791     }
792
793     public synchronized void removeVrfFromDS(String rd) {
794         LOG.debug("Removing vrf table for  rd {}", rd);
795
796         InstanceIdentifierBuilder<VrfTables> idBuilder =
797                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
798         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
799
800         VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
801
802     }
803
804     protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
805
806         Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
807
808         if (optVpnInterface.isPresent()) {
809             VpnInterface currVpnIntf = optVpnInterface.get();
810             String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
811             String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
812             InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
813             Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath);
814             long label =
815                     VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
816                             VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
817
818             List<Adjacency> adjacencies;
819             if (optAdjacencies.isPresent()) {
820                 adjacencies = optAdjacencies.get().getAdjacency();
821             } else {
822                 //This code will not be hit since VM adjacency will always be there
823                 adjacencies = new ArrayList<>();
824             }
825
826             adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIp(adj.getNextHopIp())
827                     .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
828
829             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
830             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
831
832             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
833             addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label, currVpnIntf.getName());
834
835         }
836
837     }
838
839     protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
840         Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
841
842         if (optVpnInterface.isPresent()) {
843             VpnInterface currVpnIntf = optVpnInterface.get();
844
845             InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
846             Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
847             if (optAdjacencies.isPresent()) {
848                 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
849
850                 if (!adjacencies.isEmpty()) {
851                     String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
852                     LOG.trace("Adjacencies are " + adjacencies);
853                     Iterator<Adjacency> adjIt = adjacencies.iterator();
854                     while (adjIt.hasNext()) {
855                         Adjacency adjElem = adjIt.next();
856                         if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
857                             // Commenting the release of ID here as it will be released by FIB
858                            /* VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
859                                     VpnUtil.getNextHopLabelKey(rd, adj.getIpAddress()));*/
860                             adjIt.remove();
861
862                             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
863                             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
864                                                                               currVpnIntf.getVpnInstanceName(),
865                                                                               aug);
866
867                             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
868
869                             delExtraRoute(adj.getIpAddress(), rd, currVpnIntf.getVpnInstanceName());
870                             break;
871                         }
872
873                     }
874                 }
875             }
876         }
877
878     }
879
880     protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label, String intfName) {
881
882         //add extra route to vpn mapping; advertise with nexthop as tunnel ip
883         VpnUtil.syncUpdate(
884             broker,
885             LogicalDatastoreType.OPERATIONAL,
886             VpnUtil.getVpnToExtrarouteIdentifier(
887                 (rd != null) ? rd : routerID, destination),
888             VpnUtil.getVpnToExtraroute(destination, nextHop));
889
890         if (intfName != null && !intfName.isEmpty()) {
891             BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
892             String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
893             if (nextHopIp == null || nextHopIp.isEmpty()) {
894                 LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}", intfName, destination);
895             }
896             nextHop = nextHopIp;
897         }
898         if (rd != null) {
899             addPrefixToBGP(rd, destination, nextHop, label);
900         } else {
901             // ### add FIB route directly
902             addFibEntryToDS(routerID, destination, nextHop, label);
903         }
904     }
905
906     protected void delExtraRoute(String destination, String rd, String routerID) {
907         if (rd != null) {
908             removePrefixFromBGP(rd, destination);
909         } else {
910             // ### add FIB route directly
911             removeFibEntryFromDS(routerID, destination);
912         }
913     }
914
915     class VpnInterfaceOpListener extends AbstractDataChangeListener<VpnInterface> {
916
917         public VpnInterfaceOpListener() {
918             super(VpnInterface.class);
919         }
920
921         @Override
922         protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
923             final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
924             String interfaceName = key.getName();
925             String vpnName = del.getVpnInstanceName();
926
927             LOG.trace("VpnInterfaceOpListener removed: interface name {} vpnName {}", interfaceName, vpnName);
928             //decrement the vpn interface count in Vpn Instance Op Data
929             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
930                     id = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
931             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
932                     = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
933
934             if (vpnInstance.isPresent()) {
935                 String rd = null;
936                 rd = vpnInstance.get().getVrfId();
937                 //String rd = getRouteDistinguisher(del.getVpnInstanceName());
938
939                 VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
940                 LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} in Vpn Op Instance {}",
941                         interfaceName, rd, vpnName, vpnInstOp);
942
943                 if (vpnInstOp != null) {
944                     // Vpn Interface removed => No more adjacencies from it.
945                     // Hence clean up interface from vpn-dpn-interface list.
946                     Adjacency adjacency = del.getAugmentation(Adjacencies.class).getAdjacency().get(0);
947                     Optional<Prefixes> prefixToInterface = Optional.absent();
948                     prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
949                             VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
950                                     VpnUtil.getIpPrefix(adjacency.getIpAddress())));
951                     if (!prefixToInterface.isPresent()) {
952                         prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
953                                 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
954                                         VpnUtil.getIpPrefix(adjacency.getNextHopIp())));
955                     }
956                     if (prefixToInterface.isPresent()) {
957                         VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
958                                 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
959                                         prefixToInterface.get().getIpAddress()),
960                                 VpnUtil.DEFAULT_CALLBACK);
961                         synchronized (interfaceName.intern()) {
962                             updateDpnDbs(prefixToInterface.get().getDpnId(), del.getVpnInstanceName(), interfaceName, false);
963                         }
964                     }
965 //                    Long ifCnt = 0L;
966 //                    //ifCnt = vpnInstOp.getVpnInterfaceCount();
967 //                    LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} Intf count {}",
968 //                            interfaceName, rd, vpnName, ifCnt);
969 //                    if ((ifCnt != null) && (ifCnt > 0)) {
970 //                        VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
971 //                                VpnUtil.getVpnInstanceOpDataIdentifier(rd),
972 //                                VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
973 //                    }
974                 }
975             } else {
976                 LOG.error("rd not retrievable as vpninstancetovpnid for vpn {} is absent, trying rd as ", vpnName, vpnName);
977             }
978             notifyTaskIfRequired(interfaceName);
979         }
980
981         private void notifyTaskIfRequired(String intfName) {
982             Runnable notifyTask = vpnIntfMap.remove(intfName);
983             if (notifyTask == null) {
984                 LOG.trace("VpnInterfaceOpListener update: No Notify Task queued for vpnInterface {}", intfName);
985                 return;
986             }
987             executorService.execute(notifyTask);
988         }
989
990         @Override
991         protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
992             final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
993             String interfaceName = key.getName();
994
995             if (original.getVpnInstanceName().equals(update.getVpnInstanceName())) {
996                 return;
997             }
998
999             //increment the vpn interface count in Vpn Instance Op Data
1000             //Long ifCnt = 0L;
1001             VpnInstanceOpDataEntry vpnInstOp = null;
1002 //            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
1003 //                    .vpn.id.VpnInstance>
1004 //                    updId = VpnUtil.getVpnInstanceToVpnIdIdentifier(update.getVpnInstanceName());
1005 //            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
1006 //                    .VpnInstance> updVpnInstance
1007 //                    = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, updId);
1008 //
1009 //            if (updVpnInstance.isPresent()) {
1010 //                String rd = null;
1011 //                rd = updVpnInstance.get().getVrfId();
1012 //
1013 //                vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
1014 //
1015 //                if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
1016 //                    ifCnt = vpnInstOp.getVpnInterfaceCount();
1017 //                }
1018 //
1019 //                LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in updated Vpn Op
1020 // Instance {}", interfaceName, rd, ifCnt);
1021 //
1022 //                VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1023 //                        VpnUtil.getVpnInstanceOpDataIdentifier(rd),
1024 //                        VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
1025 //            }
1026
1027             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
1028                     .vpn.id.VpnInstance>
1029                     origId = VpnUtil.getVpnInstanceToVpnIdIdentifier(original.getVpnInstanceName());
1030             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
1031                     .VpnInstance> origVpnInstance
1032                     = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, origId);
1033
1034             if (origVpnInstance.isPresent()) {
1035                 String rd = null;
1036                 rd = origVpnInstance.get().getVrfId();
1037
1038                 vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
1039                 LOG.trace("VpnInterfaceOpListener updated: interface name {} original rd {} original vpnName {}",
1040                         interfaceName, rd, original.getVpnInstanceName());
1041
1042                 if (vpnInstOp != null) {
1043                     Adjacency adjacency = original.getAugmentation(Adjacencies.class).getAdjacency().get(0);
1044                     Optional<Prefixes> prefixToInterface = Optional.absent();
1045                     prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
1046                             VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1047                                     VpnUtil.getIpPrefix(adjacency.getIpAddress())));
1048                     if (!prefixToInterface.isPresent()) {
1049                         prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
1050                                 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1051                                         VpnUtil.getIpPrefix(adjacency.getNextHopIp())));
1052                     }
1053                     if (prefixToInterface.isPresent()) {
1054 //                        VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
1055 //                                VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1056 //                                        prefixToInterface.get().getIpAddress()),
1057 //                                VpnUtil.DEFAULT_CALLBACK);
1058                         synchronized (interfaceName.intern()) {
1059                             updateDpnDbs(prefixToInterface.get().getDpnId(), original.getVpnInstanceName(), interfaceName, false);
1060                         }
1061                     }
1062                 }
1063             }
1064             notifyTaskIfRequired(interfaceName);
1065 //                if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
1066 //                    ifCnt = vpnInstOp.getVpnInterfaceCount();
1067 //                } else {
1068 //                    LOG.debug("VpnInterfaceOpListener update: Vpn interface count not recoverable from original, to handle update for rd {}", rd);
1069 //                    return;
1070 //                }
1071 //                LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in original Vpn Op Instance {}", interfaceName, rd, ifCnt);
1072 //
1073 //                if (ifCnt > 0) {
1074 //                    VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1075 //                            VpnUtil.getVpnInstanceOpDataIdentifier(rd),
1076 //                            VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
1077 //                }
1078 //            }
1079         }
1080
1081         @Override
1082         protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
1083             final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1084             String interfaceName = key.getName();
1085
1086             //increment the vpn interface count in Vpn Instance Op Data
1087 //            Long ifCnt = 0L;
1088 //            String rd = getRouteDistinguisher(add.getVpnInstanceName());
1089 //            if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName();
1090 //            VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
1091 //            if(vpnInstOp != null &&  vpnInstOp.getVpnInterfaceCount() != null) {
1092 //                ifCnt = vpnInstOp.getVpnInterfaceCount();
1093 //            }
1094 //
1095 //            LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}",
1096 //                    interfaceName, rd, ifCnt);
1097 //
1098 //            VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1099 //                    VpnUtil.getVpnInstanceOpDataIdentifier(rd),
1100 //                    VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
1101
1102         }
1103     }
1104
1105     protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
1106
1107         LOG.info("Tunnel event triggered {} for Dpn:{} ", action.name(), dpnId);
1108         InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
1109         InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
1110         Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
1111
1112         if (vpnInstances.isPresent()) {
1113             List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
1114             Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
1115             while (vpnInstIter.hasNext()) {
1116                 VpnInstance vpnInstance = vpnInstIter.next();
1117                 try {
1118                     VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
1119                     String rd = vpnConfig.getRouteDistinguisher();
1120                     if (rd == null || rd.isEmpty()) {
1121                         rd = vpnInstance.getVpnInstanceName();
1122                     }
1123                     InstanceIdentifier<VpnToDpnList> id =
1124                         VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
1125                     Optional<VpnToDpnList> dpnInVpn =
1126                         VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
1127                     if (dpnInVpn.isPresent()) {
1128                         // if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
1129                         //    fibManager.populateFibOnNewDpn(dpnId, VpnUtil
1130                         //        .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
1131                         // }
1132                         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
1133                             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
1134                             vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
1135                         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
1136                             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
1137                             InstanceIdentifier<VpnInterface> vpnIntfId =
1138                                 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
1139                             InstanceIdentifier<Adjacencies> path =
1140                                 vpnIntfId.augmentation(Adjacencies.class);
1141                             Optional<Adjacencies> adjacencies =
1142                                 VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
1143
1144                             if (adjacencies.isPresent()) {
1145                                 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
1146                                 Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
1147
1148                                 while (adjacencyIterator.hasNext()) {
1149                                     Adjacency adjacency = adjacencyIterator.next();
1150                                     try {
1151                                         if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
1152                                             //FIXME: TBD once odl-fib yang has nexthoplist and related changes follow
1153                                             //bgpManager.addPrefix(rd, adjacency.getIpAddress(), adjacency.getNextHopIp(), adjacency.getLabel().intValue());
1154
1155                                         }
1156                                         else if (action == UpdateRouteAction.WITHDRAW_ROUTE)
1157                                             bgpManager.deletePrefix(rd, adjacency.getIpAddress());
1158                                     } catch (Exception e) {
1159                                         LOG.error("Exception when updating prefix {} in vrf {} to BGP",
1160                                             adjacency.getIpAddress(), rd);
1161                                     }
1162                                 }
1163                             }
1164
1165                         }
1166                         // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
1167                         //    fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
1168                         // }
1169                     }
1170                 } catch (Exception e) {
1171                     LOG.error("updatePrefixesForDPN {} in vpn {} failed", dpnId, vpnInstance.getVpnInstanceName(), e);
1172                 }
1173             }
1174         }
1175     }
1176
1177         InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1178         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1179             .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1180             .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1181     }
1182
1183     InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1184         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1185             .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1186     }
1187
1188     protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
1189         BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
1190         if(dpId.equals(BigInteger.ZERO)) {
1191             LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
1192             return;
1193         }
1194         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1195
1196         Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1197                 .OPERATIONAL, routerDpnListIdentifier);
1198         RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1199         if (optionalRouterDpnList.isPresent()) {
1200             MDSALUtil.syncWrite(broker,  LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1201                     RouterInterfaces.class,  new RouterInterfacesKey(vpnInterfaceName)), routerInterface);
1202         } else {
1203             MDSALUtil.syncUpdate(broker,  LogicalDatastoreType.OPERATIONAL,
1204                     getRouterId(routerName),
1205                     new RouterDpnListBuilder().setRouterId(routerName).build());
1206             //VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
1207             DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1208             List<RouterInterfaces> routerInterfaces =  new ArrayList<>();
1209             routerInterfaces.add(routerInterface);
1210             MDSALUtil.syncWrite(broker,  LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier,
1211                     dpnVpnList.setRouterInterfaces(routerInterfaces).build());
1212         }
1213     }
1214
1215     protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
1216         BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
1217         if(dpId.equals(BigInteger.ZERO)) {
1218             LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1219             return;
1220         }
1221         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1222         Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1223                 .OPERATIONAL, routerDpnListIdentifier);
1224         if (optionalRouterDpnList.isPresent()) {
1225             List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1226             RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1227
1228             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1229                 if (routerInterfaces.isEmpty()) {
1230                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1231                 } else {
1232                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1233                             RouterInterfaces.class,
1234                             new RouterInterfacesKey(vpnInterfaceName)));
1235                 }
1236             }
1237         }
1238     }
1239         
1240         protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,BigInteger dpId) {
1241         if(dpId.equals(BigInteger.ZERO)) {
1242             LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1243             return;
1244         }
1245         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1246         Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1247                 .OPERATIONAL, routerDpnListIdentifier);
1248         if (optionalRouterDpnList.isPresent()) {
1249             List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1250             RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1251
1252             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1253                 if (routerInterfaces.isEmpty()) {
1254                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1255                 } else {
1256                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1257                             RouterInterfaces.class,
1258                             new RouterInterfacesKey(vpnInterfaceName)));
1259                 }
1260             }
1261         }
1262     }
1263
1264 }