BUG:5179 Fixing the jenkins Merge
[vpnservice.git] / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / vpnservice / elan / internal / ElanInterfaceManager.java
1 /*
2  * Copyright (c) 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.elan.internal;
9
10 import com.google.common.base.Optional;
11 import com.google.common.collect.Maps;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
14 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.vpnservice.elan.utils.ElanConstants;
17 import org.opendaylight.vpnservice.elan.utils.ElanUtils;
18 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
19 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType;
20 import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
21
22 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
23 import org.opendaylight.vpnservice.itm.globals.ITMConstants;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
30 import org.opendaylight.vpnservice.mdsalutil.*;
31 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanForwardingTables;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTable;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTableKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
57 import org.opendaylight.yangtools.concepts.ListenerRegistration;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62 import java.math.BigInteger;
63 import java.util.*;
64 import java.util.concurrent.ConcurrentHashMap;
65 import java.util.concurrent.ConcurrentLinkedQueue;
66
67
68 public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterface> implements AutoCloseable {
69
70     private static ElanInterfaceManager elanInterfaceManager = new ElanInterfaceManager();
71     private ListenerRegistration<DataChangeListener> elanInterfaceListenerRegistration;
72     private ListenerRegistration<DataChangeListener> itmInterfaceListenerRegistration;
73     private OdlInterfaceRpcService interfaceManagerRpcService;
74     private DataBroker broker;
75     private IMdsalApiManager mdsalManager;
76     private IInterfaceManager interfaceManager;
77     private IdManagerService idManager;
78
79     private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
80     private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
81             new ConcurrentHashMap<String, ConcurrentLinkedQueue<ElanInterface>> ();
82
83     private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class);
84
85     public ElanInterfaceManager() {
86         super(ElanInterface.class);
87     }
88
89     public static ElanInterfaceManager getElanInterfaceManager() {
90         return elanInterfaceManager;
91     }
92
93     public void setMdSalApiManager(IMdsalApiManager mdsalManager) {
94         this.mdsalManager = mdsalManager;
95     }
96
97     public void setInterfaceManagerRpcService(OdlInterfaceRpcService ifManager) {
98         this.interfaceManagerRpcService = ifManager;
99     }
100
101     public void setElanForwardingEntriesHandler(ElanForwardingEntriesHandler elanForwardingEntriesHandler) {
102         this.elanForwardingEntriesHandler = elanForwardingEntriesHandler;
103     }
104
105     public void setInterfaceManager(IInterfaceManager interfaceManager) {
106         this.interfaceManager = interfaceManager;
107     }
108
109     public void setDataBroker(DataBroker broker) {
110         this.broker = broker;
111     }
112
113     @Override
114     public void close() throws Exception {
115         if (elanInterfaceListenerRegistration != null) {
116             try {
117                 elanInterfaceListenerRegistration.close();
118             } catch (final Exception e) {
119                 logger.error("Error when cleaning up DataChangeListener.", e);
120             }
121             elanInterfaceListenerRegistration = null;
122         }
123     }
124
125     public void registerListener() {
126         try {
127             elanInterfaceListenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
128                     getElanInterfaceWildcardPath(), ElanInterfaceManager.this, DataChangeScope.SUBTREE);
129         } catch (final Exception e) {
130             logger.error("ELAN Interface DataChange listener registration failed !", e);
131             throw new IllegalStateException("ELAN Interface registration Listener failed.", e);
132         }
133     }
134
135     private InstanceIdentifier<?> getElanInterfaceWildcardPath() {
136         return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
137     }
138
139     public void setIdManager(IdManagerService idManager) {
140         this.idManager = idManager;
141     }
142
143     @Override
144     protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
145         String interfaceName =  del.getName();
146         ElanInstance elanInfo = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
147         removeElanInterface(elanInfo, interfaceName);
148     }
149
150     public void removeElanService(ElanInterface del, int vlanId) {
151         ElanInstance elanInstance = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
152         String interfaceName = del.getName();
153         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(interfaceName, InterfaceType.VLAN_INTERFACE);
154         removeElanInterface(elanInstance, interfaceInfo);
155         unbindService(elanInstance, interfaceName, vlanId);
156     }
157
158     public void removeElanInterface(ElanInstance elanInfo, String interfaceName) {
159         String elanName = elanInfo.getElanInstanceName();
160         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
161         if (interfaceInfo == null) {
162             ElanInterfaceMac elanInterfaceMac =  ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
163             if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
164                List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
165                 for(MacEntry macEntry : macEntries) {
166                     ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
167                 }
168             }
169             ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName));
170             Elan elanState = ElanUtils.getElanByName(elanName);
171             List<String> elanInterfaces = elanState.getElanInterfaces();
172             elanInterfaces.remove(interfaceName);
173             if(elanInterfaces.isEmpty()) {
174                 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
175                 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
176                 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
177                 ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanName));
178             } else {
179                 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
180                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
181             }
182             return;
183         }
184         removeElanInterface(elanInfo, interfaceInfo);
185         unbindService(elanInfo, interfaceName);
186     }
187
188     private void removeElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
189
190         BigInteger dpId = interfaceInfo.getDpId();
191         String elanName = elanInfo.getElanInstanceName();
192         String interfaceName = interfaceInfo.getInterfaceName();
193         Elan elanState = ElanUtils.getElanByName(elanName);
194         logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
195         InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
196         Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
197         if(existingElanInterface.isPresent()) {
198             List<MacEntry> macEntries = existingElanInterface.get().getMacEntry();
199             if(macEntries != null && !macEntries.isEmpty()) {
200                 for (MacEntry macEntry : macEntries) {
201                     logger.debug("removing the  mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
202                     elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(elanInfo, interfaceInfo, macEntry);
203                 }
204             }
205         }
206         /*
207          *This condition check is mainly to get DPN-ID in pre-provision deletion scenario after stopping CSS
208          */
209         if(dpId.equals(ElanConstants.INVALID_DPN)) {
210             ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName);
211             if(elanDpnInterfacesList != null && !elanDpnInterfacesList.getDpnInterfaces().isEmpty()) {
212                 List<DpnInterfaces> dpnIfList = elanDpnInterfacesList.getDpnInterfaces();
213                 for (DpnInterfaces dpnInterface : dpnIfList) {
214                     DpnInterfaces dpnIfLists = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpnInterface.getDpId());
215                     if (dpnIfLists.getInterfaces().contains(interfaceName)) {
216                         logger.debug("deleting the elanInterface from the ElanDpnInterface cache in pre-provision scenario of elan:{} dpn:{} interfaceName:{}", elanName, dpId, interfaceName);
217                         removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName);
218                         break;
219                     }
220                 }
221             }
222         } else {
223             removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName);
224         }
225
226         removeStaticELanFlows(elanInfo, interfaceInfo);
227         ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
228         List<String> elanInterfaces = elanState.getElanInterfaces();
229         elanInterfaces.remove(interfaceName);
230
231         if(elanInterfaces.isEmpty()) {
232             ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
233             ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnOperationDataPath(elanName));
234             ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
235             ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
236             //ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanName));
237         } else {
238             Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
239             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
240         }
241     }
242
243     private void removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName) {
244         DpnInterfaces dpnInterfaces =  ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
245         if(dpnInterfaces != null) {
246             List<String> interfaceLists = dpnInterfaces.getInterfaces();
247             interfaceLists.remove(interfaceName);
248             updateElanDpnInterfacesList(elanName, dpId, interfaceLists);
249         }
250     }
251
252     @Override
253     protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
254         // updating the static-Mac Entries for the existing elanInterface
255         String elanName = update.getElanInstanceName();
256         String interfaceName = update.getName();
257         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
258         List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
259         List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
260         if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
261             List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
262             if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
263                 existingClonedPhyAddress.addAll(0, existingPhysAddress);
264                 existingPhysAddress.removeAll(updatedPhysAddress);
265                 updatedPhysAddress.removeAll(existingClonedPhyAddress);
266                 // removing the PhyAddress which are not presented in the updated List
267                 for(PhysAddress physAddress: existingPhysAddress) {
268                     removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
269                 }
270             }
271             // Adding the new PhysAddress which are presented in the updated List
272             if(updatedPhysAddress.size() > 0) {
273                 for(PhysAddress physAddress: updatedPhysAddress) {
274                     InstanceIdentifier<MacEntry> macId =  getMacEntryOperationalDataPath(elanName, physAddress);
275                     Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
276                     if(existingMacEntry.isPresent()) {
277                         elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
278                     } else {
279                         elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress);
280                     }
281                 }
282             }
283         } else if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
284             for( PhysAddress physAddress : existingPhysAddress) {
285                 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
286             }
287         }
288     }
289
290     @Override
291     protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
292         String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
293         String interfaceName = elanInterfaceAdded.getName();
294         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
295         ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
296
297         if (elanInstance == null) {
298             elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInterfaceAdded.getDescription()).build();
299             //Add the ElanInstance in the Configuration data-store
300             ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstance);
301             elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
302         }
303
304
305         Long elanTag = elanInstance.getElanTag();
306         // If elan tag is not updated, then put the elan interface into unprocessed entry map and entry. Let entries
307         // in this map get processed during ELAN update DCN.
308         if (elanTag == null) {
309             ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
310             if (elanInterfaces == null) {
311                 elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
312             }
313             elanInterfaces.add(elanInterfaceAdded);
314             unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
315             return;
316         }
317         addElanInterface(elanInterfaceAdded, interfaceInfo, elanInstance);
318     }
319
320     void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
321         Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
322         if (elanInterfaces == null || elanInterfaces.isEmpty()) {
323             return;
324         }
325         for (ElanInterface elanInterface: elanInterfaces) {
326             String interfaceName = elanInterface.getName();
327             InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
328             addElanInterface(elanInterface, interfaceInfo, elanInstance);
329         }
330     }
331
332     void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
333         String interfaceName = elanInterface.getName();
334         String elanInstanceName = elanInterface.getElanInstanceName();
335         List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
336         Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
337         BigInteger dpId = null;
338         if(elanInfo == null) {
339             ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstance);
340         }
341         if(interfaceInfo != null) {
342             dpId = interfaceInfo.getDpId();
343         }
344         if(dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
345             InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
346             Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
347             if (!existingElanDpnInterfaces.isPresent()) {
348                 createElanInterfacesList(elanInstanceName, interfaceName, dpId);
349             } else {
350                 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
351                 elanInterfaces.add(interfaceName);
352                 updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces);
353             }
354         }
355
356         // add code to install Local/Remote BC group, unknow DMAC entry, terminating service table flow entry
357         // call bindservice of interfacemanager to create ingress table flow enty.
358         //Add interface to the ElanInterfaceForwardingEntires Container
359         createElanInterfaceTablesList(interfaceName);
360         createElanStateList(elanInstanceName, interfaceName);
361         if(interfaceInfo != null) {
362             installFlowsAndGroups(elanInstance, interfaceInfo);
363         }
364         // add the static mac addresses
365         if(staticMacAddresses != null) {
366             for (PhysAddress physAddress : staticMacAddresses) {
367                 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
368                 Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
369                 if (existingMacEntry.isPresent()) {
370                     elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
371                 } else {
372                     elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress);
373                 }
374                 if(interfaceInfo != null && isOperational(interfaceInfo)) {
375                     logger.debug("Installing Static Mac-Entry on the Elan Interface:{} with MacAddress:{}", interfaceInfo, physAddress.getValue());
376                     ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue());
377                 }
378             }
379         }
380     }
381
382     private Map<BigInteger, List<String>> readFePortsDbForElan(String elanName) {
383         ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName);
384         HashMap<BigInteger, List<String>> fePortsDb = Maps.newHashMap();
385         if (elanDpnInterfacesList == null) {
386             return fePortsDb;
387         }
388         List<DpnInterfaces> dpnInterfaces = elanDpnInterfacesList.getDpnInterfaces();
389         if (dpnInterfaces == null) {
390             return fePortsDb;
391         }
392         for (DpnInterfaces dpnInterface : dpnInterfaces) {
393             fePortsDb.put(dpnInterface.getDpId(), dpnInterface.getInterfaces());
394         }
395         return fePortsDb;
396     }
397
398     protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) {
399         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
400         InstanceIdentifier<MacEntry> macId =  getMacEntryOperationalDataPath(elanInstanceName, physAddress);
401         Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
402
403         if(!existingMacEntry.isPresent()) {
404             return;
405         }
406
407         MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build();
408         elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry);
409         elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress);
410     }
411
412
413     private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
414         return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
415                 new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
416     }
417
418     public void installFlowsAndGroups(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
419         if (isOperational(interfaceInfo)) {
420
421             // LocalBroadcast Group creation with elan-Interfaces
422             setupElanBroadcastGroups(elanInfo, interfaceInfo);
423
424             setupLocalBroadcastGroups(elanInfo, interfaceInfo);
425             //Terminating Service , UnknownDMAC Table.
426             setupTerminateServiceTable(elanInfo, interfaceInfo);
427             setupUnknownDMacTable(elanInfo, interfaceInfo);
428             setupFilterEqualsTable(elanInfo, interfaceInfo);
429             // bind the Elan service to the Interface
430             bindService(elanInfo, interfaceInfo.getInterfaceName());
431
432             //update the remote-DPNs remoteBC group entry with Tunnels
433             setElanBCGrouponOtherDpns(elanInfo, interfaceInfo);
434         }
435     }
436
437     public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
438         int ifTag = interfaceInfo.getInterfaceTag();
439         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
440                 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
441
442         mdsalManager.installFlow(interfaceInfo.getDpId(), flow);
443
444         Flow flowEntry = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
445                 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
446                 getInstructionsDrop());
447
448         mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntry);
449     }
450
451     public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
452         int ifTag = interfaceInfo.getInterfaceTag();
453         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
454                 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
455
456         mdsalManager.removeFlow(interfaceInfo.getDpId(), flow);
457
458         Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
459                 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
460                 getInstructionsDrop());
461
462         mdsalManager.removeFlow(interfaceInfo.getDpId(), flowEntity);
463     }
464
465     private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
466                                                      int bucketKeyStart, InterfaceInfo interfaceInfo) {
467         BigInteger dpnId = interfaceInfo.getDpId();
468         int elanTag = elanInfo.getElanTag().intValue();
469         int bucketId = bucketKeyStart;
470         List<Bucket> listBuckets = new ArrayList<Bucket>();
471         ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
472         if(elanDpns != null) {
473             List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
474             for(DpnInterfaces dpnInterface : dpnInterfaceses) {
475                if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
476                    try {
477                        List<Action> listAction = ElanUtils.getItmEgressAction(dpnId, dpnInterface.getDpId(), (int) elanTag);
478                        listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
479                        bucketId++;
480                    } catch (Exception ex) {
481                        logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
482                    }
483                }
484             }
485         }
486         return listBuckets;
487     }
488
489     private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo,
490                                                          InterfaceInfo interfaceInfo, int bucketId) {
491         BigInteger dpnId = interfaceInfo.getDpId();
492         int elanTag = elanInfo.getElanTag().intValue();
493         List<Bucket> listBucketInfo = new ArrayList<Bucket>();
494         ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
495         if(elanDpns != null) {
496             List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
497             for(DpnInterfaces dpnInterface : dpnInterfaceses) {
498                 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
499                     try {
500                         List<Action> listActionInfo = ElanUtils.getItmEgressAction(dpnId, dpnInterface.getDpId(), (int) elanTag);
501                         listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL));
502                         bucketId++;
503                     } catch (Exception ex) {
504                         logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
505                     }
506                 }
507             }
508         }
509         return listBucketInfo;
510     }
511
512     private void setElanBCGrouponOtherDpns(ElanInstance elanInfo,
513                                            InterfaceInfo interfaceInfo) {
514         BigInteger dpnId = interfaceInfo.getDpId();
515         int elanTag = elanInfo.getElanTag().intValue();
516         long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
517         List<Bucket> listBucket = new ArrayList<Bucket>();
518         int bucketId = 0;
519         ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
520         if(elanDpns != null) {
521             List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
522             for(DpnInterfaces dpnInterface : dpnInterfaceses) {
523               List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
524                 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpnId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
525                     for(String ifName : dpnInterface.getInterfaces()) {
526                         // In case if there is a InterfacePort in the cache which is not in
527                         // operational state, skip processing it
528                         InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
529                         if (!isOperational(ifInfo)) {
530                             continue;
531                         }
532
533                         listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
534                         bucketId++;
535                     }
536                     remoteListBucketInfo.addAll(listBucket);
537                     for(DpnInterfaces otherFes : dpnInterfaceses) {
538                         if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
539                                 && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
540                             try {
541                                 List<Action> remoteListActionInfo = ElanUtils.getItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), (int) elanTag);
542                                 remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP));
543                                 bucketId++;
544                             } catch (Exception ex) {
545                                 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() );
546                                 return;
547                             }
548                         }
549                     }
550                     if(remoteListBucketInfo.size() == 0) {
551                         logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId());
552                         continue;
553                     }
554                     Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo));
555                     mdsalManager.syncInstallGroup(dpnInterface.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
556                 }
557             }
558         }
559     }
560
561     private void updateRemoteBCGrouponDpnTunnelEvent(ElanInstance elanInfo,
562                                                InterfaceInfo interfaceInfo, BigInteger dstDpId) {
563         int elanTag = elanInfo.getElanTag().intValue();
564         long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
565         List<DpnInterfaces> elanDpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
566         if(elanDpns != null) {
567             for(DpnInterfaces dpnInterface : elanDpns) {
568                 int bucketId = 0;
569                 List<Bucket> remoteListBucket = new ArrayList<Bucket>();
570                 if(ElanUtils.isDpnPresent(dstDpId) && dpnInterface.getDpId().equals(dstDpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
571                     try {
572                         List<Action> remoteListActionInfo = ElanUtils.getItmEgressAction(interfaceInfo.getDpId(), dstDpId, (int) elanTag);
573                         remoteListBucket.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
574                         bucketId++;
575                     } catch (Exception ex) {
576                         logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), dstDpId);
577                         return;
578                     }
579                     List<Action> remoteListActionInfo = new ArrayList<Action>();
580                     remoteListActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}).buildAction());
581                     remoteListBucket.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
582                     Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucket));
583                     mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
584                     break;
585                 }
586             }
587         }
588     }
589
590
591     /**
592      * Returns the bucket info with the given interface as the only bucket.
593      */
594     private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
595         return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
596     }
597
598     private List<MatchInfo> getMatchesForElanTag(Long elanTag) {
599         List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
600         // Matching metadata
601         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
602                 ElanUtils.getElanMetadataLabel(elanTag),
603                 MetaDataUtil.METADATA_MASK_SERVICE }));
604         return mkMatches;
605     }
606
607     private List<Instruction> getInstructionsForOutGroup(
608             long groupId) {
609         List<Instruction> mkInstructions = new ArrayList<Instruction>();
610         List <Action> actions = new ArrayList <Action> ();
611         actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction());
612         mkInstructions.add(ElanUtils.getWriteActionInstruction(actions));
613         return mkInstructions;
614     }
615
616     public void removeFlowsAndGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
617         removeStaticELanFlows(elanInfo, interfaceInfo);
618         unbindService(elanInfo, interfaceInfo.getInterfaceName());
619     }
620
621     public void installMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
622         String interfaceName = interfaceInfo.getInterfaceName();
623         BigInteger currentDpn = interfaceInfo.getDpId();
624         ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
625         if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
626             List<MacEntry> macEntries =  elanInterfaceMac.getMacEntry();
627             for(MacEntry macEntry : macEntries) {
628                 PhysAddress physAddress = macEntry.getMacAddress();
629                 ElanUtils.setupMacFlows(elanInfo, interfaceInfo, macEntry.isIsStaticAddress() ? ElanConstants.STATIC_MAC_TIMEOUT : elanInfo.getMacTimeout(), physAddress.getValue());
630             }
631             //Programming the remoteDMACFlows
632             ElanDpnInterfacesList elanDpnInterfacesList =  ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
633             List<DpnInterfaces> dpnInterfaceLists =  elanDpnInterfacesList.getDpnInterfaces();
634             for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
635                 if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
636                     continue;
637                 }
638                 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
639                 for(String remoteIf : remoteElanInterfaces) {
640                     ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
641                     InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
642                     if(elanIfMac == null) {
643                         continue;
644                     }
645                     List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
646                     if(remoteMacEntries != null) {
647                         for (MacEntry macEntry : remoteMacEntries) {
648                             PhysAddress physAddress = macEntry.getMacAddress();
649                             ElanUtils.setupRemoteDmacFlow(currentDpn, remoteInterface.getDpId(), remoteInterface.getInterfaceTag(), elanInfo.getElanTag(), physAddress.getValue(), elanInfo.getElanInstanceName());
650                         }
651                     }
652                 }
653             }
654         }
655     }
656
657     // Install DMAC entry on dst DPN
658     public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
659         String interfaceName = interfaceInfo.getInterfaceName();
660         ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
661         if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
662             List<MacEntry> macEntries =  elanInterfaceMac.getMacEntry();
663             for(MacEntry macEntry : macEntries) {
664                 PhysAddress physAddress = macEntry.getMacAddress();
665                 ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue());
666             }
667         }
668     }
669
670     public void removeMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
671         ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceInfo.getInterfaceName());
672         if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
673             List<MacEntry> macEntries =  elanInterfaceMac.getMacEntry();
674             for(MacEntry macEntry : macEntries) {
675                 ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
676             }
677         }
678     }
679
680     public void setupElanBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
681         List<Bucket> listBucket = new ArrayList<Bucket>();
682         int bucketId = 0;
683         BigInteger dpnId = interfaceInfo.getDpId();
684         long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
685
686         DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
687         for(String ifName : dpnInterfaces.getInterfaces()) {
688             // In case if there is a InterfacePort in the cache which is not in
689             // operational state, skip processing it
690             InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
691             if (!isOperational(ifInfo)) {
692                 continue;
693             }
694
695             listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
696             bucketId++;
697         }
698         List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, interfaceInfo, bucketId);
699         listBucket.addAll(listBucketInfoRemote);
700
701         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
702         logger.trace("installing the localBroadCast Group:{}", group);
703         mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
704     }
705
706     public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
707         List<Bucket> listBucket = new ArrayList<Bucket>();
708         int bucketId = 0;
709         BigInteger dpnId = interfaceInfo.getDpId();
710         long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
711
712         DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
713         for(String ifName : dpnInterfaces.getInterfaces()) {
714             // In case if there is a InterfacePort in the cache which is not in
715             // operational state, skip processing it
716             InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
717             if (!isOperational(ifInfo)) {
718                 continue;
719             }
720
721             listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
722             bucketId++;
723         }
724
725         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
726         logger.trace("installing the localBroadCast Group:{}", group);
727         mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
728     }
729
730     public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
731         BigInteger dpnId = interfaceInfo.getDpId();
732         long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
733         List<Bucket> listBuckets = new ArrayList<>();
734         int bucketId = 0;
735         listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
736         //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo));
737         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
738         logger.trace("deleted the localBroadCast Group:{}", group);
739         mdsalManager.syncRemoveGroup(dpnId, group);
740     }
741
742     public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
743         int bucketId = 0;
744         List<Bucket> listBuckets = new ArrayList<>();
745         listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
746         bucketId++;
747         listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo));
748         BigInteger dpnId = interfaceInfo.getDpId();
749         long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
750         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
751         logger.trace("deleting the remoteBroadCast group:{}", group);
752         mdsalManager.syncRemoveGroup(dpnId, group);
753     }
754
755     public void setupTerminateServiceTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
756         long elanTag = elanInfo.getElanTag();
757         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag),
758                 5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0,  0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
759                 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
760
761         mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
762     }
763
764     public void setupUnknownDMacTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
765         long elanTag = elanInfo.getElanTag();
766         Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag),
767                 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag),
768                 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
769
770         mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
771     }
772
773     private void removeStaticELanFlows(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
774         BigInteger dpId = interfaceInfo.getDpId();
775         long elanTag = elanInfo.getElanTag();
776         /*
777          * If there are not elan ports, remove the unknown smac and default dmac
778          * flows
779          */
780         DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpId);
781         if(dpnInterfaces == null) {
782             return;
783         }
784         List <String> elanInterfaces = dpnInterfaces.getInterfaces();
785         if (elanInterfaces == null || elanInterfaces.isEmpty()) {
786
787             logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
788             removeDefaultTermFlow(dpId, elanInfo.getElanTag());
789             removeUnknownDmacFlow(dpId, elanInfo);
790             removeElanBroadcastGroup(elanInfo, interfaceInfo);
791             removeLocalBroadcastGroup(elanInfo, interfaceInfo);
792             removeFilterEqualsTable(elanInfo, interfaceInfo);
793         } else {
794             setupElanBroadcastGroups(elanInfo, interfaceInfo);
795             removeFilterEqualsTable(elanInfo, interfaceInfo);
796         }
797     }
798
799     private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo) {
800         Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
801         mdsalManager.removeFlow(dpId, flow);
802     }
803
804     private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
805         ElanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
806     }
807
808     private void bindService(ElanInstance elanInfo, String interfaceName) {
809        // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName));
810
811         int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
812         int instructionKey = 0;
813         List<Instruction> instructions = new ArrayList<Instruction>();
814         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanInfo.getElanTag()), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
815         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey));
816         BoundServices
817                 serviceInfo =
818                 ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName),
819                         ElanConstants.ELAN_SERVICE_INDEX, priority,
820                         ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
821         ElanUtils.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
822                 ElanUtils.buildServiceId(interfaceName, ElanConstants.ELAN_SERVICE_INDEX), serviceInfo);
823     }
824
825     private void unbindService(ElanInstance elanInfo, String interfaceName) {
826         ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
827                 ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
828                 ElanUtils.DEFAULT_CALLBACK);
829     }
830
831     private void unbindService(ElanInstance elanInfo, String interfaceName, int vlanId) {
832         ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
833                 ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
834                 ElanUtils.DEFAULT_CALLBACK);
835     }
836
837     private Flow getUnknownDmacFlowEntity(BigInteger dpId, ElanInstance elanInfo) {
838         long elanTag = elanInfo.getElanTag();
839         List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
840         // Matching metadata
841         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
842                 ElanUtils.getElanMetadataLabel(elanTag),
843                 MetaDataUtil.METADATA_MASK_SERVICE }));
844
845         List<Instruction> mkInstructions = new ArrayList<Instruction>();
846         List <Action> actionsInfos = new ArrayList <Action> ();
847         actionsInfos.add(new ActionInfo(ActionType.group, new String[]{Long.toString(ElanUtils.getElanRemoteBCGID(elanTag))}, 0).buildAction());
848         mkInstructions.add(ElanUtils.getWriteActionInstruction(actionsInfos));
849
850         Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag),
851                 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
852                 mkMatches, mkInstructions);
853         return flow;
854     }
855
856     private String getFlowRef(long tableId, long elanTag) {
857         return new StringBuffer().append(tableId).append(elanTag).toString();
858     }
859
860     private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
861         List<Action> listAction = new ArrayList<Action>();
862         int actionKey = 0;
863         listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction());
864         actionKey++;
865         listAction.add((new ActionInfo(ActionType.nx_resubmit, new BigInteger[] {BigInteger.valueOf(55)}, actionKey)).buildAction());
866         return listAction;
867     }
868
869     private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames) {
870         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
871                 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
872         MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
873                 dpnInterface);
874     }
875
876     private List<String> createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) {
877         List<String> interfaceNames = new ArrayList<String>();
878         interfaceNames.add(interfaceName);
879         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
880                 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
881         MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
882                 dpnInterface);
883         return interfaceNames;
884     }
885
886     private void createElanInterfaceTablesList(String interfaceName) {
887         InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
888         Optional<ElanInterfaceMac> interfaceMacTables = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
889         // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
890         if(!interfaceMacTables.isPresent()) {
891             ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName).setKey(new ElanInterfaceMacKey(interfaceName)).build();
892             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName),
893                     elanInterfaceMacTable);
894         }
895     }
896
897     private void createElanStateList(String elanInstanceName, String interfaceName) {
898         InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
899         Optional<Elan> elanInterfaceLists = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInstance);
900         // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
901         if(elanInterfaceLists.isPresent()) {
902             List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
903             if(interfaceLists == null) {
904                 interfaceLists = new ArrayList<>();
905             }
906             interfaceLists.add(interfaceName);
907             Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists).setKey(new ElanKey(elanInstanceName)).build();
908             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState);
909         }
910     }
911
912     private boolean isOperational(InterfaceInfo interfaceInfo) {
913         return ((interfaceInfo.getOpState() == InterfaceInfo.InterfaceOpState.UP) && (interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED));
914     }
915
916     protected void updatedIfPrimaryAttributeChanged(ElanInterface elanInterface, boolean isUpdated) {
917         String interfaceName = elanInterface.getName();
918         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
919         BigInteger dpId = interfaceInfo.getDpId();
920         InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
921         Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
922         ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInterface.getElanInstanceName());
923
924         if(!existingElanInterface.isPresent()) {
925             return;
926         }
927
928         List<MacEntry> macEntries = existingElanInterface.get().getMacEntry();
929         if(macEntries != null && !macEntries.isEmpty()) {
930             for (MacEntry macEntry : macEntries) {
931                 if(isUpdated) {
932                     ElanUtils.setupMacFlows(elanInfo, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, macEntry.getMacAddress().getValue());
933                 } else {
934                     ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
935                 }
936             }
937         }
938
939         InstanceIdentifier<DpnInterfaces> dpnInterfaceId = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInterface.getElanInstanceName(), interfaceInfo.getDpId());
940         Optional<DpnInterfaces> dpnInterfaces =  ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId);
941         List<String> interfaceLists = dpnInterfaces.get().getInterfaces();
942
943         if(isUpdated) {
944             interfaceLists.add(elanInterface.getName());
945         } else {
946             interfaceLists.remove(elanInterface.getName());
947         }
948
949         DpnInterfaces  updateDpnInterfaces = new DpnInterfacesBuilder().setInterfaces(interfaceLists).setDpId(dpId).setKey(new DpnInterfacesKey(dpId)).build();
950         MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId, updateDpnInterfaces);
951
952         if(isUpdated) {
953             installFlowsAndGroups(elanInfo, interfaceInfo);
954         } else {
955             removeStaticELanFlows(elanInfo, interfaceInfo);
956             unbindService(elanInfo, interfaceName);
957         }
958     }
959
960     public void handleTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
961         ElanDpnInterfaces dpnInterfaceLists =  ElanUtils.getElanDpnInterfacesList();
962         Set<String> elanInstancesMap = new HashSet<>();
963         if(dpnInterfaceLists == null) {
964             return;
965         }
966         List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
967         for(ElanDpnInterfacesList elanDpns: elanDpnIf) {
968             int cnt = 0;
969             String elanName = elanDpns.getElanInstanceName();
970             List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
971             if(dpnInterfaces == null) {
972                continue;
973             }
974             for (DpnInterfaces dpnIf : dpnInterfaces) {
975                if(dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
976                    cnt++;
977                 }
978             }
979             if(cnt == 2) {
980                 logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
981                 DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, srcDpId);
982                 Set<String> interfaceLists = new HashSet<>();
983                 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
984                 interfaceLists.addAll(dpnInterface.getInterfaces());
985                 for(String ifName : interfaceLists) {
986                     InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
987                     if (isOperational(interfaceInfo)) {
988                         if (interfaceInfo.getDpId().equals(srcDpId) && !elanInstancesMap.contains(elanDpns.getElanInstanceName())) {
989                             elanInstancesMap.add(elanDpns.getElanInstanceName());
990                             elanInterfaceManager.updateRemoteBCGrouponDpnTunnelEvent(elanInfo, interfaceInfo, dstDpId);
991                         }
992                         elanInterfaceManager.installDMacAddressTables(elanInfo, interfaceInfo, dstDpId);
993                     }
994                 }
995             }
996
997         }
998     }
999
1000     public void handleInterfaceUpated(InterfaceInfo interfaceInfo, ElanInstance elanInstance, boolean isStateUp) {
1001         BigInteger dpId = interfaceInfo.getDpId();
1002         String elanName = elanInstance.getElanInstanceName();
1003         String ifName = interfaceInfo.getInterfaceName();
1004         logger.trace("Handling interface update event for interface with info {} , state {}", interfaceInfo, isStateUp);
1005         if(isStateUp) {
1006
1007             DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1008             if(dpnInterfaces == null) {
1009                 createElanInterfacesList(elanName, interfaceInfo.getInterfaceName(), dpId);
1010             } else {
1011               List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
1012                 dpnElanInterfaces.add(interfaceInfo.getInterfaceName());
1013                 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1014                         .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
1015                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
1016             }
1017
1018             logger.trace("ElanInterface Service is installed for interface:{}", ifName);
1019             elanInterfaceManager.installFlowsAndGroups(elanInstance, interfaceInfo);
1020             elanInterfaceManager.installMacAddressTables(elanInstance, interfaceInfo);
1021         } else {
1022
1023             DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1024             if(dpnInterfaces != null) {
1025                 List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
1026                 dpnElanInterfaces.remove(interfaceInfo.getInterfaceName());
1027                 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1028                         .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
1029                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
1030             }
1031             logger.trace("ElanInterface Service is removed for the interface:{}", ifName);
1032             elanInterfaceManager.removeMacAddressTables(elanInstance, interfaceInfo);
1033             elanInterfaceManager.removeFlowsAndGroups(elanInstance, interfaceInfo);
1034         }
1035     }
1036
1037     private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
1038         List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1039         // Matching metadata
1040         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1041                 MetaDataUtil.getLportTagMetaData(LportTag),
1042                 MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1043         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(LportTag)}));
1044         return mkMatches;
1045     }
1046
1047
1048     private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
1049         List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1050         // Matching metadata
1051         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
1052                 BigInteger.valueOf(LportTag)}));
1053         return mkMatches;
1054
1055
1056     }
1057
1058     private List<Instruction> getInstructionsDrop() {
1059         List<Instruction> mkInstructions = new ArrayList<Instruction>();
1060         List <Action> actionsInfos = new ArrayList <Action> ();
1061         actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{}).buildAction());
1062         mkInstructions.add(ElanUtils.getWriteActionInstruction(actionsInfos));
1063         return mkInstructions;
1064     }
1065
1066 }