Extra route fixes
[vpnservice.git] / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / vpnservice / 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.vpnservice;
9
10 import org.opendaylight.vpnservice.utilities.InterfaceUtils;
11
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.JdkFutureAdapters;
15
16 import org.opendaylight.controller.md.sal.binding.api.*;
17 import org.opendaylight.vpnservice.mdsalutil.*;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
41
42 import java.math.BigInteger;
43 import java.util.Collection;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.ArrayList;
47 import java.util.concurrent.*;
48
49 import com.google.common.base.Optional;
50
51 import org.opendaylight.bgpmanager.api.IBgpManager;
52 import org.opendaylight.fibmanager.api.IFibManager;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
55 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
56 import org.opendaylight.yangtools.concepts.ListenerRegistration;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
59 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
60 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
72 import org.opendaylight.yangtools.yang.common.RpcError;
73 import org.opendaylight.yangtools.yang.common.RpcResult;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
76
77 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
78     private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
79     private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration;
80     private ConcurrentMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
81     private ExecutorService executorService = Executors.newSingleThreadExecutor();
82     private final DataBroker broker;
83     private final IBgpManager bgpManager;
84     private IFibManager fibManager;
85     private IMdsalApiManager mdsalManager;
86     private OdlInterfaceRpcService interfaceManager;
87     private ItmRpcService itmProvider;
88     private IdManagerService idManager;
89     private OdlArputilService arpManager;
90     private InterfaceStateChangeListener interfaceListener;
91     private VpnInterfaceOpListener vpnInterfaceOpListener;
92     private ArpNotificationHandler arpNotificationHandler;
93     protected enum UpdateRouteAction {
94         ADVERTISE_ROUTE, WITHDRAW_ROUTE
95     }
96     /**
97      * Responsible for listening to data change related to VPN Interface
98      * Bind VPN Service on the interface and informs the BGP service
99      *
100      * @param db - dataBroker service reference
101      */
102     public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) {
103         super(VpnInterface.class);
104         broker = db;
105         this.bgpManager = bgpManager;
106         interfaceListener = new InterfaceStateChangeListener(db, this);
107         vpnInterfaceOpListener = new VpnInterfaceOpListener();
108         arpNotificationHandler = new ArpNotificationHandler(this, broker);
109         notificationService.registerNotificationListener(arpNotificationHandler);
110         registerListener(db);
111     }
112
113     public void setMdsalManager(IMdsalApiManager mdsalManager) {
114         this.mdsalManager = mdsalManager;
115     }
116
117     public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
118         this.interfaceManager = interfaceManager;
119         interfaceListener.setInterfaceManager(interfaceManager);
120     }
121
122     public void setITMProvider(ItmRpcService itmProvider) {
123         this.itmProvider = itmProvider;
124     }
125
126     public void setFibManager(IFibManager fibManager) {
127         this.fibManager = fibManager;
128     }
129
130     public void setIdManager(IdManagerService idManager) {
131         this.idManager = idManager;
132     }
133
134     public void setArpManager(OdlArputilService arpManager) {
135         this.arpManager = arpManager;
136     }
137
138     @Override
139     public void close() throws Exception {
140         if (listenerRegistration != null) {
141             try {
142                 listenerRegistration.close();
143                 opListenerRegistration.close();
144             } catch (final Exception e) {
145                 LOG.error("Error when cleaning up DataChangeListener.", e);
146             }
147             listenerRegistration = null;
148             opListenerRegistration = null;
149         }
150         LOG.info("VPN Interface Manager Closed");
151     }
152
153     private void registerListener(final DataBroker db) {
154         try {
155             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
156                     getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
157             opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
158                                                                    getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
159         } catch (final Exception e) {
160             LOG.error("VPN Service DataChange listener registration fail!", e);
161             throw new IllegalStateException("VPN Service registration Listener failed.", e);
162         }
163     }
164
165     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
166         return InstanceIdentifier.create(InterfacesState.class)
167             .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
168     }
169
170     @Override
171     protected void add(final InstanceIdentifier<VpnInterface> identifier,
172             final VpnInterface vpnInterface) {
173         LOG.trace("VPN Interface key: {} , value: {}", identifier, vpnInterface );
174         addInterface(identifier, vpnInterface);
175     }
176
177     private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
178                               final VpnInterface vpnInterface) {
179         LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
180         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
181         String interfaceName = key.getName();
182
183         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
184             InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
185         if (interfaceState != null) {
186             // Interface state is up
187             processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex());
188         } else {
189             LOG.trace("VPN interfaces are not yet operational.");
190         }
191     }
192
193     protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag) {
194
195         VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
196         if(vpnInterface == null) {
197             LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
198             return;
199         }
200         String vpnName = vpnInterface.getVpnInstanceName();
201         LOG.info("Binding vpn service to interface {} ", interfaceName);
202         long vpnId = VpnUtil.getVpnId(broker, vpnName);
203         if (vpnId == VpnConstants.INVALID_ID) {
204             LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
205             return;
206         }
207         synchronized (interfaceName.intern()) {
208             if (VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName()) != null) {
209                 LOG.trace("VPN Interface already provisioned , bailing out from here.");
210                 return;
211             }
212             bindService(dpId, vpnName, interfaceName, lPortTag);
213             updateDpnDbs(dpId, vpnName, interfaceName, true);
214             processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
215         }
216
217     }
218
219     private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
220         long vpnId = VpnUtil.getVpnId(broker, vpnName);
221         if (dpId == null) {
222             dpId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
223         }
224         if(!dpId.equals(BigInteger.ZERO)) {
225             if(add)
226                 updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
227             else
228                 removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
229         }
230
231     }
232
233     private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
234         int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
235         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
236
237         int instructionKey = 0;
238         List<Instruction> instructions = new ArrayList<Instruction>();
239
240         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
241         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
242
243         BoundServices
244             serviceInfo =
245             InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
246                                             VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
247                                             VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
248         VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
249                           InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
250         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
251                     vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
252
253     }
254
255     private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
256         String intfName = intf.getName();
257
258         synchronized (intfName) {
259             // Read NextHops
260             InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
261             Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
262
263             if (adjacencies.isPresent()) {
264                 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
265                 List<Adjacency> value = new ArrayList<>();
266
267                 // Get the rd of the vpn instance
268                 String rd = getRouteDistinguisher(intf.getVpnInstanceName());
269
270                 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
271                 if (nextHopIp == null){
272                     LOG.error("NextHop for interface {} is null", intfName);
273                 }
274
275                 LOG.trace("NextHops are {}", nextHops);
276                 for (Adjacency nextHop : nextHops) {
277                     String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
278                     long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
279                             .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
280                     String adjNextHop = nextHop.getNextHopIp();
281                     value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIp((adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp)
282                             .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
283                     if(nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
284                         VpnUtil.syncUpdate(
285                                 broker,
286                                 LogicalDatastoreType.OPERATIONAL,
287                                 VpnUtil.getPrefixToInterfaceIdentifier(
288                                         VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
289                                 VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
290                     } else {
291                         //Extra route adjacency
292                         VpnUtil.syncUpdate(
293                                 broker,
294                                 LogicalDatastoreType.OPERATIONAL,
295                                 VpnUtil.getVpnToExtrarouteIdentifier(
296                                         (rd != null) ? rd : intf.getVpnInstanceName(), nextHop.getIpAddress()),
297                                 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIp()));
298
299                     }
300                 }
301
302                 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
303                 VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
304                 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
305                 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
306                 for (Adjacency nextHop : aug.getAdjacency()) {
307                     long label = nextHop.getLabel();
308                     //String adjNextHop = nextHop.getNextHopIp();
309                     if (rd != null) {
310                         addPrefixToBGP(rd, nextHop.getIpAddress(),
311                                             nextHopIp, label);
312                     } else {
313                         // ### add FIB route directly
314                         addFibEntryToDS(intf.getVpnInstanceName(), nextHop.getIpAddress(),
315                                             nextHopIp, (int) label);
316                     }
317                 }
318             }
319         }
320     }
321
322     private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
323                              long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
324         List<MatchInfo> matches = new ArrayList<MatchInfo>();
325         BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
326         BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
327                 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
328
329         // Matching Arp reply flows
330         matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
331         matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
332                 metadata, metadataMask }));
333
334         matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
335
336         // Instruction to punt to controller
337         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
338         List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
339         actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
340         instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
341
342         // Install the flow entry in L3_INTERFACE_TABLE
343         String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
344                     NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
345         FlowEntity flowEntity;
346         flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
347                 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
348                 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
349
350         if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
351             LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
352             mdsalManager.installFlow(flowEntity);
353         } else {
354             LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
355             mdsalManager.removeFlow(flowEntity);
356         }
357     }
358
359     private String getRouteDistinguisher(String vpnName) {
360         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
361                                       .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
362         Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
363         String rd = "";
364         if(vpnInstance.isPresent()) {
365             VpnInstance instance = vpnInstance.get();
366             VpnAfConfig config = instance.getIpv4Family();
367             rd = config.getRouteDistinguisher();
368         }
369         return rd;
370     }
371
372     private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
373         String routeDistinguisher = getRouteDistinguisher(vpnName);
374         String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
375         InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
376         Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
377         org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
378             vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
379
380         if (dpnInVpn.isPresent()) {
381             VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
382                 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance
383                     .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
384                     new VpnInterfacesKey(intfName)), vpnInterface);
385         } else {
386             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
387                                     VpnUtil.getVpnInstanceOpDataIdentifier(rd),
388                                     VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId));
389             VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
390             List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
391                 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces =  new ArrayList<>();
392             vpnInterfaces.add(vpnInterface);
393             VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
394                               vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
395
396             /**
397              * FIXME: DC Gateway tunnel should be built dynamically
398             //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
399             //if tunnel to DC GW does not exist, create it
400             //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
401             String dcGW = bgpManager.getDCGwIP();
402             if(dcGW != null && !dcGW.isEmpty())
403             {
404                 LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
405                 itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
406             }*/
407             fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
408         }
409     }
410
411     private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
412         //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
413         String rd = VpnUtil.getVpnRd(broker, vpnName);
414         InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
415         Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
416         if (dpnInVpn.isPresent()) {
417             List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
418                 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
419             org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
420                     currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
421
422             if (vpnInterfaces.remove(currVpnInterface)) {
423                 if (vpnInterfaces.isEmpty()) {
424                     VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
425                     fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
426                 } else {
427                     VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
428                         org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
429                             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
430                             new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
431                 }
432             }
433         }
434     }
435
436     private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
437         try {
438             bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
439         } catch(Exception e) {
440             LOG.error("Add prefix failed", e);
441         }
442     }
443
444
445     private InstanceIdentifier<VpnInterface> getWildCardPath() {
446         return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
447     }
448
449     @Override
450     protected void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
451         LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
452         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
453         String interfaceName = key.getName();
454
455         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
456         Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
457         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
458             InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
459
460         if (existingVpnInterface.isPresent() && interfaceState != null) {
461             processVpnInterfaceDown(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex(), false);
462         } else {
463             LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
464         }
465     }
466
467     protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
468         VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
469         if(vpnInterface == null) {
470             LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
471             return;
472         }
473         String vpnName = vpnInterface.getVpnInstanceName();
474         InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
475
476         synchronized (interfaceName.intern()) {
477             removeAdjacenciesFromVpn(identifier, vpnInterface);
478             LOG.info("Unbinding vpn service from interface {} ", interfaceName);
479             unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown);
480
481             //wait till DCN for removal of vpn interface in operational DS arrives
482             Runnable notifyTask = new VpnNotifyTask();
483             synchronized (interfaceName.intern()) {
484                 vpnIntfMap.put(interfaceName, notifyTask);
485                 synchronized (notifyTask) {
486                     try {
487                         notifyTask.wait(VpnConstants.WAIT_TIME_IN_MILLISECONDS);
488                     } catch (InterruptedException e) {
489                     }
490                 }
491             }
492
493         }
494     }
495
496     private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
497         //Read NextHops
498         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
499         Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
500
501         String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
502         if (adjacencies.isPresent()) {
503             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
504
505             if (!nextHops.isEmpty()) {
506                 LOG.trace("NextHops are " + nextHops);
507                 for (Adjacency nextHop : nextHops) {
508                     VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
509                                       VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
510                     /*VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
511                                    VpnUtil.getPrefixToInterfaceIdentifier(
512                                        VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
513                                        nextHop.getIpAddress()),
514                                    VpnUtil.DEFAULT_CALLBACK);*/
515                     if (rd.equals(intf.getVpnInstanceName())) {
516                         //this is an internal vpn - the rd is assigned to the vpn instance name;
517                         //remove from FIB directly
518                         removeFibEntryFromDS(intf.getVpnInstanceName(), nextHop.getIpAddress());
519                     } else {
520                         removePrefixFromBGP(rd, nextHop.getIpAddress());
521                     }
522                 }
523             }
524         }
525     }
526
527
528     private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
529                                int lPortTag, boolean isInterfaceStateDown) {
530         if (!isInterfaceStateDown) {
531             VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
532                            InterfaceUtils.buildServiceId(vpnInterfaceName,
533                                                          VpnConstants.L3VPN_SERVICE_IDENTIFIER),
534                            VpnUtil.DEFAULT_CALLBACK);
535         }
536         long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
537         makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
538                     vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
539     }
540
541
542     private void removePrefixFromBGP(String rd, String prefix) {
543         try {
544             bgpManager.deletePrefix(rd, prefix);
545         } catch(Exception e) {
546             LOG.error("Delete prefix failed", e);
547         }
548     }
549
550     @Override
551     protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
552         if (LOG.isTraceEnabled()) {
553             LOG.trace("Updating VPN Interface : key " + identifier + ",  original value=" + original + ", update " +
554                     "value=" + update);
555         }
556         String oldVpnName = original.getVpnInstanceName();
557         String newVpnName = update.getVpnInstanceName();
558         List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
559         List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
560         if (oldAdjs == null) {
561             oldAdjs = new ArrayList<>();
562         }
563         if (newAdjs == null) {
564             newAdjs = new ArrayList<>();
565         }
566         //handles switching between <internal VPN - external VPN>
567         if (!oldVpnName.equals(newVpnName)) {
568             remove(identifier, original);
569             add(identifier, update);
570         }
571         //handle both addition and removal of adjacencies
572         //currently, new adjacency may be an extra route
573         if (!oldAdjs.equals(newAdjs)) {
574             for (Adjacency adj : newAdjs) {
575                 if (oldAdjs.contains(adj)) {
576                     oldAdjs.remove(adj);
577                 } else {
578                     // add new adjacency - right now only extra route will hit this path
579                     addNewAdjToVpnInterface(identifier, adj);
580                 }
581             }
582             for (Adjacency adj : oldAdjs) {
583                 delAdjFromVpnInterface(identifier, adj);
584             }
585         }
586     }
587
588     public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, String srcInterface){
589         SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
590                                                                     .setIpaddress(srcIP).setSrcIpAddress(targetIP).setMacaddress(srcMac).build();
591         final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
592         Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
593         Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
594             @Override
595             public void onFailure(Throwable error) {
596                 LOG.error("Error - {}", msgFormat, error);
597             }
598
599             @Override
600             public void onSuccess(RpcResult<Void> result) {
601                 if(!result.isSuccessful()) {
602                     LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
603                 } else {
604                     LOG.debug("Successful RPC Result - {}", msgFormat);
605                 }
606             }
607         });
608     }
609
610     private String getErrorText(Collection<RpcError> errors) {
611         StringBuilder errorText = new StringBuilder();
612         for(RpcError error : errors) {
613             errorText.append(",").append(error.getErrorType()).append("-")
614                      .append(error.getMessage());
615         }
616         return errorText.toString();
617     }
618
619     private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
620         return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
621     }
622
623
624
625     public synchronized void addFibEntryToDS(String rd, String prefix,
626             String nexthop, int label) {
627
628         VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
629                     setNextHopAddress(nexthop).setLabel((long)label).build();
630         LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label);
631
632         List<VrfEntry> vrfEntryList = new ArrayList<VrfEntry>();
633         vrfEntryList.add(vrfEntry);
634
635         InstanceIdentifierBuilder<VrfTables> idBuilder =
636                     InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
637         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
638
639         VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
640                     setVrfEntry(vrfEntryList).build();
641
642         VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
643     }
644
645     public synchronized void removeFibEntryFromDS(String rd, String prefix) {
646
647         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
648
649         InstanceIdentifierBuilder<VrfEntry> idBuilder =
650             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
651         InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
652         VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
653
654     }
655
656     public synchronized void removeVrfFromDS(String rd) {
657         LOG.debug("Removing vrf table for  rd {}", rd);
658
659         InstanceIdentifierBuilder<VrfTables> idBuilder =
660                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
661         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
662
663         VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
664
665     }
666
667     protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
668
669         Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
670
671         if (optVpnInterface.isPresent()) {
672             VpnInterface currVpnIntf = optVpnInterface.get();
673             String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
674             String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
675             InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
676             Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath);
677             long label =
678                     VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
679                             VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
680
681             List<Adjacency> adjacencies;
682             if (optAdjacencies.isPresent()) {
683                 adjacencies = optAdjacencies.get().getAdjacency();
684             } else {
685                 //This code will not be hit since VM adjacency will always be there
686                 adjacencies = new ArrayList<>();
687             }
688
689             adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIp(adj.getNextHopIp())
690                     .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
691
692             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
693             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
694
695             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
696             addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label, currVpnIntf.getName());
697
698         }
699
700     }
701
702     protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
703         Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
704
705         if (optVpnInterface.isPresent()) {
706             VpnInterface currVpnIntf = optVpnInterface.get();
707
708             InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
709             Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
710             if (optAdjacencies.isPresent()) {
711                 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
712
713                 if (!adjacencies.isEmpty()) {
714                     String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
715                     LOG.trace("Adjacencies are " + adjacencies);
716                     Iterator<Adjacency> adjIt = adjacencies.iterator();
717                     while (adjIt.hasNext()) {
718                         Adjacency adjElem = adjIt.next();
719                         if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
720                             VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
721                                     VpnUtil.getNextHopLabelKey(rd, adj.getIpAddress()));
722                             adjIt.remove();
723
724                             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
725                             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
726                                                                               currVpnIntf.getVpnInstanceName(),
727                                                                               aug);
728
729                             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
730
731                             delExtraRoute(adj.getIpAddress(), rd, currVpnIntf.getVpnInstanceName());
732                             break;
733                         }
734
735                     }
736                 }
737             }
738         }
739
740     }
741
742     protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label, String intfName) {
743
744         //add extra route to vpn mapping; advertise with nexthop as tunnel ip
745         VpnUtil.syncUpdate(
746             broker,
747             LogicalDatastoreType.OPERATIONAL,
748             VpnUtil.getVpnToExtrarouteIdentifier(
749                 (rd != null) ? rd : routerID, destination),
750             VpnUtil.getVpnToExtraroute(destination, nextHop));
751
752         if(intfName != null && !intfName.isEmpty()) {
753             BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
754             String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
755             if (nextHopIp == null && !nextHopIp.isEmpty()) {
756                 LOG.error("NextHop for interface {} is null. Adding extra route {} without nextHop", intfName,
757                         destination);
758             }
759             nextHop = nextHopIp;
760         }
761         if (rd != null) {
762             addPrefixToBGP(rd, destination, nextHop, label);
763         } else {
764             // ### add FIB route directly
765             addFibEntryToDS(routerID, destination, nextHop, label);
766         }
767     }
768
769     protected void delExtraRoute(String destination, String rd, String routerID) {
770         if (rd != null) {
771             removePrefixFromBGP(rd, destination);
772         } else {
773             // ### add FIB route directly
774             removeFibEntryFromDS(routerID, destination);
775         }
776     }
777
778     class VpnInterfaceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInterface> {
779
780         public VpnInterfaceOpListener() {
781             super(VpnInterface.class);
782         }
783
784         @Override
785         protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
786             final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
787             String interfaceName = key.getName();
788
789             //increment the vpn interface count in Vpn Instance Op Data
790             Long ifCnt = 0L;
791             String rd = getRouteDistinguisher(del.getVpnInstanceName());
792             if(rd == null || rd.isEmpty()) rd = del.getVpnInstanceName();
793             VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
794             if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
795                 ifCnt = vpnInstOp.getVpnInterfaceCount();
796             }
797
798             LOG.trace("VpnInterfaceOpListener remove: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
799
800             if(ifCnt != 0) {
801                 VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
802                         VpnUtil.getVpnInstanceOpDataIdentifier(rd),
803                         VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
804             }
805
806             // Vpn Interface removed => No more adjacencies from it.
807             // Hence clean up interface from vpn-dpn-interface list.
808             Adjacency adjacency = del.getAugmentation(Adjacencies.class).getAdjacency().get(0);
809             Optional<Prefixes> prefixToInterface = Optional.absent();
810             prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
811                          VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
812                                                 VpnUtil.getIpPrefix(adjacency.getIpAddress())));
813             if (!prefixToInterface.isPresent()) {
814                 prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
815                                                  VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
816                                                          VpnUtil.getIpPrefix(adjacency.getNextHopIp())));
817             }
818             if (prefixToInterface.isPresent()) {
819                 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
820                                VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
821                                                  prefixToInterface.get().getIpAddress()),
822                                VpnUtil.DEFAULT_CALLBACK);
823                 updateDpnDbs(prefixToInterface.get().getDpnId(), del.getVpnInstanceName(), interfaceName, false);
824             }
825             notifyTaskIfRequired(interfaceName);
826         }
827
828         private void notifyTaskIfRequired(String intfName) {
829             Runnable notifyTask = vpnIntfMap.remove(intfName);
830             if (notifyTask == null) {
831                 return;
832             }
833             executorService.execute(notifyTask);
834         }
835
836         @Override
837         protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
838         }
839
840         @Override
841         protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
842             final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
843             String interfaceName = key.getName();
844
845             //increment the vpn interface count in Vpn Instance Op Data
846             Long ifCnt = 0L;
847             String rd = getRouteDistinguisher(add.getVpnInstanceName());
848             if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName();
849             VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
850             if(vpnInstOp != null &&  vpnInstOp.getVpnInterfaceCount() != null) {
851                 ifCnt = vpnInstOp.getVpnInterfaceCount();
852             }
853
854             LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
855
856             VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
857                     VpnUtil.getVpnInstanceOpDataIdentifier(rd),
858                     VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
859
860
861         }
862     }
863
864     protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
865
866         LOG.info("Tunnel event triggered {} for Dpn:{} ", action.name(), dpnId);
867         InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
868         InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
869         Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
870
871         if (vpnInstances.isPresent()) {
872             List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
873             Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
874             while (vpnInstIter.hasNext()) {
875                 VpnInstance vpnInstance = vpnInstIter.next();
876                 try {
877                     VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
878                     String rd = vpnConfig.getRouteDistinguisher();
879                     if (rd == null || rd.isEmpty()) {
880                         rd = vpnInstance.getVpnInstanceName();
881                     }
882                     InstanceIdentifier<VpnToDpnList> id =
883                         VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
884                     Optional<VpnToDpnList> dpnInVpn =
885                         VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
886                     if (dpnInVpn.isPresent()) {
887                         // if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
888                         //    fibManager.populateFibOnNewDpn(dpnId, VpnUtil
889                         //        .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
890                         // }
891                         List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
892                             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
893                             vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
894                         for (org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
895                             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
896                             InstanceIdentifier<VpnInterface> vpnIntfId =
897                                 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
898                             InstanceIdentifier<Adjacencies> path =
899                                 vpnIntfId.augmentation(Adjacencies.class);
900                             Optional<Adjacencies> adjacencies =
901                                 VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
902
903                             if (adjacencies.isPresent()) {
904                                 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
905                                 Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
906
907                                 while (adjacencyIterator.hasNext()) {
908                                     Adjacency adjacency = adjacencyIterator.next();
909                                     try {
910                                         if (action == UpdateRouteAction.ADVERTISE_ROUTE)
911                                             bgpManager.addPrefix(rd, adjacency.getIpAddress(),
912                                                                  adjacency.getNextHopIp(),
913                                                                  adjacency.getLabel().intValue());
914                                         else if (action == UpdateRouteAction.WITHDRAW_ROUTE)
915                                             bgpManager.deletePrefix(rd, adjacency.getIpAddress());
916                                     } catch (Exception e) {
917                                         LOG.error("Exception when updating prefix {} in vrf {} to BGP",
918                                             adjacency.getIpAddress(), rd);
919                                     }
920                                 }
921                             }
922
923                         }
924                         // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
925                         //    fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
926                         // }
927                     }
928                 } catch (Exception e) {
929                     LOG.error("updatePrefixesForDPN {} in vpn {} failed", dpnId, vpnInstance.getVpnInstanceName(), e);
930                 }
931             }
932         }
933     }
934
935 }