Merge "Refactor aclservice to for all the acl types to inherit the same abstract...
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / netvirt / 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.netvirt.elan.internal;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Queue;
20 import java.util.Set;
21 import java.util.concurrent.ConcurrentHashMap;
22 import java.util.concurrent.ConcurrentLinkedQueue;
23 import java.util.concurrent.ConcurrentMap;
24 import org.apache.commons.lang3.StringUtils;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
29 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
30 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
31 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
32 import org.opendaylight.genius.itm.globals.ITMConstants;
33 import org.opendaylight.genius.mdsalutil.ActionInfo;
34 import org.opendaylight.genius.mdsalutil.ActionType;
35 import org.opendaylight.genius.mdsalutil.FlowEntity;
36 import org.opendaylight.genius.mdsalutil.InstructionInfo;
37 import org.opendaylight.genius.mdsalutil.InstructionType;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.genius.mdsalutil.MatchFieldType;
40 import org.opendaylight.genius.mdsalutil.MatchInfo;
41 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
42 import org.opendaylight.genius.mdsalutil.NwConstants;
43 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
44 import org.opendaylight.genius.utils.ServiceIndex;
45 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
46 import org.opendaylight.netvirt.elan.utils.ElanConstants;
47 import org.opendaylight.netvirt.elan.utils.ElanForwardingEntriesHandler;
48 import org.opendaylight.netvirt.elan.utils.ElanUtils;
49 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
50 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTableKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
90 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
91 import org.slf4j.Logger;
92 import org.slf4j.LoggerFactory;
93
94 /**
95  * Class in charge of handling creations, modifications and removals of
96  * ElanInterfaces.
97  *
98  * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
99  *
100  */
101 @SuppressWarnings("deprecation")
102 public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface, ElanInterfaceManager>
103         implements AutoCloseable {
104
105     private final DataBroker broker;
106     private final IMdsalApiManager mdsalManager;
107     private final IInterfaceManager interfaceManager;
108     private final IdManagerService idManager;
109     private final ElanForwardingEntriesHandler elanForwardingEntriesHandler;
110     private ElanL2GatewayUtils elanL2GatewayUtils;
111     private ElanUtils elanUtils;
112
113     private static final long WAIT_TIME_FOR_SYNC_INSTALL = Long.getLong("wait.time.sync.install", 300L);
114
115     private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces = new ConcurrentHashMap<>();
116
117     private static final Logger LOG = LoggerFactory.getLogger(ElanInterfaceManager.class);
118
119     public ElanInterfaceManager(final DataBroker dataBroker,
120                                 final IdManagerService managerService,
121                                 final IMdsalApiManager mdsalApiManager,
122                                 IInterfaceManager interfaceManager,
123                                 final ElanForwardingEntriesHandler elanForwardingEntriesHandler) {
124         super(ElanInterface.class, ElanInterfaceManager.class);
125         this.broker = dataBroker;
126         this.idManager = managerService;
127         this.mdsalManager = mdsalApiManager;
128         this.interfaceManager = interfaceManager;
129         this.elanForwardingEntriesHandler = elanForwardingEntriesHandler;
130     }
131
132     public void setElanUtils(ElanUtils elanUtils) {
133         this.elanUtils = elanUtils;
134         this.elanL2GatewayUtils = elanUtils.getElanL2GatewayUtils();
135         this.elanForwardingEntriesHandler.setElanUtils(elanUtils);
136     }
137
138     public void init() {
139         registerListener(LogicalDatastoreType.CONFIGURATION, broker);
140     }
141
142     @Override
143     protected InstanceIdentifier<ElanInterface> getWildCardPath() {
144         return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
145     }
146
147     @Override
148     protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
149         String interfaceName = del.getName();
150         ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, del.getElanInstanceName());
151         /*
152          * Handling in case the elan instance is deleted.If the Elan instance is
153          * deleted, there is no need to explicitly delete the elan interfaces
154          */
155         if (elanInfo == null) {
156             return;
157         }
158         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
159         String elanInstanceName = elanInfo.getElanInstanceName();
160         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
161         InterfaceRemoveWorkerOnElan configWorker = new InterfaceRemoveWorkerOnElan(elanInstanceName, elanInfo,
162                 interfaceName, interfaceInfo, false, this);
163         coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
164     }
165
166     public void removeElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo, String interfaceName,
167             InterfaceInfo interfaceInfo, boolean isInterfaceStateRemoved) {
168         String elanName = elanInfo.getElanInstanceName();
169         boolean isLastElanInterface = false;
170         long elanTag = elanInfo.getElanTag();
171         WriteTransaction tx = broker.newWriteOnlyTransaction();
172         WriteTransaction deleteFlowGroupTx = broker.newWriteOnlyTransaction();
173         Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, tx);
174         if (elanState == null) {
175             return;
176         }
177         List<String> elanInterfaces = elanState.getElanInterfaces();
178         if (elanInterfaces.size() == 0) {
179             isLastElanInterface = true;
180         }
181         if (interfaceInfo != null) {
182             BigInteger dpId = interfaceInfo.getDpId();
183             DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName,
184                     elanTag, tx);
185             /*
186              * If there are not elan ports, remove the unknown dmac, terminating
187              * service table flows, remote/local bc group
188              */
189             if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
190                     || dpnInterfaces.getInterfaces().isEmpty()) {
191                 // No more Elan Interfaces in this DPN
192                 LOG.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
193                 removeDefaultTermFlow(dpId, elanInfo.getElanTag());
194                 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, elanInfo.getElanTag());
195                 removeEtreeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx);
196                 removeElanBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
197                 removeLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
198                 removeEtreeBroadcastGrups(elanInfo, interfaceInfo, deleteFlowGroupTx);
199                 if (ElanUtils.isVxlan(elanInfo)) {
200                     unsetExternalTunnelTable(dpId, elanInfo);
201                 }
202             } else {
203                 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
204             }
205         }
206         futures.add(ElanUtils.waitForTransactionToComplete(tx));
207         futures.add(ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx));
208         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
209         InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(
210                 interfaceName, elanInfo, interfaceInfo, isInterfaceStateRemoved, this, isLastElanInterface);
211         coordinator.enqueueJob(interfaceName, removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES);
212     }
213
214     private void removeEtreeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo,
215             WriteTransaction deleteFlowGroupTx) {
216         EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanInfo.getElanTag());
217         if (etreeLeafTag != null) {
218             long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
219             removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, leafTag);
220         }
221     }
222
223     private void removeEtreeBroadcastGrups(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
224             WriteTransaction deleteFlowGroupTx) {
225         removeLeavesEtreeBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
226         removeLeavesLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
227     }
228
229     private void removeLeavesLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
230             WriteTransaction deleteFlowGroupTx) {
231         EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
232         if (etreeInstance != null) {
233             BigInteger dpnId = interfaceInfo.getDpId();
234             long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeInstance.getEtreeLeafTagVal().getValue());
235             List<Bucket> listBuckets = new ArrayList<>();
236             int bucketId = 0;
237             listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
238             Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
239                     MDSALUtil.buildBucketLists(listBuckets));
240             LOG.trace("deleted the localBroadCast Group:{}", group);
241             mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
242         }
243     }
244
245     private void removeLeavesEtreeBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
246             WriteTransaction deleteFlowGroupTx) {
247         EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
248         if (etreeInstance != null) {
249             long etreeTag = etreeInstance.getEtreeLeafTagVal().getValue();
250             int bucketId = 0;
251             int actionKey = 0;
252             List<Bucket> listBuckets = new ArrayList<>();
253             List<Action> listAction = new ArrayList<>();
254             listAction.add(new ActionInfo(ActionType.group,
255                     new String[] { String.valueOf(ElanUtils.getEtreeLeafLocalBCGId(etreeTag)) }, ++actionKey)
256                             .buildAction());
257             listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
258                     MDSALUtil.WATCH_GROUP));
259             bucketId++;
260             listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, etreeTag));
261             BigInteger dpnId = interfaceInfo.getDpId();
262             long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeTag);
263             Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
264                     MDSALUtil.buildBucketLists(listBuckets));
265             LOG.trace("deleting the remoteBroadCast group:{}", group);
266             mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
267         }
268     }
269
270     private Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
271         String elanName = elanInfo.getElanInstanceName();
272         Elan elanState = ElanUtils.getElanByName(broker, elanName);
273         if (elanState == null) {
274             return elanState;
275         }
276         List<String> elanInterfaces = elanState.getElanInterfaces();
277         elanInterfaces.remove(interfaceName);
278         if (elanInterfaces.isEmpty()) {
279             tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
280             tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
281             tx.delete(LogicalDatastoreType.OPERATIONAL,
282                     ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
283         } else {
284             Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName)
285                     .setKey(new ElanKey(elanName)).build();
286             tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName),
287                     updateElanState);
288         }
289         return elanState;
290     }
291
292     private void deleteElanInterfaceFromConfigDS(String interfaceName, WriteTransaction tx) {
293         // removing the ElanInterface from the config data_store if interface is
294         // not present in Interface config DS
295         if (interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName) == null) {
296             tx.delete(LogicalDatastoreType.CONFIGURATION,
297                     ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
298         }
299     }
300
301     void removeEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo,
302             InterfaceInfo interfaceInfo, String interfaceName, boolean isInterfaceStateRemoved,
303             boolean isLastElanInterface) {
304         String elanName = elanInfo.getElanInstanceName();
305         WriteTransaction tx = broker.newWriteOnlyTransaction();
306         WriteTransaction deleteFlowGroupTx = broker.newWriteOnlyTransaction();
307         InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils
308                 .getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
309         LOG.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
310         if (interfaceInfo != null) {
311             Optional<ElanInterfaceMac> existingElanInterfaceMac = elanUtils.read(broker,
312                     LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
313             if (existingElanInterfaceMac.isPresent()) {
314                 List<PhysAddress> macAddresses = new ArrayList<>();
315                 List<MacEntry> existingMacEntries = existingElanInterfaceMac.get().getMacEntry();
316                 List<MacEntry> macEntries = new ArrayList<>();
317                 if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
318                     macEntries.addAll(existingMacEntries);
319                 }
320                 if (!macEntries.isEmpty()) {
321                     for (MacEntry macEntry : macEntries) {
322                         LOG.debug("removing the  mac-entry:{} present on elanInterface:{}",
323                                 macEntry.getMacAddress().getValue(), interfaceName);
324                         if (!isLastElanInterface) {
325                             tx.delete(LogicalDatastoreType.OPERATIONAL,
326                                     ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
327                         }
328                         elanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, deleteFlowGroupTx);
329                         macAddresses.add(macEntry.getMacAddress());
330                     }
331
332                     // Removing all those MACs from External Devices belonging
333                     // to this ELAN
334                     if (ElanUtils.isVxlan(elanInfo)) {
335                         elanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
336                     }
337                 }
338             }
339             removeDefaultTermFlow(interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag());
340             removeFilterEqualsTable(elanInfo, interfaceInfo, deleteFlowGroupTx);
341         } else {
342             // Interface does not exist in ConfigDS, so lets remove everything
343             // about that interface related to Elan
344             ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
345             if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
346                 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
347                 for (MacEntry macEntry : macEntries) {
348                     tx.delete(LogicalDatastoreType.OPERATIONAL,
349                             ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
350                 }
351             }
352         }
353         tx.delete(LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
354         if (!isInterfaceStateRemoved) {
355             unbindService(elanInfo, interfaceName, tx);
356         }
357         deleteElanInterfaceFromConfigDS(interfaceName, tx);
358         futures.add(ElanUtils.waitForTransactionToComplete(tx));
359         futures.add(ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx));
360     }
361
362     private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId,
363             String interfaceName, long elanTag, WriteTransaction tx) {
364         DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
365         if (dpnInterfaces != null) {
366             List<String> interfaceLists = dpnInterfaces.getInterfaces();
367             interfaceLists.remove(interfaceName);
368
369             if (interfaceLists == null || interfaceLists.isEmpty()) {
370                 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
371                 deleteElanDpnInterface(elanName, dpId, tx);
372             } else {
373                 dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
374             }
375         }
376         return dpnInterfaces;
377     }
378
379     private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
380         List<DpnInterfaces> dpnInterfaces = elanUtils.getInvolvedDpnsInElan(elanName);
381         for (DpnInterfaces dpnInterface : dpnInterfaces) {
382             BigInteger currentDpId = dpnInterface.getDpId();
383             if (!currentDpId.equals(dpId)) {
384                 for (String elanInterface : dpnInterface.getInterfaces()) {
385                     ElanInterfaceMac macs = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
386                     if (macs == null || macs.getMacEntry() == null) {
387                         continue;
388                     }
389                     for (MacEntry mac : macs.getMacEntry()) {
390                         removeTheMacFlowInTheDPN(dpId, elanTag, currentDpId, mac);
391                         removeEtreeMacFlowInTheDPN(dpId, elanTag, currentDpId, mac);
392                     }
393                 }
394             }
395         }
396     }
397
398     private void removeEtreeMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) {
399         EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanTag);
400         if (etreeLeafTag != null) {
401             removeTheMacFlowInTheDPN(dpId, etreeLeafTag.getEtreeLeafTag().getValue(), currentDpId, mac);
402         }
403     }
404
405     private void removeTheMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) {
406         mdsalManager
407                 .removeFlow(dpId,
408                         MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE,
409                                 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, currentDpId,
410                                         mac.getMacAddress().getValue(), elanTag)));
411     }
412
413     @Override
414     protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
415         // updating the static-Mac Entries for the existing elanInterface
416         String elanName = update.getElanInstanceName();
417         String interfaceName = update.getName();
418         List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
419         List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
420         if (updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
421             List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
422             if (existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
423                 existingClonedPhyAddress.addAll(0, existingPhysAddress);
424                 existingPhysAddress.removeAll(updatedPhysAddress);
425                 updatedPhysAddress.removeAll(existingClonedPhyAddress);
426                 // removing the PhyAddress which are not presented in the
427                 // updated List
428                 for (PhysAddress physAddress : existingPhysAddress) {
429                     removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
430                 }
431             }
432             // Adding the new PhysAddress which are presented in the updated
433             // List
434             if (updatedPhysAddress.size() > 0) {
435                 for (PhysAddress physAddress : updatedPhysAddress) {
436                     InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
437                     Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
438                             LogicalDatastoreType.OPERATIONAL, macId);
439                     WriteTransaction tx = broker.newWriteOnlyTransaction();
440                     if (existingMacEntry.isPresent()) {
441                         elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(
442                                 elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(),
443                                 tx);
444                     } else {
445                         elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(
446                                 ElanUtils.getElanInstanceByName(broker, elanName), interfaceName, physAddress, tx);
447                     }
448                     ElanUtils.waitForTransactionToComplete(tx);
449                 }
450             }
451         } else if (existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
452             for (PhysAddress physAddress : existingPhysAddress) {
453                 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
454             }
455         }
456     }
457
458     @Override
459     protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
460         String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
461         String interfaceName = elanInterfaceAdded.getName();
462         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
463         if (interfaceInfo == null) {
464             LOG.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
465             return;
466         }
467         ElanInstance elanInstance = ElanUtils.getElanInstanceByName(broker, elanInstanceName);
468
469         if (elanInstance == null) {
470             elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
471                     .setDescription(elanInterfaceAdded.getDescription()).build();
472             // Add the ElanInstance in the Configuration data-store
473             WriteTransaction tx = broker.newWriteOnlyTransaction();
474             List<String> elanInterfaces = new ArrayList<>();
475             elanInterfaces.add(interfaceName);
476             ElanUtils.updateOperationalDataStore(broker, idManager,
477                     elanInstance, elanInterfaces, tx);
478             ElanUtils.waitForTransactionToComplete(tx);
479             elanInstance = ElanUtils.getElanInstanceByName(broker, elanInstanceName);
480         }
481
482         Long elanTag = elanInstance.getElanTag();
483         // If elan tag is not updated, then put the elan interface into
484         // unprocessed entry map and entry. Let entries
485         // in this map get processed during ELAN update DCN.
486         if (elanTag == null) {
487             ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
488             if (elanInterfaces == null) {
489                 elanInterfaces = new ConcurrentLinkedQueue<>();
490             }
491             elanInterfaces.add(elanInterfaceAdded);
492             unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
493             return;
494         }
495         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
496         InterfaceAddWorkerOnElan addWorker = new InterfaceAddWorkerOnElan(elanInstanceName, elanInterfaceAdded,
497                 interfaceInfo, elanInstance, this);
498         coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
499     }
500
501     void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
502         List<ListenableFuture<Void>> futures = new ArrayList<>();
503         Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
504         if (elanInterfaces == null || elanInterfaces.isEmpty()) {
505             return;
506         }
507         for (ElanInterface elanInterface : elanInterfaces) {
508             String interfaceName = elanInterface.getName();
509             InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
510             addElanInterface(futures, elanInterface, interfaceInfo, elanInstance);
511         }
512     }
513
514     void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
515             WriteTransaction writeFlowGroupTx) {
516         ElanDpnInterfacesList elanDpnInterfacesList = elanUtils
517                 .getElanDpnInterfacesList(elanInstance.getElanInstanceName());
518         List<DpnInterfaces> dpnInterfaceLists = null;
519         if (elanDpnInterfacesList != null) {
520             dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
521         }
522         if (dpnInterfaceLists == null) {
523             dpnInterfaceLists = new ArrayList<>();
524         }
525         for (DpnInterfaces dpnInterfaces : dpnInterfaceLists) {
526             if (dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
527                 continue;
528             }
529             List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
530             for (String remoteIf : remoteElanInterfaces) {
531                 ElanInterfaceMac elanIfMac = elanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
532                 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
533                 if (elanIfMac == null) {
534                     continue;
535                 }
536                 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
537                 if (remoteMacEntries != null) {
538                     for (MacEntry macEntry : remoteMacEntries) {
539                         PhysAddress physAddress = macEntry.getMacAddress();
540                         elanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
541                                 remoteInterface.getInterfaceTag(), elanInstance.getElanTag(), physAddress.getValue(),
542                                 elanInstance.getElanInstanceName(), writeFlowGroupTx, remoteIf);
543                     }
544                 }
545             }
546         }
547     }
548
549     void addElanInterface(List<ListenableFuture<Void>> futures, ElanInterface elanInterface,
550             InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
551         Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
552         Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
553         Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
554
555         String interfaceName = elanInterface.getName();
556         String elanInstanceName = elanInterface.getElanInstanceName();
557
558         Elan elanInfo = ElanUtils.getElanByName(broker, elanInstanceName);
559         WriteTransaction tx = broker.newWriteOnlyTransaction();
560         if (elanInfo == null) {
561             List<String> elanInterfaces = new ArrayList<>();
562             elanInterfaces.add(interfaceName);
563             ElanUtils.updateOperationalDataStore(broker, idManager,
564                     elanInstance, elanInterfaces, tx);
565         } else {
566             createElanStateList(elanInstanceName, interfaceName, tx);
567         }
568         boolean isFirstInterfaceInDpn = false;
569         // Specific actions to the DPN where the ElanInterface has been added,
570         // for example, programming the
571         // External tunnel table if needed or adding the ElanInterface to the
572         // DpnInterfaces in the operational DS.
573         BigInteger dpId = interfaceInfo != null ? dpId = interfaceInfo.getDpId() : null;
574         DpnInterfaces dpnInterfaces = null;
575         if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
576             InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils
577                     .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
578             Optional<DpnInterfaces> existingElanDpnInterfaces = elanUtils.read(broker,
579                     LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
580             if (!existingElanDpnInterfaces.isPresent()) {
581                 isFirstInterfaceInDpn = true;
582                 // ELAN's 1st ElanInterface added to this DPN
583                 dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
584                 // The 1st ElanInterface in a DPN must program the Ext Tunnel
585                 // table, but only if Elan has VNI
586                 if (ElanUtils.isVxlan(elanInstance)) {
587                     setExternalTunnelTable(dpId, elanInstance);
588                 }
589                 elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
590             } else {
591                 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
592                 elanInterfaces.add(interfaceName);
593                 if (elanInterfaces.size() == 1) { // 1st dpn interface
594                     elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
595                 }
596                 dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
597             }
598         }
599
600         // add code to install Local/Remote BC group, unknow DMAC entry,
601         // terminating service table flow entry
602         // call bindservice of interfacemanager to create ingress table flow
603         // enty.
604         // Add interface to the ElanInterfaceForwardingEntires Container
605         createElanInterfaceTablesList(interfaceName, tx);
606         if (interfaceInfo != null) {
607             installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn, tx);
608         }
609         futures.add(ElanUtils.waitForTransactionToComplete(tx));
610
611         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
612         InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(interfaceName,
613                 elanInterface, interfaceInfo, elanInstance, isFirstInterfaceInDpn, this);
614         coordinator.enqueueJob(interfaceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
615     }
616
617     void setupEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInstance,
618             ElanInterface elanInterface, InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) {
619         String elanInstanceName = elanInstance.getElanInstanceName();
620         String interfaceName = elanInterface.getName();
621         WriteTransaction tx = broker.newWriteOnlyTransaction();
622         BigInteger dpId = interfaceInfo.getDpId();
623         WriteTransaction writeFlowGroupTx = broker.newWriteOnlyTransaction();
624         installEntriesForElanInterface(elanInstance, interfaceInfo, isFirstInterfaceInDpn, tx, writeFlowGroupTx);
625         List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
626         if (staticMacAddresses != null) {
627             boolean isInterfaceOperational = isOperational(interfaceInfo);
628             for (PhysAddress physAddress : staticMacAddresses) {
629                 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
630                 Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
631                         LogicalDatastoreType.OPERATIONAL, macId);
632                 if (existingMacEntry.isPresent()) {
633                     elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(
634                             elanInstanceName, interfaceName, existingMacEntry.get().getInterface(),
635                             existingMacEntry.get(), tx);
636                 } else {
637                     elanForwardingEntriesHandler
638                             .addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress, tx);
639                 }
640
641                 if (isInterfaceOperational) {
642                     // Setting SMAC, DMAC, UDMAC in this DPN and also in other
643                     // DPNs
644                     elanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT,
645                             physAddress.getValue(), writeFlowGroupTx);
646                 }
647             }
648
649             if (isInterfaceOperational) {
650                 // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop
651                 // on purpose.
652                 elanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId,
653                         staticMacAddresses);
654             }
655         }
656         futures.add(ElanUtils.waitForTransactionToComplete(tx));
657         futures.add(ElanUtils.waitForTransactionToComplete(writeFlowGroupTx));
658     }
659
660     protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName,
661             PhysAddress physAddress) {
662         InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
663         InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
664         Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
665                 LogicalDatastoreType.OPERATIONAL, macId);
666
667         if (!existingMacEntry.isPresent()) {
668             return;
669         }
670
671         MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName)
672                 .setKey(new MacEntryKey(physAddress)).build();
673         WriteTransaction tx = broker.newWriteOnlyTransaction();
674         elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(
675                 ElanUtils.getElanInstanceByName(broker, elanInstanceName), interfaceInfo, macEntry, tx);
676         elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName,
677                 physAddress, tx);
678         ElanUtils.waitForTransactionToComplete(tx);
679     }
680
681     private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
682         return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName))
683                 .child(MacEntry.class, new MacEntryKey(physAddress)).build();
684     }
685
686     private void installEntriesForElanInterface(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
687             boolean isFirstInterfaceInDpn, WriteTransaction tx, WriteTransaction writeFlowGroupTx) {
688         if (!isOperational(interfaceInfo)) {
689             return;
690         }
691         BigInteger dpId = interfaceInfo.getDpId();
692         elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, writeFlowGroupTx);
693         setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx);
694         if (isFirstInterfaceInDpn) {
695             // Terminating Service , UnknownDMAC Table.
696             setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
697             setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
698             // update the remote-DPNs remoteBC group entry with Tunnels
699             if(ElanUtils.isVxlan(elanInstance)) {
700                 setElanBCGrouponOtherDpns(elanInstance, elanInstance.getElanTag().longValue(), dpId, writeFlowGroupTx);
701             }
702             /*
703              * Install remote DMAC flow. This is required since this DPN is
704              * added later to the elan instance and remote DMACs of other
705              * interfaces in this elan instance are not present in the current
706              * dpn.
707              */
708             programRemoteDmacFlow(elanInstance, interfaceInfo, writeFlowGroupTx);
709         }
710         // bind the Elan service to the Interface
711         bindService(elanInstance, ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceInfo.getInterfaceName()), tx);
712     }
713
714     public void installEntriesForFirstInterfaceonDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
715             DpnInterfaces dpnInterfaces, boolean isFirstInterfaceInDpn, WriteTransaction tx) {
716         if (!isOperational(interfaceInfo)) {
717             return;
718         }
719         // LocalBroadcast Group creation with elan-Interfaces
720         setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
721         if (isFirstInterfaceInDpn) {
722             LOG.trace("waitTimeForSyncInstall is {}", WAIT_TIME_FOR_SYNC_INSTALL);
723             BigInteger dpId = interfaceInfo.getDpId();
724             // RemoteBroadcast Group creation
725             try {
726                 Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
727             } catch (InterruptedException e1) {
728                 LOG.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
729             }
730             setupElanBroadcastGroups(elanInfo, dpnInterfaces, dpId);
731             try {
732                 Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
733             } catch (InterruptedException e1) {
734                 LOG.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
735             }
736         }
737     }
738
739     public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
740             WriteTransaction writeFlowGroupTx) {
741         int ifTag = interfaceInfo.getInterfaceTag();
742         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
743                 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
744                 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
745                 getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
746                 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
747
748         mdsalManager.addFlowToTx(interfaceInfo.getDpId(), flow, writeFlowGroupTx);
749
750         Flow flowEntry = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
751                 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000 + ifTag), 10, elanInfo.getElanInstanceName(), 0,
752                 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
753                 getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
754
755         mdsalManager.addFlowToTx(interfaceInfo.getDpId(), flowEntry, writeFlowGroupTx);
756     }
757
758     public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
759             WriteTransaction deleteFlowGroupTx) {
760         int ifTag = interfaceInfo.getInterfaceTag();
761         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
762                 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
763                 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
764                 getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
765                 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
766
767         mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
768
769         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
770                 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000 + ifTag), 10, elanInfo.getElanInstanceName(), 0,
771                 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
772                 getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
773
774         mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flowEntity, deleteFlowGroupTx);
775     }
776
777     private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo, int bucketKeyStart,
778             InterfaceInfo interfaceInfo, long elanTag) {
779         return getRemoteBCGroupBuckets(elanInfo, null, interfaceInfo.getDpId(), bucketKeyStart, elanTag);
780     }
781
782     private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId,
783             int bucketId, long elanTag) {
784         List<Bucket> listBucketInfo = new ArrayList<>();
785         ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
786         listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId, elanTag));
787         listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId, bucketId));
788         listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId));
789         return listBucketInfo;
790     }
791
792     private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
793             long elanTag) {
794         List<Bucket> listBucketInfo = new ArrayList<>();
795         if (elanDpns != null) {
796             for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
797                 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId
798                         && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
799                     try {
800                         List<Action> listActionInfo = elanUtils.getInternalTunnelItmEgressAction(dpnId,
801                                 dpnInterface.getDpId(), elanTag);
802                         if (listActionInfo.isEmpty()) {
803                             continue;
804                         }
805                         listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
806                                 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
807                         bucketId++;
808                     } catch (Exception ex) {
809                         LOG.error("Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
810                                 dpnId, dpnInterface.getDpId());
811                     }
812                 }
813             }
814         }
815         return listBucketInfo;
816     }
817
818     private List<Bucket> getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns,
819             DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) {
820         DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId);
821         if (currDpnInterfaces == null || !elanUtils.isDpnPresent(currDpnInterfaces.getDpId())
822                 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
823             return Collections.emptyList();
824         }
825
826         List<Bucket> listBucketInfo = new ArrayList<>();
827         for (String interfaceName : currDpnInterfaces.getInterfaces()) {
828             if (elanUtils.isExternal(interfaceName)) {
829                 List<Action> listActionInfo = elanUtils.getExternalPortItmEgressAction(interfaceName);
830                 if (!listActionInfo.isEmpty()) {
831                     listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
832                             MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
833                     bucketId++;
834                 }
835             }
836         }
837         return listBucketInfo;
838     }
839
840     private DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) {
841         if (elanDpns != null) {
842             for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
843                 if (dpnInterface.getDpId() == dpnId) {
844                     return dpnInterface;
845                 }
846             }
847         }
848         return null;
849     }
850
851     private void setElanBCGrouponOtherDpns(ElanInstance elanInfo, long elanTag, BigInteger dpId, WriteTransaction tx) {
852         long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
853         List<Bucket> listBucket = new ArrayList<>();
854         int bucketId = 0;
855         ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
856         if (elanDpns != null) {
857             List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
858             for (DpnInterfaces dpnInterface : dpnInterfaceses) {
859                 List<Bucket> remoteListBucketInfo = new ArrayList<>();
860                 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpId)
861                         && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
862                     List<Action> listAction = new ArrayList<>();
863                     int actionKey = 0;
864                     listAction.add(new ActionInfo(ActionType.group,
865                             new String[] { String.valueOf(ElanUtils.getElanLocalBCGId(elanTag)) }, ++actionKey)
866                                     .buildAction());
867                     listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId,
868                             MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
869                     bucketId++;
870                     remoteListBucketInfo.addAll(listBucket);
871                     for (DpnInterfaces otherFes : dpnInterfaceses) {
872                         if (elanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
873                                 && otherFes.getInterfaces() != null && !otherFes.getInterfaces().isEmpty()) {
874                             try {
875                                 List<Action> remoteListActionInfo = elanUtils.getInternalTunnelItmEgressAction(
876                                         dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
877                                 if (!remoteListActionInfo.isEmpty()) {
878                                     remoteListBucketInfo
879                                             .add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT,
880                                                     bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
881                                     bucketId++;
882                                 }
883                             } catch (Exception ex) {
884                                 LOG.error(
885                                         "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
886                                         dpnInterface.getDpId(), otherFes.getDpId());
887                                 return;
888                             }
889                         }
890                     }
891                     List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpId,
892                             bucketId);
893                     remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
894
895                     if (remoteListBucketInfo.size() == 0) {
896                         LOG.debug("No ITM is present on Dpn - {} ", dpnInterface.getDpId());
897                         continue;
898                     }
899                     Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
900                             MDSALUtil.buildBucketLists(remoteListBucketInfo));
901                     mdsalManager.addGroupToTx(dpnInterface.getDpId(), group, tx);
902                 }
903             }
904         }
905     }
906
907     /**
908      * Returns the bucket info with the given interface as the only bucket.
909      */
910     private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
911         return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart,
912                 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
913     }
914
915     private List<MatchInfo> buildMatchesForVni(Long vni) {
916         List<MatchInfo> mkMatches = new ArrayList<>();
917         MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(vni) });
918         mkMatches.add(match);
919         return mkMatches;
920     }
921
922     private List<Instruction> getInstructionsForOutGroup(long groupId) {
923         List<Instruction> mkInstructions = new ArrayList<>();
924         List<Action> actions = new ArrayList<>();
925         actions.add(new ActionInfo(ActionType.group, new String[] { Long.toString(groupId) }).buildAction());
926         mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
927         return mkInstructions;
928     }
929
930     private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
931         List<MatchInfo> mkMatches = new ArrayList<>();
932         // Matching metadata
933         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
934                 ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG }));
935         return mkMatches;
936     }
937
938     /**
939      * Builds the list of instructions to be installed in the External Tunnel
940      * table (38), which so far consists in writing the elanTag in metadata and
941      * send packet to the new DHCP table.
942      *
943      * @param elanTag
944      *            elanTag to be written in metadata when flow is selected
945      * @return the instructions ready to be installed in a flow
946      */
947     private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
948         List<InstructionInfo> mkInstructions = new ArrayList<>();
949         mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
950                 new BigInteger[] { ElanUtils.getElanMetadataLabel(elanTag), ElanUtils.getElanMetadataMask() }));
951         // TODO: We should point to SMAC or DMAC depending on a configuration
952         // property to enable
953         // mac learning
954         mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.ELAN_DMAC_TABLE }));
955
956         return mkInstructions;
957     }
958
959     // Install DMAC entry on dst DPN
960     public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
961         String interfaceName = interfaceInfo.getInterfaceName();
962         ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
963         if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
964             WriteTransaction writeFlowTx = broker.newWriteOnlyTransaction();
965             List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
966             for (MacEntry macEntry : macEntries) {
967                 PhysAddress physAddress = macEntry.getMacAddress();
968                 elanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue(),
969                         writeFlowTx);
970             }
971             writeFlowTx.submit();
972         }
973     }
974
975     public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
976         setupElanBroadcastGroups(elanInfo, null, dpnId);
977     }
978
979     public void setupElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
980         setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
981         setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
982     }
983
984     public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
985         List<Bucket> listBucket = new ArrayList<>();
986         int bucketId = 0;
987         int actionKey = 0;
988         Long elanTag = elanInfo.getElanTag();
989         List<Action> listAction = new ArrayList<>();
990         listAction.add(new ActionInfo(ActionType.group,
991                 new String[] { String.valueOf(ElanUtils.getElanLocalBCGId(elanTag)) }, ++actionKey).buildAction());
992         listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
993                 MDSALUtil.WATCH_GROUP));
994         bucketId++;
995         List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
996                 elanInfo.getElanTag());
997         listBucket.addAll(listBucketInfoRemote);
998         long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
999         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1000                 MDSALUtil.buildBucketLists(listBucket));
1001         LOG.trace("Installing the remote BroadCast Group:{}", group);
1002         mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
1003     }
1004
1005     public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
1006         EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1007         if (etreeInstance != null) {
1008             long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
1009             List<Bucket> listBucket = new ArrayList<>();
1010             int bucketId = 0;
1011             int actionKey = 0;
1012             List<Action> listAction = new ArrayList<>();
1013             listAction.add(new ActionInfo(ActionType.group,
1014                     new String[] { String.valueOf(ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag)) }, ++actionKey)
1015                             .buildAction());
1016             listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
1017                     MDSALUtil.WATCH_GROUP));
1018             bucketId++;
1019             List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
1020                     etreeLeafTag);
1021             listBucket.addAll(listBucketInfoRemote);
1022             long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
1023             Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1024                     MDSALUtil.buildBucketLists(listBucket));
1025             LOG.trace("Installing the remote BroadCast Group:{}", group);
1026             mdsalManager.syncInstallGroup(dpnId, group,
1027                     ElanConstants.DELAY_TIME_IN_MILLISECOND);
1028         }
1029     }
1030
1031     private void createDropBucket(List<Bucket> listBucket) {
1032         List<Action> actionsInfos = new ArrayList<>();
1033         actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}).buildAction());
1034         Bucket dropBucket = MDSALUtil.buildBucket(actionsInfos, MDSALUtil.GROUP_WEIGHT, 0, MDSALUtil.WATCH_PORT,
1035                 MDSALUtil.WATCH_GROUP);
1036         listBucket.add(dropBucket);
1037     }
1038
1039     public void setupLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1040             InterfaceInfo interfaceInfo) {
1041         setupStandardLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo);
1042         setupLeavesLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo);
1043     }
1044
1045     public void setupStandardLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1046             InterfaceInfo interfaceInfo) {
1047         List<Bucket> listBucket = new ArrayList<>();
1048         int bucketId = 0;
1049         long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag());
1050
1051         List<String> interfaces = new ArrayList<>();
1052         if (newDpnInterface != null) {
1053             interfaces = newDpnInterface.getInterfaces();
1054         }
1055         for (String ifName : interfaces) {
1056             // In case if there is a InterfacePort in the cache which is not in
1057             // operational state, skip processing it
1058             InterfaceInfo ifInfo = interfaceManager
1059                     .getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
1060             if (!isOperational(ifInfo)) {
1061                 continue;
1062             }
1063
1064             if (!elanUtils.isExternal(ifName)) {
1065                 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId,
1066                         MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1067                 bucketId++;
1068             }
1069         }
1070
1071         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1072                 MDSALUtil.buildBucketLists(listBucket));
1073         LOG.trace("installing the localBroadCast Group:{}", group);
1074         mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group,
1075                 ElanConstants.DELAY_TIME_IN_MILLISECOND);
1076     }
1077
1078     private void setupLeavesLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1079             InterfaceInfo interfaceInfo) {
1080         EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1081         if (etreeInstance != null) {
1082             List<Bucket> listBucket = new ArrayList<>();
1083             int bucketId = 0;
1084
1085             List<String> interfaces = new ArrayList<>();
1086             if (newDpnInterface != null) {
1087                 interfaces = newDpnInterface.getInterfaces();
1088             }
1089             for (String ifName : interfaces) {
1090                 // In case if there is a InterfacePort in the cache which is not
1091                 // in
1092                 // operational state, skip processing it
1093                 InterfaceInfo ifInfo = interfaceManager
1094                         .getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
1095                 if (!isOperational(ifInfo)) {
1096                     continue;
1097                 }
1098
1099                 if (!elanUtils.isExternal(ifName)) {
1100                     // only add root interfaces
1101                     bucketId = addInterfaceIfRootInterface(bucketId, ifName, listBucket, ifInfo);
1102                 }
1103             }
1104
1105             if (listBucket.size() == 0) { // No Buckets
1106                 createDropBucket(listBucket);
1107             }
1108
1109             long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
1110             long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag);
1111             Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1112                     MDSALUtil.buildBucketLists(listBucket));
1113             LOG.trace("installing the localBroadCast Group:{}", group);
1114             mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group,
1115                     ElanConstants.DELAY_TIME_IN_MILLISECOND);
1116         }
1117     }
1118
1119     private int addInterfaceIfRootInterface(int bucketId, String ifName, List<Bucket> listBucket,
1120             InterfaceInfo ifInfo) {
1121         EtreeInterface etreeInterface = ElanUtils.getEtreeInterfaceByElanInterfaceName(broker, ifName);
1122         if (etreeInterface != null && etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1123             listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId,
1124                     MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1125             bucketId++;
1126         }
1127         return bucketId;
1128     }
1129
1130     public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
1131             WriteTransaction deleteFlowGroupTx) {
1132         BigInteger dpnId = interfaceInfo.getDpId();
1133         long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag());
1134         List<Bucket> listBuckets = new ArrayList<>();
1135         int bucketId = 0;
1136         listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
1137         // listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1,
1138         // interfaceInfo));
1139         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1140                 MDSALUtil.buildBucketLists(listBuckets));
1141         LOG.trace("deleted the localBroadCast Group:{}", group);
1142         mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
1143     }
1144
1145     public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
1146             WriteTransaction deleteFlowGroupTx) {
1147         int bucketId = 0;
1148         int actionKey = 0;
1149         Long elanTag = elanInfo.getElanTag();
1150         List<Bucket> listBuckets = new ArrayList<>();
1151         List<Action> listAction = new ArrayList<>();
1152         listAction.add(new ActionInfo(ActionType.group,
1153                 new String[] { String.valueOf(ElanUtils.getElanLocalBCGId(elanTag)) }, ++actionKey).buildAction());
1154         listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
1155                 MDSALUtil.WATCH_GROUP));
1156         bucketId++;
1157         listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, elanInfo.getElanTag()));
1158         BigInteger dpnId = interfaceInfo.getDpId();
1159         long groupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag());
1160         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1161                 MDSALUtil.buildBucketLists(listBuckets));
1162         LOG.trace("deleting the remoteBroadCast group:{}", group);
1163         mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
1164     }
1165
1166     /**
1167      * Installs a flow in the External Tunnel table consisting in translating
1168      * the VNI retrieved from the packet that came over a tunnel with a TOR into
1169      * elanTag that will be used later in the ELANs pipeline.
1170      *
1171      * @param dpnId
1172      *            the dpn id
1173      * @param elanInfo
1174      *            the elan info
1175      */
1176     public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
1177         long elanTag = elanInfo.getElanTag();
1178         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.EXTERNAL_TUNNEL_TABLE,
1179                 getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag), 5, // prio
1180                 elanInfo.getElanInstanceName(), // flowName
1181                 0, // idleTimeout
1182                 0, // hardTimeout
1183                 ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
1184                 buildMatchesForVni(elanInfo.getSegmentationId()), getInstructionsExtTunnelTable(elanTag));
1185
1186         mdsalManager.installFlow(flowEntity);
1187     }
1188
1189     /**
1190      * Removes, from External Tunnel table, the flow that translates from VNI to
1191      * elanTag. Important: ensure this method is only called whenever there is
1192      * no other ElanInterface in the specified DPN
1193      *
1194      * @param dpnId
1195      *            DPN whose Ext Tunnel table is going to be modified
1196      * @param elanInfo
1197      *            holds the elanTag needed for selecting the flow to be removed
1198      */
1199     public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
1200         // TODO: Use DataStoreJobCoordinator in order to avoid that removing the
1201         // last ElanInstance plus
1202         // adding a new one does (almost at the same time) are executed in that
1203         // exact order
1204
1205         String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
1206         FlowEntity flowEntity = new FlowEntity(dpnId);
1207         flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
1208         flowEntity.setFlowId(flowId);
1209         mdsalManager.removeFlow(flowEntity);
1210     }
1211
1212     public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
1213         setupTerminateServiceTable(elanInfo, dpId, elanInfo.getElanTag(), writeFlowGroupTx);
1214         setupEtreeTerminateServiceTable(elanInfo, dpId, writeFlowGroupTx);
1215     }
1216
1217     public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1218             WriteTransaction writeFlowGroupTx) {
1219         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1220                 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag), 5,
1221                 String.format("%s:%d", "ITM Flow Entry ", elanTag), 0, 0,
1222                 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)),
1223                 ElanUtils.getTunnelMatchesForServiceId((int) elanTag),
1224                 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag)));
1225
1226         mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
1227     }
1228
1229     private void setupEtreeTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId,
1230             WriteTransaction writeFlowGroupTx) {
1231         EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1232         if (etreeInstance != null) {
1233             setupTerminateServiceTable(elanInfo, dpId, etreeInstance.getEtreeLeafTagVal().getValue(), writeFlowGroupTx);
1234         }
1235     }
1236
1237     public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
1238         long elanTag = elanInfo.getElanTag();
1239         installLocalUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
1240         installRemoteUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
1241         setupEtreeUnknownDMacTable(elanInfo, dpId, elanTag, writeFlowGroupTx);
1242     }
1243
1244     private void setupEtreeUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1245             WriteTransaction writeFlowGroupTx) {
1246         EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanTag);
1247         if (etreeLeafTag != null) {
1248             long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
1249             installRemoteUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
1250             installLocalUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
1251         }
1252     }
1253
1254     private void installLocalUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1255             WriteTransaction writeFlowGroupTx) {
1256         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1257                 getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
1258                         /* SH flag */false),
1259                 5, elanInfo.getElanInstanceName(), 0, 0,
1260                 ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
1261                 getMatchesForElanTag(elanTag, /* SH flag */false),
1262                 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGId(elanTag)));
1263
1264         mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
1265     }
1266
1267     private void installRemoteUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1268             WriteTransaction writeFlowGroupTx) {
1269         // only if ELAN can connect to external network, perform the following
1270         if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) {
1271             Flow flowEntity2 = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1272                     getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
1273                             /* SH flag */true),
1274                     5, elanInfo.getElanInstanceName(), 0, 0,
1275                     ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
1276                     getMatchesForElanTag(elanTag, /* SH flag */true),
1277                     getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag)));
1278             mdsalManager.addFlowToTx(dpId, flowEntity2, writeFlowGroupTx);
1279         }
1280     }
1281
1282
1283     private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo, WriteTransaction deleteFlowGroupTx,
1284             long elanTag) {
1285         Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1286                 elanTag, /* SH flag */ false))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE).build();
1287         mdsalManager.removeFlowToTx(dpId, flow, deleteFlowGroupTx);
1288
1289         if (ElanUtils.isVxlan(elanInfo)) {
1290             Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1291                     elanTag, /* SH flag */ true))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE)
1292                     .build();
1293             mdsalManager.removeFlowToTx(dpId, flow2, deleteFlowGroupTx);
1294         }
1295     }
1296
1297     private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
1298         elanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
1299     }
1300
1301     private void bindService(ElanInstance elanInfo, ElanInterface elanInterface, WriteTransaction tx) {
1302         if (isStandardElanService(elanInterface)) {
1303             bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), tx);
1304         } else { // Etree service
1305             bindEtreeService(elanInfo, elanInterface, tx);
1306         }
1307     }
1308
1309     private void bindElanService(long elanTag, String elanInstanceName, String interfaceName, WriteTransaction tx) {
1310         int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
1311         int instructionKey = 0;
1312         List<Instruction> instructions = new ArrayList<>();
1313         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanTag),
1314                 MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
1315         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ELAN_SMAC_TABLE, ++instructionKey));
1316         short elanServiceIndex = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX);
1317         BoundServices serviceInfo = ElanUtils.getBoundServices(
1318                 String.format("%s.%s.%s", "vpn", elanInstanceName, interfaceName), elanServiceIndex,
1319                 priority, NwConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
1320         tx.put(LogicalDatastoreType.CONFIGURATION,
1321                 ElanUtils.buildServiceId(interfaceName, elanServiceIndex), serviceInfo, true);
1322     }
1323
1324     private void bindEtreeService(ElanInstance elanInfo, ElanInterface elanInterface, WriteTransaction tx) {
1325         if (elanInterface.getAugmentation(EtreeInterface.class).getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1326             bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), tx);
1327         } else {
1328             EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1329             if (etreeInstance == null) {
1330                 LOG.error("EtreeInterface " + elanInterface.getName() + " is associated with a non EtreeInstance: "
1331                         + elanInfo.getElanInstanceName());
1332             } else {
1333                 bindElanService(etreeInstance.getEtreeLeafTagVal().getValue(), elanInfo.getElanInstanceName(),
1334                         elanInterface.getName(), tx);
1335             }
1336         }
1337     }
1338
1339     private boolean isStandardElanService(ElanInterface elanInterface) {
1340         return elanInterface.getAugmentation(EtreeInterface.class) == null;
1341     }
1342
1343     private boolean isStandardElanService(ElanInstance elanInstance) {
1344         return elanInstance.getAugmentation(EtreeInstance.class) == null;
1345     }
1346
1347     private void unbindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
1348         tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.buildServiceId(interfaceName,
1349                 ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX)));
1350     }
1351
1352     private String getFlowRef(long tableId, long elanTag) {
1353         return new StringBuffer().append(tableId).append(elanTag).toString();
1354     }
1355
1356     private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) {
1357         return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString();
1358     }
1359
1360     private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
1361         List<Action> listAction = new ArrayList<>();
1362         int actionKey = 0;
1363         listAction.add(new ActionInfo(ActionType.set_field_tunnel_id,
1364                 new BigInteger[] { BigInteger.valueOf(interfaceInfo.getInterfaceTag()) }, actionKey).buildAction());
1365         actionKey++;
1366         listAction.add(new ActionInfo(ActionType.nx_resubmit,
1367                 new String[] { String.valueOf(NwConstants.ELAN_FILTER_EQUALS_TABLE) }, actionKey).buildAction());
1368         return listAction;
1369     }
1370
1371     private DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId,
1372             List<String> interfaceNames, WriteTransaction tx) {
1373         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
1374                 .setKey(new DpnInterfacesKey(dpId)).build();
1375         tx.put(LogicalDatastoreType.OPERATIONAL,
1376                 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, true);
1377         return dpnInterface;
1378     }
1379
1380     /**
1381      * Delete elan dpn interface from operational DS.
1382      *
1383      * @param elanInstanceName
1384      *            the elan instance name
1385      * @param dpId
1386      *            the dp id
1387      */
1388     private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId, WriteTransaction tx) {
1389         tx.delete(LogicalDatastoreType.OPERATIONAL,
1390                 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
1391     }
1392
1393     private DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId,
1394             WriteTransaction tx) {
1395         List<String> interfaceNames = new ArrayList<>();
1396         interfaceNames.add(interfaceName);
1397         DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
1398                 .setKey(new DpnInterfacesKey(dpId)).build();
1399         tx.put(LogicalDatastoreType.OPERATIONAL,
1400                 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, true);
1401         return dpnInterface;
1402     }
1403
1404     private void createElanInterfaceTablesList(String interfaceName, WriteTransaction tx) {
1405         InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils
1406                 .getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1407         Optional<ElanInterfaceMac> interfaceMacTables = elanUtils.read(broker,
1408                 LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
1409         // Adding new Elan Interface Port to the operational DataStore without
1410         // Static-Mac Entries..
1411         if (!interfaceMacTables.isPresent()) {
1412             ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName)
1413                     .setKey(new ElanInterfaceMacKey(interfaceName)).build();
1414             tx.put(LogicalDatastoreType.OPERATIONAL,
1415                     ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), elanInterfaceMacTable,
1416                     true);
1417         }
1418     }
1419
1420     private void createElanStateList(String elanInstanceName, String interfaceName, WriteTransaction tx) {
1421         InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
1422         Optional<Elan> elanInterfaceLists = elanUtils.read(broker,
1423                 LogicalDatastoreType.OPERATIONAL, elanInstance);
1424         // Adding new Elan Interface Port to the operational DataStore without
1425         // Static-Mac Entries..
1426         if (elanInterfaceLists.isPresent()) {
1427             List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
1428             if (interfaceLists == null) {
1429                 interfaceLists = new ArrayList<>();
1430             }
1431             interfaceLists.add(interfaceName);
1432             Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists)
1433                     .setKey(new ElanKey(elanInstanceName)).build();
1434             tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName),
1435                     elanState, true);
1436         }
1437     }
1438
1439     private boolean isOperational(InterfaceInfo interfaceInfo) {
1440         if (interfaceInfo == null) {
1441             return false;
1442         }
1443         return interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED;
1444     }
1445
1446     public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
1447         ElanDpnInterfaces dpnInterfaceLists = elanUtils.getElanDpnInterfacesList();
1448         if (dpnInterfaceLists == null) {
1449             return;
1450         }
1451         List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1452         for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1453             int cnt = 0;
1454             String elanName = elanDpns.getElanInstanceName();
1455             List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
1456             if (dpnInterfaces == null) {
1457                 continue;
1458             }
1459             for (DpnInterfaces dpnIf : dpnInterfaces) {
1460                 if (dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
1461                     cnt++;
1462                 }
1463             }
1464             if (cnt == 2) {
1465                 LOG.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
1466                 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, elanName);
1467                 // update Remote BC Group
1468                 setupElanBroadcastGroups(elanInfo, srcDpId);
1469
1470                 DpnInterfaces dpnInterface = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dstDpId);
1471                 Set<String> interfaceLists = new HashSet<>();
1472                 interfaceLists.addAll(dpnInterface.getInterfaces());
1473                 for (String ifName : interfaceLists) {
1474                     InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
1475                     if (isOperational(interfaceInfo)) {
1476                         installDMacAddressTables(elanInfo, interfaceInfo, srcDpId);
1477                     }
1478                 }
1479             }
1480
1481         }
1482     }
1483
1484     /**
1485      * Handle external tunnel state event.
1486      *
1487      * @param externalTunnel
1488      *            the external tunnel
1489      * @param intrf
1490      *            the interface
1491      */
1492     public void handleExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1493         if (!validateExternalTunnelStateEvent(externalTunnel, intrf)) {
1494             return;
1495         }
1496         // dpId/externalNodeId will be available either in source or destination
1497         // based on the tunnel end point
1498         BigInteger dpId = null;
1499         NodeId externalNodeId = null;
1500         if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
1501             dpId = new BigInteger(externalTunnel.getSourceDevice());
1502             externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
1503         } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
1504             dpId = new BigInteger(externalTunnel.getDestinationDevice());
1505             externalNodeId = new NodeId(externalTunnel.getSourceDevice());
1506         }
1507         if (dpId == null || externalNodeId == null) {
1508             LOG.error("Dp ID / externalNodeId not found in external tunnel {}", externalTunnel);
1509             return;
1510         }
1511
1512         ElanDpnInterfaces dpnInterfaceLists = elanUtils.getElanDpnInterfacesList();
1513         if (dpnInterfaceLists == null) {
1514             return;
1515         }
1516         List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1517         for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1518             String elanName = elanDpns.getElanInstanceName();
1519             ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, elanName);
1520
1521             DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1522             if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
1523                     || dpnInterfaces.getInterfaces().isEmpty()) {
1524                 continue;
1525             }
1526             LOG.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
1527
1528             setupElanBroadcastGroups(elanInfo, dpId);
1529             // install L2gwDevices local macs in dpn.
1530             elanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo, intrf.getName());
1531             // Install dpn macs on external device
1532             elanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
1533                     externalNodeId);
1534         }
1535         LOG.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
1536     }
1537
1538     /**
1539      * Validate external tunnel state event.
1540      *
1541      * @param externalTunnel
1542      *            the external tunnel
1543      * @param intrf
1544      *            the intrf
1545      * @return true, if successful
1546      */
1547     private boolean validateExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1548         if (intrf.getOperStatus() == Interface.OperStatus.Up) {
1549             String srcDevice = externalTunnel.getDestinationDevice();
1550             String destDevice = externalTunnel.getSourceDevice();
1551             ExternalTunnel otherEndPointExtTunnel = elanUtils.getExternalTunnel(srcDevice, destDevice,
1552                     LogicalDatastoreType.CONFIGURATION);
1553             if (LOG.isTraceEnabled()) {
1554                 LOG.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
1555                         otherEndPointExtTunnel);
1556             }
1557             if (otherEndPointExtTunnel != null) {
1558                 boolean otherEndPointInterfaceOperational = ElanUtils.isInterfaceOperational(
1559                         otherEndPointExtTunnel.getTunnelInterfaceName(), broker);
1560                 if (otherEndPointInterfaceOperational) {
1561                     return true;
1562                 } else {
1563                     LOG.debug("Other end [{}] of the external tunnel is not yet UP for {}",
1564                             otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
1565                 }
1566             }
1567         }
1568         return false;
1569     }
1570
1571     private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int lportTag) {
1572         List<MatchInfo> mkMatches = new ArrayList<>();
1573         // Matching metadata
1574         mkMatches.add(new MatchInfo(MatchFieldType.metadata,
1575                 new BigInteger[] { MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1576         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(lportTag) }));
1577         return mkMatches;
1578     }
1579
1580     private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int lportTag) {
1581         List<MatchInfo> mkMatches = new ArrayList<>();
1582         // Matching metadata
1583         mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(lportTag) }));
1584         return mkMatches;
1585     }
1586
1587     public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
1588         List<DpnInterfaces> dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
1589         if (dpns == null) {
1590             return;
1591         }
1592         for (DpnInterfaces dpn : dpns) {
1593             setupElanBroadcastGroups(elanInfo, dpn.getDpId());
1594         }
1595     }
1596
1597     public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
1598             int bucketId) {
1599         List<Bucket> listBucketInfo = new ArrayList<>();
1600         ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
1601                 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
1602         for (L2GatewayDevice device : map.values()) {
1603             String interfaceName = elanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
1604                     device.getHwvtepNodeId());
1605             if (interfaceName == null) {
1606                 continue;
1607             }
1608             List<Action> listActionInfo = elanUtils.buildTunnelItmEgressActions(interfaceName,
1609                     elanInfo.getSegmentationId());
1610             listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
1611                     MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1612             bucketId++;
1613         }
1614         return listBucketInfo;
1615     }
1616
1617     @Override
1618     protected ElanInterfaceManager getDataTreeChangeListener() {
1619         return this;
1620     }
1621 }