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.Collections;
13 import java.util.HashSet;
14 import java.util.List;
16 import java.util.Queue;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.ConcurrentLinkedQueue;
20 import java.util.concurrent.ConcurrentMap;
22 import org.apache.commons.lang3.StringUtils;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
26 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
27 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
28 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
29 import org.opendaylight.netvirt.elan.utils.ElanConstants;
30 import org.opendaylight.netvirt.elan.utils.ElanUtils;
31 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
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.neutronvpn.api.l2gw.L2GatewayDevice;
44 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTableKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
79 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
80 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
84 import com.google.common.base.Optional;
85 import com.google.common.base.Preconditions;
88 * Class in charge of handling creations, modifications and removals of ElanInterfaces.
90 * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
93 @SuppressWarnings( "deprecation" )
94 public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface,ElanInterfaceManager> implements AutoCloseable {
96 private ElanServiceProvider elanServiceProvider = null;
97 private static volatile ElanInterfaceManager elanInterfaceManager = null;
98 private static long waitTimeForSyncInstall;
100 private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
101 new ConcurrentHashMap<String, ConcurrentLinkedQueue<ElanInterface>> ();
103 private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class);
105 public ElanInterfaceManager(ElanServiceProvider elanServiceProvider) {
106 super(ElanInterface.class,ElanInterfaceManager.class);
107 this.elanServiceProvider = elanServiceProvider;
110 public static ElanInterfaceManager getElanInterfaceManager(ElanServiceProvider elanServiceProvider) {
111 if (elanInterfaceManager == null) {
112 synchronized (ElanInterfaceManager.class) {
113 if (elanInterfaceManager == null) {
114 elanInterfaceManager = new ElanInterfaceManager(elanServiceProvider);
115 Long waitTime = Long.getLong("wait.time.sync.install");
116 if (waitTime == null) {
119 waitTimeForSyncInstall = waitTime;
123 return elanInterfaceManager;
127 protected InstanceIdentifier<ElanInterface> getWildCardPath() {
128 return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
132 protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
133 String interfaceName = del.getName();
134 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
136 * Handling in case the elan instance is deleted.If the Elan instance is deleted, there is no need to explicitly delete the elan interfaces
138 if (elanInfo == null) {
141 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
142 String elanInstanceName = elanInfo.getElanInstanceName();
143 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
144 InterfaceRemoveWorkerOnElan configWorker = new InterfaceRemoveWorkerOnElan(elanInstanceName, elanInfo, interfaceName, interfaceInfo, false, this);
145 coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
148 public void removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo, boolean isInterfaceStateRemoved) {
149 String elanName = elanInfo.getElanInstanceName();
150 boolean isLastElanInterface = false;
151 long elanTag = elanInfo.getElanTag();
152 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
153 WriteTransaction deleteFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
154 Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, tx);
155 if (elanState == null) {
158 List<String> elanInterfaces = elanState.getElanInterfaces();
159 if (elanInterfaces.size() == 0) {
160 isLastElanInterface = true;
162 if (interfaceInfo != null) {
163 BigInteger dpId = interfaceInfo.getDpId();
164 DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag, tx);
166 * If there are not elan ports, remove the unknown dmac, terminating service table
167 * flows, remote/local bc group
169 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
170 // No more Elan Interfaces in this DPN
171 logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
172 removeDefaultTermFlow(dpId, elanInfo.getElanTag());
173 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx);
174 removeElanBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
175 removeLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
176 if (ElanUtils.isVxlan(elanInfo)) {
177 unsetExternalTunnelTable(dpId, elanInfo);
180 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
183 ElanUtils.waitForTransactionToComplete(tx);
184 ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx);
185 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
186 InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(interfaceName, elanInfo,
187 interfaceInfo, isInterfaceStateRemoved, this, isLastElanInterface);
188 coordinator.enqueueJob(interfaceName, removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES);
191 private Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
192 String elanName = elanInfo.getElanInstanceName();
193 Elan elanState = ElanUtils.getElanByName(elanName);
194 if(elanState == null) {
197 List<String> elanInterfaces = elanState.getElanInterfaces();
198 elanInterfaces.remove(interfaceName);
199 if(elanInterfaces.isEmpty()) {
200 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
201 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
202 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
204 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
205 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
210 private void deleteElanInterfaceFromConfigDS(String interfaceName, WriteTransaction tx) {
211 //removing the ElanInterface from the config data_store if interface is not present in Interface config DS
212 if (elanServiceProvider.getInterfaceManager().getInterfaceInfoFromConfigDataStore(interfaceName) == null) {
213 tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
217 void removeEntriesForElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String interfaceName, boolean isInterfaceStateRemoved, boolean isLastElanInterface) {
218 String elanName = elanInfo.getElanInstanceName();
219 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
220 WriteTransaction deleteFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
221 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
222 logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
223 if (interfaceInfo != null) {
224 Optional<ElanInterfaceMac> existingElanInterfaceMac = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
225 if(existingElanInterfaceMac.isPresent()) {
226 List<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
227 List<MacEntry> existingMacEntries = existingElanInterfaceMac.get().getMacEntry();
228 List<MacEntry> macEntries = new ArrayList<>();
229 if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
230 macEntries.addAll(existingMacEntries);
232 if(!macEntries.isEmpty()) {
233 for (MacEntry macEntry : macEntries) {
234 logger.debug("removing the mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
235 if (!isLastElanInterface) {
236 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
238 ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, deleteFlowGroupTx);
239 macAddresses.add(macEntry.getMacAddress());
242 // Removing all those MACs from External Devices belonging to this ELAN
243 if (ElanUtils.isVxlan(elanInfo)) {
244 ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
248 removeDefaultTermFlow(interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag());
249 removeFilterEqualsTable(elanInfo, interfaceInfo, deleteFlowGroupTx);
251 // Interface does not exist in ConfigDS, so lets remove everything about that interface related to Elan
252 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
253 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
254 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
255 for(MacEntry macEntry : macEntries) {
256 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
260 tx.delete(LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
261 if(!isInterfaceStateRemoved) {
262 unbindService(elanInfo, interfaceName, tx);
264 deleteElanInterfaceFromConfigDS(interfaceName, tx);
265 ElanUtils.waitForTransactionToComplete(tx);
266 ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx);
269 private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName,
270 long elanTag, WriteTransaction tx) {
271 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
272 if(dpnInterfaces != null) {
273 List<String> interfaceLists = dpnInterfaces.getInterfaces();
274 interfaceLists.remove(interfaceName);
276 if (interfaceLists == null || interfaceLists.isEmpty()) {
277 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
278 deleteElanDpnInterface(elanName, dpId, tx);
280 dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
283 return dpnInterfaces;
286 private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
287 List<DpnInterfaces> dpnInterfaces = ElanUtils.getInvolvedDpnsInElan(elanName);
288 for (DpnInterfaces dpnInterface : dpnInterfaces) {
289 BigInteger currentDpId = dpnInterface.getDpId();
290 if (!currentDpId.equals(dpId)) {
291 for (String elanInterface : dpnInterface.getInterfaces()) {
292 ElanInterfaceMac macs = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
296 for (MacEntry mac : macs.getMacEntry())
297 elanServiceProvider.getMdsalManager().removeFlow(dpId, MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE,
298 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, currentDpId, mac.getMacAddress().getValue(), elanTag)));
305 protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
306 // updating the static-Mac Entries for the existing elanInterface
307 String elanName = update.getElanInstanceName();
308 String interfaceName = update.getName();
309 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
310 List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
311 List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
312 if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
313 List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
314 if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
315 existingClonedPhyAddress.addAll(0, existingPhysAddress);
316 existingPhysAddress.removeAll(updatedPhysAddress);
317 updatedPhysAddress.removeAll(existingClonedPhyAddress);
318 // removing the PhyAddress which are not presented in the updated List
319 for(PhysAddress physAddress: existingPhysAddress) {
320 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
323 // Adding the new PhysAddress which are presented in the updated List
324 if(updatedPhysAddress.size() > 0) {
325 for(PhysAddress physAddress: updatedPhysAddress) {
326 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
327 Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
328 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
329 if(existingMacEntry.isPresent()) {
330 elanServiceProvider.getElanForwardingEntriesHandler().updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(), tx);
332 elanServiceProvider.getElanForwardingEntriesHandler().addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress, tx);
334 ElanUtils.waitForTransactionToComplete(tx);
337 } else if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
338 for( PhysAddress physAddress : existingPhysAddress) {
339 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
345 protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
346 String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
347 String interfaceName = elanInterfaceAdded.getName();
348 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
349 if (interfaceInfo == null) {
350 logger.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
353 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
355 if (elanInstance == null) {
356 elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInterfaceAdded.getDescription()).build();
357 //Add the ElanInstance in the Configuration data-store
358 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
359 List<String> elanInterfaces = new ArrayList<String>();
360 elanInterfaces.add(interfaceName);
361 ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(), elanInstance, elanInterfaces, tx);
362 ElanUtils.waitForTransactionToComplete(tx);
363 elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
367 Long elanTag = elanInstance.getElanTag();
368 // If elan tag is not updated, then put the elan interface into unprocessed entry map and entry. Let entries
369 // in this map get processed during ELAN update DCN.
370 if (elanTag == null) {
371 ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
372 if (elanInterfaces == null) {
373 elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
375 elanInterfaces.add(elanInterfaceAdded);
376 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
379 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
380 InterfaceAddWorkerOnElan addWorker = new InterfaceAddWorkerOnElan(elanInstanceName, elanInterfaceAdded,
381 interfaceInfo, elanInstance, this);
382 coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
385 void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
386 Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
387 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
390 for (ElanInterface elanInterface: elanInterfaces) {
391 String interfaceName = elanInterface.getName();
392 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
393 addElanInterface(elanInterface, interfaceInfo, elanInstance);
397 void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo, WriteTransaction writeFlowGroupTx){
398 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInstance.getElanInstanceName());
399 List<DpnInterfaces> dpnInterfaceLists = null;
400 if (elanDpnInterfacesList != null) {
401 dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
403 if (dpnInterfaceLists == null) {
404 dpnInterfaceLists = new ArrayList<DpnInterfaces>();
406 for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
407 if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
410 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
411 for(String remoteIf : remoteElanInterfaces) {
412 ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
413 InterfaceInfo remoteInterface = elanServiceProvider.getInterfaceManager().getInterfaceInfo(remoteIf);
414 if(elanIfMac == null) {
417 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
418 if(remoteMacEntries != null) {
419 for (MacEntry macEntry : remoteMacEntries) {
420 PhysAddress physAddress = macEntry.getMacAddress();
421 ElanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
422 remoteInterface.getInterfaceTag(),
423 elanInstance.getElanTag(),
424 physAddress.getValue(),
425 elanInstance.getElanInstanceName(), writeFlowGroupTx);
432 void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
433 Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
434 Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
435 Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
437 String interfaceName = elanInterface.getName();
438 String elanInstanceName = elanInterface.getElanInstanceName();
440 Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
441 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
442 if (elanInfo == null) {
443 List<String> elanInterfaces = new ArrayList<String>();
444 elanInterfaces.add(interfaceName);
445 ElanUtils.updateOperationalDataStore(elanServiceProvider.getBroker(), elanServiceProvider.getIdManager(), elanInstance, elanInterfaces, tx);
447 createElanStateList(elanInstanceName, interfaceName, tx);
449 boolean isFirstInterfaceInDpn = false;
450 // Specific actions to the DPN where the ElanInterface has been added, for example, programming the
451 // External tunnel table if needed or adding the ElanInterface to the DpnInterfaces in the operational DS.
452 BigInteger dpId = ( interfaceInfo != null ) ? dpId = interfaceInfo.getDpId() : null;
453 DpnInterfaces dpnInterfaces = null;
454 if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
455 InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
456 Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
457 if (!existingElanDpnInterfaces.isPresent()) {
458 isFirstInterfaceInDpn = true;
459 // ELAN's 1st ElanInterface added to this DPN
460 dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
461 // The 1st ElanInterface in a DPN must program the Ext Tunnel table, but only if Elan has VNI
462 if (ElanUtils.isVxlan(elanInstance)) {
463 setExternalTunnelTable(dpId, elanInstance);
465 ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
467 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
468 elanInterfaces.add(interfaceName);
469 if (elanInterfaces.size() == 1) {//1st dpn interface
470 ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
472 dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
476 // add code to install Local/Remote BC group, unknow DMAC entry, terminating service table flow entry
477 // call bindservice of interfacemanager to create ingress table flow enty.
478 //Add interface to the ElanInterfaceForwardingEntires Container
479 createElanInterfaceTablesList(interfaceName, tx);
480 if (interfaceInfo != null) {
481 installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn, tx);
483 ElanUtils.waitForTransactionToComplete(tx);
485 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
486 InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(interfaceName, elanInterface,
487 interfaceInfo, elanInstance, isFirstInterfaceInDpn, this);
488 coordinator.enqueueJob(interfaceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
491 void setupEntriesForElanInterface(ElanInstance elanInstance, ElanInterface elanInterface,
492 InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) {
493 String elanInstanceName = elanInstance.getElanInstanceName();
494 String interfaceName = elanInterface.getName();
495 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
496 BigInteger dpId = interfaceInfo.getDpId();
497 WriteTransaction writeFlowGroupTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
498 installEntriesForElanInterface(elanInstance, interfaceInfo, isFirstInterfaceInDpn, tx, writeFlowGroupTx);
499 List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
500 if (staticMacAddresses != null) {
501 boolean isInterfaceOperational = isOperational(interfaceInfo);
502 for (PhysAddress physAddress : staticMacAddresses) {
503 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
504 Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
505 if (existingMacEntry.isPresent()) {
506 elanServiceProvider.getElanForwardingEntriesHandler().updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(),
507 existingMacEntry.get(), tx);
509 elanServiceProvider.getElanForwardingEntriesHandler().addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress, tx);
512 if ( isInterfaceOperational ) {
513 // Setting SMAC, DMAC, UDMAC in this DPN and also in other DPNs
514 ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue(), writeFlowGroupTx);
518 if ( isInterfaceOperational ) {
519 // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop on purpose.
520 ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, staticMacAddresses);
523 ElanUtils.waitForTransactionToComplete(tx);
524 ElanUtils.waitForTransactionToComplete(writeFlowGroupTx);
527 protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) {
528 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(interfaceName);
529 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
530 Optional<MacEntry> existingMacEntry = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, macId);
532 if (!existingMacEntry.isPresent()) {
536 MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build();
537 WriteTransaction tx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
538 elanServiceProvider.getElanForwardingEntriesHandler().deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry, tx);
539 elanServiceProvider.getElanForwardingEntriesHandler().deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress, tx);
540 ElanUtils.waitForTransactionToComplete(tx);
544 private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
545 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
546 new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
549 private void installEntriesForElanInterface(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
550 boolean isFirstInterfaceInDpn, WriteTransaction tx, WriteTransaction writeFlowGroupTx) {
551 if (!isOperational(interfaceInfo)) {
554 BigInteger dpId = interfaceInfo.getDpId();
555 ElanUtils.setupTermDmacFlows(interfaceInfo, elanServiceProvider.getMdsalManager(), writeFlowGroupTx);
556 setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx);
557 if (isFirstInterfaceInDpn) {
558 //Terminating Service , UnknownDMAC Table.
559 setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
560 setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
561 //update the remote-DPNs remoteBC group entry with Tunnels
562 setElanBCGrouponOtherDpns(elanInstance, dpId, writeFlowGroupTx);
564 * Install remote DMAC flow.
565 * This is required since this DPN is added later to the elan instance
566 * and remote DMACs of other interfaces in this elan instance are not present in the current dpn.
568 programRemoteDmacFlow(elanInstance, interfaceInfo, writeFlowGroupTx);
570 // bind the Elan service to the Interface
571 bindService(elanInstance, interfaceInfo.getInterfaceName(), tx);
574 public void installEntriesForFirstInterfaceonDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, DpnInterfaces dpnInterfaces,
575 boolean isFirstInterfaceInDpn, WriteTransaction tx) {
576 if (!isOperational(interfaceInfo)) {
579 // LocalBroadcast Group creation with elan-Interfaces
580 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
581 if (isFirstInterfaceInDpn) {
582 logger.trace("waitTimeForSyncInstall is {}", waitTimeForSyncInstall);
583 BigInteger dpId = interfaceInfo.getDpId();
584 // RemoteBroadcast Group creation
586 Thread.sleep(waitTimeForSyncInstall);
587 } catch (InterruptedException e1) {
588 logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
590 setupElanBroadcastGroups(elanInfo, dpnInterfaces, dpId);
592 Thread.sleep(waitTimeForSyncInstall);
593 } catch (InterruptedException e1) {
594 logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
599 public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction writeFlowGroupTx) {
600 int ifTag = interfaceInfo.getInterfaceTag();
601 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
602 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
604 elanServiceProvider.getMdsalManager().addFlowToTx(interfaceInfo.getDpId(), flow, writeFlowGroupTx);
606 Flow flowEntry = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
607 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
608 MDSALUtil.buildInstructionsDrop());
610 elanServiceProvider.getMdsalManager().addFlowToTx(interfaceInfo.getDpId(), flowEntry, writeFlowGroupTx);
613 public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
614 int ifTag = interfaceInfo.getInterfaceTag();
615 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
616 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
618 elanServiceProvider.getMdsalManager().removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
620 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
621 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
622 MDSALUtil.buildInstructionsDrop());
624 elanServiceProvider.getMdsalManager().removeFlowToTx(interfaceInfo.getDpId(), flowEntity, deleteFlowGroupTx);
627 private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
628 int bucketKeyStart, InterfaceInfo interfaceInfo) {
629 return getRemoteBCGroupBuckets(elanInfo, null, interfaceInfo.getDpId(), bucketKeyStart);
632 private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) {
633 int elanTag = elanInfo.getElanTag().intValue();
634 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
635 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
636 listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId, elanTag));
637 listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId, bucketId));
638 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId));
639 return listBucketInfo;
642 private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
644 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
645 if (elanDpns != null) {
646 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
647 if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId
648 && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
650 List<Action> listActionInfo = ElanUtils.getInternalTunnelItmEgressAction(dpnId,
651 dpnInterface.getDpId(), elanTag);
652 if (listActionInfo.isEmpty()) {
655 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
656 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
658 } catch (Exception ex) {
659 logger.error("Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
660 dpnId, dpnInterface.getDpId());
665 return listBucketInfo;
668 private List<Bucket> getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns, DpnInterfaces dpnInterfaces, BigInteger dpnId,
670 DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId);
671 if (currDpnInterfaces == null || !ElanUtils.isDpnPresent(currDpnInterfaces.getDpId())
672 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
673 return Collections.emptyList();
676 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
677 for (String interfaceName : currDpnInterfaces.getInterfaces()) {
678 if (ElanUtils.isExternal(interfaceName)) {
679 List<Action> listActionInfo = ElanUtils.getExternalPortItmEgressAction(interfaceName);
680 if (!listActionInfo.isEmpty()) {
681 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
682 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
687 return listBucketInfo;
690 private DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) {
691 if (elanDpns != null) {
692 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
693 if (dpnInterface.getDpId() == dpnId) {
701 private void setElanBCGrouponOtherDpns(ElanInstance elanInfo,
702 BigInteger dpId, WriteTransaction tx) {
703 int elanTag = elanInfo.getElanTag().intValue();
704 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
705 List<Bucket> listBucket = new ArrayList<Bucket>();
707 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
708 if (elanDpns != null) {
709 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
710 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
711 List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
712 if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
713 List<Action> listAction = new ArrayList<Action>();
715 listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
716 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
718 remoteListBucketInfo.addAll(listBucket);
719 for(DpnInterfaces otherFes : dpnInterfaceses) {
720 if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
721 && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
723 List<Action> remoteListActionInfo = ElanUtils.getInternalTunnelItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
724 if (!remoteListActionInfo.isEmpty()) {
725 remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP));
728 } catch (Exception ex) {
729 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() );
734 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpId,
736 remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
738 if (remoteListBucketInfo.size() == 0) {
739 logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId());
742 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo));
743 elanServiceProvider.getMdsalManager().addGroupToTx(dpnInterface.getDpId(), group, tx);
750 * Returns the bucket info with the given interface as the only bucket.
752 private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
753 return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
756 private List<MatchInfo> getMatchesForElanTag(Long elanTag) {
757 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
759 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
760 ElanUtils.getElanMetadataLabel(elanTag),
761 MetaDataUtil.METADATA_MASK_SERVICE }));
766 private List<MatchInfo> buildMatchesForVni(Long vni) {
767 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
768 MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id,
769 new BigInteger[]{BigInteger.valueOf(vni)} );
770 mkMatches.add(match);
774 private List<Instruction> getInstructionsForOutGroup(
776 List<Instruction> mkInstructions = new ArrayList<Instruction>();
777 List <Action> actions = new ArrayList <Action> ();
778 actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction());
779 mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
780 return mkInstructions;
783 private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
784 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
786 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
787 ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet),
788 MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG}));
793 * Builds the list of instructions to be installed in the External Tunnel table (38), which so far
794 * consists in writing the elanTag in metadata and send packet to the new DHCP table
796 * @param elanTag elanTag to be written in metadata when flow is selected
797 * @return the instructions ready to be installed in a flow
799 private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
800 List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
801 mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
803 ElanUtils.getElanMetadataLabel(elanTag),
804 ElanUtils.getElanMetadataMask()
806 // TODO: We should point to SMAC or DMAC depending on a configuration property to enable
808 mkInstructions.add(new InstructionInfo(InstructionType.goto_table,
809 new long[] { NwConstants.ELAN_DMAC_TABLE }));
811 return mkInstructions;
814 // Install DMAC entry on dst DPN
815 public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
816 String interfaceName = interfaceInfo.getInterfaceName();
817 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
818 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
819 WriteTransaction writeFlowTx = elanServiceProvider.getBroker().newWriteOnlyTransaction();
820 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
821 for(MacEntry macEntry : macEntries) {
822 PhysAddress physAddress = macEntry.getMacAddress();
823 ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue(), writeFlowTx);
825 writeFlowTx.submit();
829 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
830 setupElanBroadcastGroups(elanInfo, null, dpnId);
833 public void setupElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
834 List<Bucket> listBucket = new ArrayList<Bucket>();
837 Long elanTag = elanInfo.getElanTag();
838 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
839 List<Action> listAction = new ArrayList<Action>();
840 listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
841 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
843 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId);
844 listBucket.addAll(listBucketInfoRemote);
845 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
846 logger.trace("Installing the remote BroadCast Group:{}", group);
847 elanServiceProvider.getMdsalManager().syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
850 public void setupLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface, InterfaceInfo interfaceInfo) {
851 List<Bucket> listBucket = new ArrayList<Bucket>();
853 BigInteger dpnId = interfaceInfo.getDpId();
854 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
856 List<String> interfaces = new ArrayList<String>();
857 if (newDpnInterface != null) {
858 interfaces = newDpnInterface.getInterfaces();
860 for(String ifName : interfaces) {
861 // In case if there is a InterfacePort in the cache which is not in
862 // operational state, skip processing it
863 InterfaceInfo ifInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
864 if (!isOperational(ifInfo)) {
868 if (!ElanUtils.isExternal(ifName)) {
869 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId,
870 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
875 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
876 logger.trace("installing the localBroadCast Group:{}", group);
877 elanServiceProvider.getMdsalManager().syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
880 public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
881 BigInteger dpnId = interfaceInfo.getDpId();
882 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
883 List<Bucket> listBuckets = new ArrayList<>();
885 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
886 //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo));
887 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
888 logger.trace("deleted the localBroadCast Group:{}", group);
889 elanServiceProvider.getMdsalManager().removeGroupToTx(dpnId, group, deleteFlowGroupTx);
892 public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo, WriteTransaction deleteFlowGroupTx) {
895 Long elanTag = elanInfo.getElanTag();
896 List<Bucket> listBuckets = new ArrayList<>();
897 List<Action> listAction = new ArrayList<Action>();
898 listAction.add((new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}, ++actionKey)).buildAction());
899 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
901 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo));
902 BigInteger dpnId = interfaceInfo.getDpId();
903 long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
904 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
905 logger.trace("deleting the remoteBroadCast group:{}", group);
906 elanServiceProvider.getMdsalManager().removeGroupToTx(dpnId, group, deleteFlowGroupTx);
910 * Installs a flow in the External Tunnel table consisting in translating
911 * the VNI retrieved from the packet that came over a tunnel with a TOR into
912 * elanTag that will be used later in the ELANs pipeline.
919 public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
920 long elanTag = elanInfo.getElanTag();
921 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
922 NwConstants.EXTERNAL_TUNNEL_TABLE,
923 getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag),
925 elanInfo.getElanInstanceName(), // flowName
928 ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
929 buildMatchesForVni(elanInfo.getSegmentationId()),
930 getInstructionsExtTunnelTable(elanTag) );
932 elanServiceProvider.getMdsalManager().installFlow(flowEntity);
936 * Removes, from External Tunnel table, the flow that translates from VNI to elanTag.
937 * Important: ensure this method is only called whenever there is no other ElanInterface in the specified DPN
939 * @param dpnId DPN whose Ext Tunnel table is going to be modified
940 * @param elanInfo holds the elanTag needed for selecting the flow to be removed
942 public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
943 // TODO: Use DataStoreJobCoordinator in order to avoid that removing the last ElanInstance plus
944 // adding a new one does (almost at the same time) are executed in that exact order
946 String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
947 FlowEntity flowEntity = new FlowEntity(dpnId);
948 flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
949 flowEntity.setFlowId(flowId);
950 elanServiceProvider.getMdsalManager().removeFlow(flowEntity);
953 public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
954 long elanTag = elanInfo.getElanTag();
955 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag),
956 5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
957 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
959 elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
962 public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
963 long elanTag = elanInfo.getElanTag();
964 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/false),
965 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/false),
966 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
968 elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
970 // only if ELAN can connect to external network, perform the following
971 if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) {
972 Flow flowEntity2 = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true),
973 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/true),
974 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
975 elanServiceProvider.getMdsalManager().addFlowToTx(dpId, flowEntity2, writeFlowGroupTx);
980 private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo, WriteTransaction deleteFlowGroupTx) {
981 // Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
982 // mdsalManager.removeFlow(dpId, flow);
983 Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
984 elanInfo.getElanTag(), /*SH flag*/ false)))
985 .setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE)
987 elanServiceProvider.getMdsalManager().removeFlowToTx(dpId, flow, deleteFlowGroupTx);
989 if (ElanUtils.isVxlan(elanInfo)) {
990 Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
991 elanInfo.getElanTag(), /*SH flag*/ true)))
992 .setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE)
994 elanServiceProvider.getMdsalManager().removeFlowToTx(dpId, flow2, deleteFlowGroupTx);
1000 private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
1001 ElanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
1004 private void bindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
1005 // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName));
1007 int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
1008 int instructionKey = 0;
1009 List<Instruction> instructions = new ArrayList<Instruction>();
1010 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanInfo.getElanTag()), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
1011 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ELAN_SMAC_TABLE, ++instructionKey));
1014 ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName),
1015 NwConstants.ELAN_SERVICE_INDEX, priority,
1016 NwConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
1017 tx.put(LogicalDatastoreType.CONFIGURATION,
1018 ElanUtils.buildServiceId(interfaceName, NwConstants.ELAN_SERVICE_INDEX), serviceInfo, true);
1021 private void unbindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
1022 tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.buildServiceId(interfaceName,NwConstants.ELAN_SERVICE_INDEX));
1025 private String getFlowRef(long tableId, long elanTag) {
1026 return new StringBuffer().append(tableId).append(elanTag).toString();
1029 private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) {
1030 return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString();
1033 private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
1034 List<Action> listAction = new ArrayList<Action>();
1036 listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction());
1038 listAction.add((new ActionInfo(ActionType.nx_resubmit,
1039 new String[] {String.valueOf(NwConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction());
1043 private DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames, WriteTransaction tx) {
1044 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1045 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
1046 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
1047 dpnInterface, true);
1048 return dpnInterface;
1052 * Delete elan dpn interface from operational DS.
1054 * @param elanInstanceName
1055 * the elan instance name
1059 private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId, WriteTransaction tx) {
1060 tx.delete(LogicalDatastoreType.OPERATIONAL,
1061 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
1064 private DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId, WriteTransaction tx) {
1065 List<String> interfaceNames = new ArrayList<String>();
1066 interfaceNames.add(interfaceName);
1067 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1068 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
1069 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
1070 dpnInterface, true);
1071 return dpnInterface;
1074 private void createElanInterfaceTablesList(String interfaceName, WriteTransaction tx) {
1075 InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1076 Optional<ElanInterfaceMac> interfaceMacTables = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
1077 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
1078 if (!interfaceMacTables.isPresent()) {
1079 ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName).setKey(new ElanInterfaceMacKey(interfaceName)).build();
1080 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName),
1081 elanInterfaceMacTable, true);
1085 private void createElanStateList(String elanInstanceName, String interfaceName, WriteTransaction tx) {
1086 InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
1087 Optional<Elan> elanInterfaceLists = ElanUtils.read(elanServiceProvider.getBroker(), LogicalDatastoreType.OPERATIONAL, elanInstance);
1088 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
1089 if (elanInterfaceLists.isPresent()) {
1090 List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
1091 if (interfaceLists == null) {
1092 interfaceLists = new ArrayList<>();
1094 interfaceLists.add(interfaceName);
1095 Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists).setKey(new ElanKey(elanInstanceName)).build();
1096 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState, true);
1100 private boolean isOperational(InterfaceInfo interfaceInfo) {
1101 if (interfaceInfo == null) {
1104 return interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED;
1107 public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
1108 ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
1109 if (dpnInterfaceLists == null) {
1112 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1113 for(ElanDpnInterfacesList elanDpns: elanDpnIf) {
1115 String elanName = elanDpns.getElanInstanceName();
1116 List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
1117 if (dpnInterfaces == null) {
1120 for (DpnInterfaces dpnIf : dpnInterfaces) {
1121 if (dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
1126 logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
1127 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
1128 // update Remote BC Group
1129 setupElanBroadcastGroups(elanInfo, srcDpId);
1131 DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dstDpId);
1132 Set<String> interfaceLists = new HashSet<>();
1133 interfaceLists.addAll(dpnInterface.getInterfaces());
1134 for(String ifName : interfaceLists) {
1135 InterfaceInfo interfaceInfo = elanServiceProvider.getInterfaceManager().getInterfaceInfo(ifName);
1136 if (isOperational(interfaceInfo)) {
1137 installDMacAddressTables(elanInfo, interfaceInfo, srcDpId);
1146 * Handle external tunnel state event.
1148 * @param externalTunnel
1149 * the external tunnel
1153 public void handleExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1154 if (!validateExternalTunnelStateEvent(externalTunnel, intrf)) {
1157 // dpId/externalNodeId will be available either in source or destination
1158 // based on the tunnel end point
1159 BigInteger dpId = null;
1160 NodeId externalNodeId = null;
1161 if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
1162 dpId = new BigInteger(externalTunnel.getSourceDevice());
1163 externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
1164 } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
1165 dpId = new BigInteger(externalTunnel.getDestinationDevice());
1166 externalNodeId = new NodeId(externalTunnel.getSourceDevice());
1168 if (dpId == null || externalNodeId == null) {
1169 logger.error("Dp ID / externalNodeId not found in external tunnel {}", externalTunnel);
1173 ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
1174 if (dpnInterfaceLists == null) {
1177 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1178 for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1179 String elanName = elanDpns.getElanInstanceName();
1180 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
1182 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1183 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
1184 || dpnInterfaces.getInterfaces().isEmpty()) {
1187 logger.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
1189 setupElanBroadcastGroups(elanInfo, dpId);
1190 // install L2gwDevices local macs in dpn.
1191 ElanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo);
1192 // Install dpn macs on external device
1193 ElanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
1196 logger.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
1200 * Validate external tunnel state event.
1202 * @param externalTunnel
1203 * the external tunnel
1206 * @return true, if successful
1208 private boolean validateExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1209 if (intrf.getOperStatus() == Interface.OperStatus.Up) {
1210 String srcDevice = externalTunnel.getDestinationDevice();
1211 String destDevice = externalTunnel.getSourceDevice();
1212 ExternalTunnel otherEndPointExtTunnel = ElanUtils.getExternalTunnel(srcDevice, destDevice,
1213 LogicalDatastoreType.CONFIGURATION);
1214 if (logger.isTraceEnabled()) {
1215 logger.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
1216 otherEndPointExtTunnel);
1218 if (otherEndPointExtTunnel != null) {
1219 boolean otherEndPointInterfaceOperational = ElanUtils
1220 .isInterfaceOperational(otherEndPointExtTunnel.getTunnelInterfaceName(), elanServiceProvider.getBroker());
1221 if (otherEndPointInterfaceOperational) {
1224 logger.debug("Other end [{}] of the external tunnel is not yet UP for {}",
1225 otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
1232 private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
1233 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1234 // Matching metadata
1235 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1236 MetaDataUtil.getLportTagMetaData(LportTag),
1237 MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1238 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(LportTag)}));
1243 private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
1244 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1245 // Matching metadata
1246 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
1247 BigInteger.valueOf(LportTag)}));
1251 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
1252 List<DpnInterfaces> dpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
1256 for (DpnInterfaces dpn : dpns) {
1257 setupElanBroadcastGroups(elanInfo, dpn.getDpId());
1261 public static List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
1263 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
1264 ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
1265 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
1266 for (L2GatewayDevice device : map.values()) {
1267 String interfaceName = ElanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
1268 device.getHwvtepNodeId());
1269 if (interfaceName == null) {
1272 List<Action> listActionInfo = ElanUtils.buildTunnelItmEgressActions(interfaceName, elanInfo.getSegmentationId());
1273 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
1274 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1277 return listBucketInfo;
1280 public ElanServiceProvider getElanServiceProvider() {
1281 return elanServiceProvider;
1284 public void setElanServiceProvider(ElanServiceProvider elanServiceProvider) {
1285 this.elanServiceProvider = elanServiceProvider;
1290 protected ElanInterfaceManager getDataTreeChangeListener() {