2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.elan.internal;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.HashSet;
13 import java.util.List;
15 import java.util.Queue;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ConcurrentLinkedQueue;
19 import java.util.concurrent.ConcurrentMap;
21 import org.apache.commons.lang3.StringUtils;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
25 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
26 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
27 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
28 import org.opendaylight.netvirt.elan.utils.ElanConstants;
29 import org.opendaylight.netvirt.elan.utils.ElanUtils;
30 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
31 import org.opendaylight.genius.itm.globals.ITMConstants;
32 import org.opendaylight.genius.mdsalutil.ActionInfo;
33 import org.opendaylight.genius.mdsalutil.ActionType;
34 import org.opendaylight.genius.mdsalutil.FlowEntity;
35 import org.opendaylight.genius.mdsalutil.InstructionInfo;
36 import org.opendaylight.genius.mdsalutil.InstructionType;
37 import org.opendaylight.genius.mdsalutil.MDSALUtil;
38 import org.opendaylight.genius.mdsalutil.MatchFieldType;
39 import org.opendaylight.genius.mdsalutil.MatchInfo;
40 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
41 import org.opendaylight.genius.mdsalutil.NwConstants;
42 //import org.opendaylight.genius.neutronvpn.api.l2gw.L2GatewayDevice;
43 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTableKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
78 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
79 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
83 import com.google.common.base.Optional;
84 import com.google.common.base.Preconditions;
87 * Class in charge of handling creations, modifications and removals of ElanInterfaces.
89 * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
92 @SuppressWarnings( "deprecation" )
93 public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface,ElanInterfaceManager> implements AutoCloseable {
95 private ElanServiceProvider elanServiceProvider = null;
96 private static volatile ElanInterfaceManager elanInterfaceManager = null;
97 private static long waitTimeForSyncInstall;
99 private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
100 new ConcurrentHashMap<String, ConcurrentLinkedQueue<ElanInterface>> ();
102 private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class);
104 public ElanInterfaceManager(ElanServiceProvider elanServiceProvider) {
105 super(ElanInterface.class,ElanInterfaceManager.class);
106 this.elanServiceProvider = elanServiceProvider;
109 public static ElanInterfaceManager getElanInterfaceManager(ElanServiceProvider elanServiceProvider) {
110 if (elanInterfaceManager == null) {
111 synchronized (ElanInterfaceManager.class) {
112 if (elanInterfaceManager == null) {
113 elanInterfaceManager = new ElanInterfaceManager(elanServiceProvider);
114 Long waitTime = Long.getLong("wait.time.sync.install");
115 if (waitTime == null) {
118 waitTimeForSyncInstall = waitTime;
122 return elanInterfaceManager;
125 protected InstanceIdentifier<ElanInterface> getWildCardPath() {
126 return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
130 protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
131 String interfaceName = del.getName();
132 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
134 * Handling in case the elan instance is deleted.If the Elan instance is deleted, there is no need to explicitly delete the elan interfaces
136 if (elanInfo == null) {
139 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
140 String elanInstanceName = elanInfo.getElanInstanceName();
141 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
142 InterfaceRemoveWorkerOnElan configWorker = new InterfaceRemoveWorkerOnElan(elanInstanceName, elanInfo, interfaceName, interfaceInfo, false, this);
143 coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
146 public void removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo, boolean isInterfaceStateRemoved) {
147 String elanName = elanInfo.getElanInstanceName();
148 boolean isLastElanInterface = false;
149 long elanTag = elanInfo.getElanTag();
150 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
151 WriteTransaction deleteFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
152 Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, tx);
153 if (elanState == null) {
156 List<String> elanInterfaces = elanState.getElanInterfaces();
157 if (elanInterfaces.size() == 0) {
158 isLastElanInterface = true;
160 if (interfaceInfo != null) {
161 BigInteger dpId = interfaceInfo.getDpId();
162 DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag, tx);
164 * If there are not elan ports, remove the unknown dmac, terminating service table
165 * flows, remote/local bc group
167 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
168 // No more Elan Interfaces in this DPN
169 logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
170 removeDefaultTermFlow(dpId, elanInfo.getElanTag());
171 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx);
172 removeElanBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
173 removeLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
174 if ( elanInfo.getVni() != null && elanInfo.getVni().longValue() != 0 ) {
175 unsetExternalTunnelTable(dpId, elanInfo);
178 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
181 ElanUtils.waitForTransactionToComplete(tx);
182 deleteFlowGroupTx.submit();
183 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
184 InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(interfaceName, elanInfo,
185 interfaceInfo, isInterfaceStateRemoved, this, isLastElanInterface);
186 coordinator.enqueueJob(interfaceName, removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES);
189 private Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
190 String elanName = elanInfo.getElanInstanceName();
191 Elan elanState = ElanUtils.getElanByName(elanName);
192 if(elanState == null) {
195 List<String> elanInterfaces = elanState.getElanInterfaces();
196 elanInterfaces.remove(interfaceName);
197 if(elanInterfaces.isEmpty()) {
198 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
199 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
200 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
202 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
203 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
208 private void deleteElanInterfaceFromConfigDS(String interfaceName, WriteTransaction tx) {
209 //removing the ElanInterface from the config data_store if interface is not present in Interface config DS
210 if (elanServiceProvider.getInterfaceManager().getInterfaceInfoFromConfigDataStore(interfaceName) == null) {
211 tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
215 void removeEntriesForElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String interfaceName, boolean isInterfaceStateRemoved, boolean isLastElanInterface) {
216 String elanName = elanInfo.getElanInstanceName();
217 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
218 WriteTransaction deleteFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
219 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
220 logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
221 if (interfaceInfo != null) {
222 Optional<ElanInterfaceMac> existingElanInterfaceMac = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
223 if(existingElanInterfaceMac.isPresent()) {
224 List<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
225 List<MacEntry> existingMacEntries = existingElanInterfaceMac.get().getMacEntry();
226 List<MacEntry> macEntries = new ArrayList<>();
227 if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
228 macEntries.addAll(existingMacEntries);
230 if(!macEntries.isEmpty()) {
231 for (MacEntry macEntry : macEntries) {
232 logger.debug("removing the mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
233 if (!isLastElanInterface) {
234 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
236 ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, deleteFlowGroupTx);
237 macAddresses.add(macEntry.getMacAddress());
240 // Removing all those MACs from External Devices belonging to this ELAN
241 if ( elanInfo.getVni() != null && elanInfo.getVni() != 0 ) {
242 ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
246 removeDefaultTermFlow(interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag());
247 removeFilterEqualsTable(elanInfo, interfaceInfo, deleteFlowGroupTx);
249 // Interface does not exist in ConfigDS, so lets remove everything about that interface related to Elan
250 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
251 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
252 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
253 for(MacEntry macEntry : macEntries) {
254 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
258 tx.delete(LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
259 if(!isInterfaceStateRemoved) {
260 unbindService(elanInfo, interfaceName, tx);
262 deleteElanInterfaceFromConfigDS(interfaceName, tx);
263 ElanUtils.waitForTransactionToComplete(tx);
264 deleteFlowGroupTx.submit();
267 private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName,
268 long elanTag, WriteTransaction tx) {
269 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
270 if(dpnInterfaces != null) {
271 List<String> interfaceLists = dpnInterfaces.getInterfaces();
272 interfaceLists.remove(interfaceName);
274 if (interfaceLists == null || interfaceLists.isEmpty()) {
275 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
276 deleteElanDpnInterface(elanName, dpId, tx);
278 dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
281 return dpnInterfaces;
284 private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
285 List<DpnInterfaces> dpnInterfaces = ElanUtils.getInvolvedDpnsInElan(elanName);
286 for (DpnInterfaces dpnInterface : dpnInterfaces) {
287 BigInteger currentDpId = dpnInterface.getDpId();
288 if (!currentDpId.equals(dpId)) {
289 for (String elanInterface : dpnInterface.getInterfaces()) {
290 ElanInterfaceMac macs = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
294 for (MacEntry mac : macs.getMacEntry())
295 elanServiceProvider.getMdsalManager().removeFlow(dpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
296 ElanUtils.getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, currentDpId, mac.getMacAddress().getValue(), elanTag)));
303 protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
304 // updating the static-Mac Entries for the existing elanInterface
305 String elanName = update.getElanInstanceName();
306 String interfaceName = update.getName();
307 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
308 List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
309 List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
310 if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
311 List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
312 if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
313 existingClonedPhyAddress.addAll(0, existingPhysAddress);
314 existingPhysAddress.removeAll(updatedPhysAddress);
315 updatedPhysAddress.removeAll(existingClonedPhyAddress);
316 // removing the PhyAddress which are not presented in the updated List
317 for(PhysAddress physAddress: existingPhysAddress) {
318 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
321 // Adding the new PhysAddress which are presented in the updated List
322 if(updatedPhysAddress.size() > 0) {
323 for(PhysAddress physAddress: updatedPhysAddress) {
324 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
325 Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
326 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
327 if(existingMacEntry.isPresent()) {
328 elanServiceProvider.getElanForwardingEntriesHandler().updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(), tx);
330 elanServiceProvider.getElanForwardingEntriesHandler().addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress, tx);
332 ElanUtils.waitForTransactionToComplete(tx);
335 } else if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
336 for( PhysAddress physAddress : existingPhysAddress) {
337 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
343 protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
344 String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
345 String interfaceName = elanInterfaceAdded.getName();
346 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
347 if (interfaceInfo == null) {
348 logger.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
351 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
353 if (elanInstance == null) {
354 elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInterfaceAdded.getDescription()).build();
355 //Add the ElanInstance in the Configuration data-store
356 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
357 List<String> elanInterfaces = new ArrayList<String>();
358 elanInterfaces.add(interfaceName);
359 ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(), elanInstance, elanInterfaces, tx);
360 ElanUtils.waitForTransactionToComplete(tx);
361 elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
365 Long elanTag = elanInstance.getElanTag();
366 // If elan tag is not updated, then put the elan interface into unprocessed entry map and entry. Let entries
367 // in this map get processed during ELAN update DCN.
368 if (elanTag == null) {
369 ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
370 if (elanInterfaces == null) {
371 elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
373 elanInterfaces.add(elanInterfaceAdded);
374 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
377 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
378 InterfaceAddWorkerOnElan addWorker = new InterfaceAddWorkerOnElan(elanInstanceName, elanInterfaceAdded,
379 interfaceInfo, elanInstance, this);
380 coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
383 void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
384 Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
385 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
388 for (ElanInterface elanInterface: elanInterfaces) {
389 String interfaceName = elanInterface.getName();
390 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
391 addElanInterface(elanInterface, interfaceInfo, elanInstance);
395 void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo, WriteTransaction writeFlowGroupTx){
396 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInstance.getElanInstanceName());
397 List<DpnInterfaces> dpnInterfaceLists = null;
398 if (elanDpnInterfacesList != null) {
399 dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
401 if (dpnInterfaceLists == null) {
402 dpnInterfaceLists = new ArrayList<DpnInterfaces>();
404 for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
405 if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
408 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
409 for(String remoteIf : remoteElanInterfaces) {
410 ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
411 InterfaceInfo remoteInterface = elanServiceProvider.getInterfaceManager().getInterfaceInfo(remoteIf);
412 if(elanIfMac == null) {
415 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
416 if(remoteMacEntries != null) {
417 for (MacEntry macEntry : remoteMacEntries) {
418 PhysAddress physAddress = macEntry.getMacAddress();
419 ElanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
420 remoteInterface.getInterfaceTag(),
421 elanInstance.getElanTag(),
422 physAddress.getValue(),
423 elanInstance.getElanInstanceName(), writeFlowGroupTx);
430 void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
431 Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
432 Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
433 Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
435 String interfaceName = elanInterface.getName();
436 String elanInstanceName = elanInterface.getElanInstanceName();
438 Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
439 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
440 if (elanInfo == null) {
441 List<String> elanInterfaces = new ArrayList<String>();
442 elanInterfaces.add(interfaceName);
443 ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(), elanInstance, elanInterfaces, tx);
445 createElanStateList(elanInstanceName, interfaceName, tx);
447 boolean isFirstInterfaceInDpn = false;
448 // Specific actions to the DPN where the ElanInterface has been added, for example, programming the
449 // External tunnel table if needed or adding the ElanInterface to the DpnInterfaces in the operational DS.
450 BigInteger dpId = ( interfaceInfo != null ) ? dpId = interfaceInfo.getDpId() : null;
451 DpnInterfaces dpnInterfaces = null;
452 if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
453 InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
454 Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
455 if (!existingElanDpnInterfaces.isPresent()) {
456 isFirstInterfaceInDpn = true;
457 // ELAN's 1st ElanInterface added to this DPN
458 dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
459 // The 1st ElanInterface in a DPN must program the Ext Tunnel table, but only if Elan has VNI
460 if ( elanInstance.getVni() != null && elanInstance.getVni().longValue() != 0 ) {
461 setExternalTunnelTable(dpId, elanInstance);
463 ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
465 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
466 elanInterfaces.add(interfaceName);
467 if (elanInterfaces.size() == 1) {//1st dpn interface
468 ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
470 dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
474 // add code to install Local/Remote BC group, unknow DMAC entry, terminating service table flow entry
475 // call bindservice of interfacemanager to create ingress table flow enty.
476 //Add interface to the ElanInterfaceForwardingEntires Container
477 createElanInterfaceTablesList(interfaceName, tx);
478 if (interfaceInfo != null) {
479 installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn, tx);
481 ElanUtils.waitForTransactionToComplete(tx);
483 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
484 InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(interfaceName, elanInterface,
485 interfaceInfo, elanInstance, isFirstInterfaceInDpn, this);
486 coordinator.enqueueJob(interfaceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
489 void setupEntriesForElanInterface(ElanInstance elanInstance, ElanInterface elanInterface,
490 InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) {
491 String elanInstanceName = elanInstance.getElanInstanceName();
492 String interfaceName = elanInterface.getName();
493 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
494 BigInteger dpId = interfaceInfo.getDpId();
495 WriteTransaction writeFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
496 installEntriesForElanInterface(elanInstance, interfaceInfo, isFirstInterfaceInDpn, tx, writeFlowGroupTx);
497 List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
498 if (staticMacAddresses != null) {
499 boolean isInterfaceOperational = isOperational(interfaceInfo);
500 for (PhysAddress physAddress : staticMacAddresses) {
501 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
502 Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
503 if (existingMacEntry.isPresent()) {
504 elanServiceProvider.getElanForwardingEntriesHandler().updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(),
505 existingMacEntry.get(), tx);
507 elanServiceProvider.getElanForwardingEntriesHandler().addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress, tx);
510 if ( isInterfaceOperational ) {
511 // Setting SMAC, DMAC, UDMAC in this DPN and also in other DPNs
512 ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue(), writeFlowGroupTx);
516 if ( isInterfaceOperational ) {
517 // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop on purpose.
518 ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, staticMacAddresses);
521 ElanUtils.waitForTransactionToComplete(tx);
522 writeFlowGroupTx.submit();
525 protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) {
526 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
527 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
528 Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
530 if (!existingMacEntry.isPresent()) {
534 MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build();
535 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
536 elanServiceProvider.getElanForwardingEntriesHandler().deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry, tx);
537 elanServiceProvider.getElanForwardingEntriesHandler().deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress, tx);
538 ElanUtils.waitForTransactionToComplete(tx);
542 private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
543 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
544 new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
547 private void installEntriesForElanInterface(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
548 boolean isFirstInterfaceInDpn, WriteTransaction tx, WriteTransaction writeFlowGroupTx) {
549 if (!isOperational(interfaceInfo)) {
552 BigInteger dpId = interfaceInfo.getDpId();
553 ElanUtils.setupTermDmacFlows(interfaceInfo, elanServiceProvider.getMdsalManager(), writeFlowGroupTx);
554 setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx);
555 if (isFirstInterfaceInDpn) {
556 //Terminating Service , UnknownDMAC Table.
557 setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
558 setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
559 //update the remote-DPNs remoteBC group entry with Tunnels
560 setElanBCGrouponOtherDpns(elanInstance, dpId, writeFlowGroupTx);
562 * Install remote DMAC flow.
563 * This is required since this DPN is added later to the elan instance
564 * and remote DMACs of other interfaces in this elan instance are not present in the current dpn.
566 programRemoteDmacFlow(elanInstance, interfaceInfo, writeFlowGroupTx);
568 // bind the Elan service to the Interface
569 bindService(elanInstance, interfaceInfo.getInterfaceName(), tx);
572 public void installEntriesForFirstInterfaceonDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, DpnInterfaces dpnInterfaces,
573 boolean isFirstInterfaceInDpn, WriteTransaction tx) {
574 if (!isOperational(interfaceInfo)) {
577 // LocalBroadcast Group creation with elan-Interfaces
578 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
579 if (isFirstInterfaceInDpn) {
580 logger.trace("waitTimeForSyncInstall is {}", waitTimeForSyncInstall);
581 BigInteger dpId = interfaceInfo.getDpId();
582 // RemoteBroadcast Group creation
584 Thread.sleep(waitTimeForSyncInstall);
585 } catch (InterruptedException e1) {
586 logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
588 setupElanBroadcastGroups(elanInfo, dpId);
590 Thread.sleep(waitTimeForSyncInstall);
591 } catch (InterruptedException e1) {
592 logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
597 public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction writeFlowGroupTx) {
598 int ifTag = interfaceInfo.getInterfaceTag();
599 Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
600 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
602 elanServiceProvider.getMdsalManager().addFlowToTx(interfaceInfo.getDpId(), flow, writeFlowGroupTx);
604 Flow flowEntry = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
605 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
606 MDSALUtil.buildInstructionsDrop());
608 elanServiceProvider.getMdsalManager().addFlowToTx(interfaceInfo.getDpId(), flowEntry, writeFlowGroupTx);
611 public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
612 int ifTag = interfaceInfo.getInterfaceTag();
613 Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
614 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
616 elanServiceProvider.getMdsalManager().removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
618 Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
619 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
620 MDSALUtil.buildInstructionsDrop());
622 elanServiceProvider.getMdsalManager().removeFlowToTx(interfaceInfo.getDpId(), flowEntity, deleteFlowGroupTx);
625 private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
626 int bucketKeyStart, InterfaceInfo interfaceInfo) {
627 BigInteger dpnId = interfaceInfo.getDpId();
628 int elanTag = elanInfo.getElanTag().intValue();
629 int bucketId = bucketKeyStart;
630 List<Bucket> listBuckets = new ArrayList<Bucket>();
631 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
632 if (elanDpns != null) {
633 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
634 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
635 if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
637 List<Action> listAction = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
638 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
640 } catch (Exception ex) {
641 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
645 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId);
646 listBuckets.addAll(elanL2GwDevicesBuckets);
651 private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, BigInteger dpnId, int bucketId) {
652 int elanTag = elanInfo.getElanTag().intValue();
653 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
654 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
655 if (elanDpns != null) {
656 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
657 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
658 if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
660 List<Action> listActionInfo = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
661 if (listActionInfo.isEmpty()) {
664 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL));
666 } catch (Exception ex) {
667 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
672 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId);
673 listBucketInfo.addAll(elanL2GwDevicesBuckets);
675 return listBucketInfo;
678 private void setElanBCGrouponOtherDpns(ElanInstance elanInfo,
679 BigInteger dpId, WriteTransaction tx) {
680 int elanTag = elanInfo.getElanTag().intValue();
681 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
682 List<Bucket> listBucket = new ArrayList<Bucket>();
684 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
685 if (elanDpns != null) {
686 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
687 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
688 List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
689 if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
690 List<Action> listAction = new ArrayList<Action>();
692 listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
693 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
695 remoteListBucketInfo.addAll(listBucket);
696 for(DpnInterfaces otherFes : dpnInterfaceses) {
697 if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
698 && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
700 List<Action> remoteListActionInfo = ElanUtils.getInternalItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
701 remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP));
703 } catch (Exception ex) {
704 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() );
709 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpId,
711 remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
713 if (remoteListBucketInfo.size() == 0) {
714 logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId());
717 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo));
718 elanServiceProvider.getMdsalManager().addGroupToTx(dpnInterface.getDpId(), group, tx);
725 * Returns the bucket info with the given interface as the only bucket.
727 private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
728 return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
731 private List<MatchInfo> getMatchesForElanTag(Long elanTag) {
732 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
734 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
735 ElanUtils.getElanMetadataLabel(elanTag),
736 MetaDataUtil.METADATA_MASK_SERVICE }));
741 private List<MatchInfo> buildMatchesForVni(Long vni) {
742 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
743 MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id,
744 new BigInteger[]{BigInteger.valueOf(vni)} );
745 mkMatches.add(match);
749 private List<Instruction> getInstructionsForOutGroup(
751 List<Instruction> mkInstructions = new ArrayList<Instruction>();
752 List <Action> actions = new ArrayList <Action> ();
753 actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction());
754 mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
755 return mkInstructions;
758 private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
759 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
761 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
762 ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet),
763 MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG}));
768 * Builds the list of instructions to be installed in the External Tunnel table (38), which so far
769 * consists in writing the elanTag in metadata and send packet to the new DHCP table
771 * @param elanTag elanTag to be written in metadata when flow is selected
772 * @return the instructions ready to be installed in a flow
774 private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
775 List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
776 mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
778 ElanUtils.getElanMetadataLabel(elanTag),
779 ElanUtils.getElanMetadataMask()
781 // TODO: We should point to SMAC or DMAC depending on a configuration property to enable
783 mkInstructions.add(new InstructionInfo(InstructionType.goto_table,
784 new long[] { ElanConstants.ELAN_DMAC_TABLE }));
786 return mkInstructions;
789 // Install DMAC entry on dst DPN
790 public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
791 String interfaceName = interfaceInfo.getInterfaceName();
792 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
793 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
794 WriteTransaction writeFlowTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
795 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
796 for(MacEntry macEntry : macEntries) {
797 PhysAddress physAddress = macEntry.getMacAddress();
798 ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue(), writeFlowTx);
800 writeFlowTx.submit();
804 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
805 List<Bucket> listBucket = new ArrayList<Bucket>();
808 Long elanTag = elanInfo.getElanTag();
809 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
810 List<Action> listAction = new ArrayList<Action>();
811 listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
812 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
814 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnId, bucketId);
815 listBucket.addAll(listBucketInfoRemote);
816 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
817 logger.trace("Installing the remote BroadCast Group:{}", group);
818 elanServiceProvider.getMdsalManager().syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
821 public void setupLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface, InterfaceInfo interfaceInfo) {
822 List<Bucket> listBucket = new ArrayList<Bucket>();
824 BigInteger dpnId = interfaceInfo.getDpId();
825 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
827 List<String> interfaces = new ArrayList<String>();
828 if (newDpnInterface != null) {
829 interfaces = newDpnInterface.getInterfaces();
831 for(String ifName : interfaces) {
832 // In case if there is a InterfacePort in the cache which is not in
833 // operational state, skip processing it
834 InterfaceInfo ifInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
835 if (!isOperational(ifInfo)) {
839 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
843 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
844 logger.trace("installing the localBroadCast Group:{}", group);
845 elanServiceProvider.getMdsalManager().syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
848 public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
849 BigInteger dpnId = interfaceInfo.getDpId();
850 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
851 List<Bucket> listBuckets = new ArrayList<>();
853 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
854 //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo));
855 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
856 logger.trace("deleted the localBroadCast Group:{}", group);
857 elanServiceProvider.getMdsalManager().removeGroupToTx(dpnId, group, deleteFlowGroupTx);
860 public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
863 Long elanTag = elanInfo.getElanTag();
864 List<Bucket> listBuckets = new ArrayList<>();
865 List<Action> listAction = new ArrayList<Action>();
866 listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
867 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
869 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo));
870 BigInteger dpnId = interfaceInfo.getDpId();
871 long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
872 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
873 logger.trace("deleting the remoteBroadCast group:{}", group);
874 elanServiceProvider.getMdsalManager().removeGroupToTx(dpnId, group, deleteFlowGroupTx);
878 * Installs a flow in the External Tunnel table consisting in translating
879 * the VNI retrieved from the packet that came over a tunnel with a TOR into
880 * elanTag that will be used later in the ELANs pipeline.
887 public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
888 long elanTag = elanInfo.getElanTag();
889 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
890 NwConstants.EXTERNAL_TUNNEL_TABLE,
891 getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag),
893 elanInfo.getElanInstanceName(), // flowName
896 ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
897 buildMatchesForVni(elanInfo.getVni()),
898 getInstructionsExtTunnelTable(elanTag) );
900 elanServiceProvider.getMdsalManager().installFlow(flowEntity);
904 * Removes, from External Tunnel table, the flow that translates from VNI to elanTag.
905 * Important: ensure this method is only called whenever there is no other ElanInterface in the specified DPN
907 * @param dpnId DPN whose Ext Tunnel table is going to be modified
908 * @param elanInfo holds the elanTag needed for selecting the flow to be removed
910 public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
911 // TODO: Use DataStoreJobCoordinator in order to avoid that removing the last ElanInstance plus
912 // adding a new one does (almost at the same time) are executed in that exact order
914 String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
915 FlowEntity flowEntity = new FlowEntity(dpnId);
916 flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
917 flowEntity.setFlowId(flowId);
918 elanServiceProvider.getMdsalManager().removeFlow(flowEntity);
921 public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
922 long elanTag = elanInfo.getElanTag();
923 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag),
924 5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
925 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
927 elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
930 public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
931 long elanTag = elanInfo.getElanTag();
932 Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/false),
933 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/false),
934 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
936 elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
938 // only if vni is present in elanInfo, perform the following
939 if (elanInfo.getVni() != null && elanInfo.getVni() != 0) {
940 Flow flowEntity2 = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true),
941 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/true),
942 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
943 elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity2, writeFlowGroupTx);
948 private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo, WriteTransaction deleteFlowGroupTx) {
949 // Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
950 // mdsalManager.removeFlow(dpId, flow);
951 Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
952 elanInfo.getElanTag(), /*SH flag*/ false)))
953 .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
955 elanServiceProvider.getMdsalManager().removeFlowToTx(dpId, flow, deleteFlowGroupTx);
957 if ( elanInfo.getVni() != null && elanInfo.getVni() > 0 ) {
958 Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
959 elanInfo.getElanTag(), /*SH flag*/ true)))
960 .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
962 elanServiceProvider.getMdsalManager().removeFlowToTx(dpId, flow2, deleteFlowGroupTx);
968 private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
969 ElanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
972 private void bindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
973 // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName));
975 int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
976 int instructionKey = 0;
977 List<Instruction> instructions = new ArrayList<Instruction>();
978 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanInfo.getElanTag()), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
979 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey));
982 ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName),
983 ElanConstants.ELAN_SERVICE_INDEX, priority,
984 ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
985 tx.put(LogicalDatastoreType.CONFIGURATION,
986 ElanUtils.buildServiceId(interfaceName, ElanConstants.ELAN_SERVICE_INDEX), serviceInfo, true);
989 private void unbindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
990 tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX));
993 private String getFlowRef(long tableId, long elanTag) {
994 return new StringBuffer().append(tableId).append(elanTag).toString();
997 private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) {
998 return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString();
1001 private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
1002 List<Action> listAction = new ArrayList<Action>();
1004 listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction());
1006 listAction.add((new ActionInfo(ActionType.nx_resubmit,
1007 new String[] {String.valueOf(ElanConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction());
1011 private DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames, WriteTransaction tx) {
1012 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1013 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
1014 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
1015 dpnInterface, true);
1016 return dpnInterface;
1020 * Delete elan dpn interface from operational DS.
1022 * @param elanInstanceName
1023 * the elan instance name
1027 private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId, WriteTransaction tx) {
1028 tx.delete(LogicalDatastoreType.OPERATIONAL,
1029 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
1032 private DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId, WriteTransaction tx) {
1033 List<String> interfaceNames = new ArrayList<String>();
1034 interfaceNames.add(interfaceName);
1035 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1036 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
1037 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
1038 dpnInterface, true);
1039 return dpnInterface;
1042 private void createElanInterfaceTablesList(String interfaceName, WriteTransaction tx) {
1043 InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1044 Optional<ElanInterfaceMac> interfaceMacTables = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
1045 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
1046 if (!interfaceMacTables.isPresent()) {
1047 ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName).setKey(new ElanInterfaceMacKey(interfaceName)).build();
1048 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName),
1049 elanInterfaceMacTable, true);
1053 private void createElanStateList(String elanInstanceName, String interfaceName, WriteTransaction tx) {
1054 InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
1055 Optional<Elan> elanInterfaceLists = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInstance);
1056 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
1057 if (elanInterfaceLists.isPresent()) {
1058 List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
1059 if (interfaceLists == null) {
1060 interfaceLists = new ArrayList<>();
1062 interfaceLists.add(interfaceName);
1063 Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists).setKey(new ElanKey(elanInstanceName)).build();
1064 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState, true);
1068 private boolean isOperational(InterfaceInfo interfaceInfo) {
1069 if (interfaceInfo == null) {
1072 return interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED;
1075 public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
1076 ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
1077 if (dpnInterfaceLists == null) {
1080 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1081 for(ElanDpnInterfacesList elanDpns: elanDpnIf) {
1083 String elanName = elanDpns.getElanInstanceName();
1084 List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
1085 if (dpnInterfaces == null) {
1088 for (DpnInterfaces dpnIf : dpnInterfaces) {
1089 if (dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
1094 logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
1095 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
1096 // update Remote BC Group
1097 setupElanBroadcastGroups(elanInfo, srcDpId);
1099 DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dstDpId);
1100 Set<String> interfaceLists = new HashSet<>();
1101 interfaceLists.addAll(dpnInterface.getInterfaces());
1102 for(String ifName : interfaceLists) {
1103 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(ifName);
1104 if (isOperational(interfaceInfo)) {
1105 installDMacAddressTables(elanInfo, interfaceInfo, srcDpId);
1114 * Handle external tunnel state event.
1116 * @param externalTunnel
1117 * the external tunnel
1121 public void handleExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1122 if (!validateExternalTunnelStateEvent(externalTunnel, intrf)) {
1125 // dpId/externalNodeId will be available either in source or destination
1126 // based on the tunnel end point
1127 BigInteger dpId = null;
1128 NodeId externalNodeId = null;
1129 if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
1130 dpId = new BigInteger(externalTunnel.getSourceDevice());
1131 externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
1132 } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
1133 dpId = new BigInteger(externalTunnel.getDestinationDevice());
1134 externalNodeId = new NodeId(externalTunnel.getSourceDevice());
1136 if (dpId == null || externalNodeId == null) {
1137 logger.error("Dp ID / externalNodeId not found in external tunnel {}", externalTunnel);
1141 ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
1142 if (dpnInterfaceLists == null) {
1145 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1146 for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1147 String elanName = elanDpns.getElanInstanceName();
1148 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
1150 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1151 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
1152 || dpnInterfaces.getInterfaces().isEmpty()) {
1155 logger.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
1157 setupElanBroadcastGroups(elanInfo, dpId);
1158 // install L2gwDevices local macs in dpn.
1159 ElanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo);
1160 // Install dpn macs on external device
1161 ElanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
1164 logger.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
1168 * Validate external tunnel state event.
1170 * @param externalTunnel
1171 * the external tunnel
1174 * @return true, if successful
1176 private boolean validateExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1177 if (intrf.getOperStatus() == Interface.OperStatus.Up) {
1178 String srcDevice = externalTunnel.getDestinationDevice();
1179 String destDevice = externalTunnel.getSourceDevice();
1180 ExternalTunnel otherEndPointExtTunnel = ElanUtils.getExternalTunnel(srcDevice, destDevice,
1181 LogicalDatastoreType.CONFIGURATION);
1182 if (logger.isTraceEnabled()) {
1183 logger.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
1184 otherEndPointExtTunnel);
1186 if (otherEndPointExtTunnel != null) {
1187 boolean otherEndPointInterfaceOperational = ElanUtils
1188 .isInterfaceOperational(otherEndPointExtTunnel.getTunnelInterfaceName(), elanServiceProvider.getBroker());
1189 if (otherEndPointInterfaceOperational) {
1192 logger.debug("Other end [{}] of the external tunnel is not yet UP for {}",
1193 otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
1200 private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
1201 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1202 // Matching metadata
1203 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1204 MetaDataUtil.getLportTagMetaData(LportTag),
1205 MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1206 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(LportTag)}));
1211 private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
1212 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1213 // Matching metadata
1214 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
1215 BigInteger.valueOf(LportTag)}));
1219 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
1220 List<DpnInterfaces> dpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
1224 for (DpnInterfaces dpn : dpns) {
1225 setupElanBroadcastGroups(elanInfo, dpn.getDpId());
1229 public static List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
1231 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
1232 ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
1233 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
1234 for (L2GatewayDevice device : map.values()) {
1235 String interfaceName = ElanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
1236 device.getHwvtepNodeId());
1237 if (interfaceName == null) {
1240 List<Action> listActionInfo = ElanUtils.buildItmEgressActions(interfaceName, elanInfo.getVni());
1241 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
1242 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1245 return listBucketInfo;
1248 public ElanServiceProvider getElanServiceProvider() {
1249 return elanServiceProvider;
1252 public void setElanServiceProvider(ElanServiceProvider elanServiceProvider) {
1253 this.elanServiceProvider = elanServiceProvider;
1258 protected ElanInterfaceManager getDataTreeChangeListener() {