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 com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.HashSet;
17 import java.util.List;
19 import java.util.Queue;
21 import java.util.concurrent.ConcurrentHashMap;
22 import java.util.concurrent.ConcurrentLinkedQueue;
23 import java.util.concurrent.ConcurrentMap;
24 import org.apache.commons.lang3.StringUtils;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
29 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
30 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
31 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
32 import org.opendaylight.genius.itm.globals.ITMConstants;
33 import org.opendaylight.genius.mdsalutil.ActionInfo;
34 import org.opendaylight.genius.mdsalutil.ActionType;
35 import org.opendaylight.genius.mdsalutil.FlowEntity;
36 import org.opendaylight.genius.mdsalutil.InstructionInfo;
37 import org.opendaylight.genius.mdsalutil.InstructionType;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.genius.mdsalutil.MatchFieldType;
40 import org.opendaylight.genius.mdsalutil.MatchInfo;
41 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
42 import org.opendaylight.genius.mdsalutil.NwConstants;
43 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
44 import org.opendaylight.genius.utils.ServiceIndex;
45 import org.opendaylight.netvirt.elan.ElanException;
46 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
47 import org.opendaylight.netvirt.elan.utils.ElanConstants;
48 import org.opendaylight.netvirt.elan.utils.ElanForwardingEntriesHandler;
49 import org.opendaylight.netvirt.elan.utils.ElanUtils;
50 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
51 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTableKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
91 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
92 import org.slf4j.Logger;
93 import org.slf4j.LoggerFactory;
96 * Class in charge of handling creations, modifications and removals of
99 * @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
101 @SuppressWarnings("deprecation")
102 public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface, ElanInterfaceManager>
103 implements AutoCloseable {
105 private final DataBroker broker;
106 private final IMdsalApiManager mdsalManager;
107 private final IInterfaceManager interfaceManager;
108 private final IdManagerService idManager;
109 private final ElanForwardingEntriesHandler elanForwardingEntriesHandler;
110 private ElanL2GatewayUtils elanL2GatewayUtils;
111 private ElanUtils elanUtils;
113 private static final long WAIT_TIME_FOR_SYNC_INSTALL = Long.getLong("wait.time.sync.install", 300L);
115 private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces = new ConcurrentHashMap<>();
117 private static final Logger LOG = LoggerFactory.getLogger(ElanInterfaceManager.class);
119 public ElanInterfaceManager(final DataBroker dataBroker,
120 final IdManagerService managerService,
121 final IMdsalApiManager mdsalApiManager,
122 IInterfaceManager interfaceManager,
123 final ElanForwardingEntriesHandler elanForwardingEntriesHandler) {
124 super(ElanInterface.class, ElanInterfaceManager.class);
125 this.broker = dataBroker;
126 this.idManager = managerService;
127 this.mdsalManager = mdsalApiManager;
128 this.interfaceManager = interfaceManager;
129 this.elanForwardingEntriesHandler = elanForwardingEntriesHandler;
132 public void setElanUtils(ElanUtils elanUtils) {
133 this.elanUtils = elanUtils;
134 this.elanL2GatewayUtils = elanUtils.getElanL2GatewayUtils();
135 this.elanForwardingEntriesHandler.setElanUtils(elanUtils);
139 registerListener(LogicalDatastoreType.CONFIGURATION, broker);
143 protected InstanceIdentifier<ElanInterface> getWildCardPath() {
144 return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
148 protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
149 String interfaceName = del.getName();
150 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, del.getElanInstanceName());
152 * Handling in case the elan instance is deleted.If the Elan instance is
153 * deleted, there is no need to explicitly delete the elan interfaces
155 if (elanInfo == null) {
158 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
159 String elanInstanceName = elanInfo.getElanInstanceName();
160 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
161 InterfaceRemoveWorkerOnElan configWorker = new InterfaceRemoveWorkerOnElan(elanInstanceName, elanInfo,
162 interfaceName, interfaceInfo, false, this);
163 coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
166 public void removeElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo, String interfaceName,
167 InterfaceInfo interfaceInfo, boolean isInterfaceStateRemoved) {
168 String elanName = elanInfo.getElanInstanceName();
169 boolean isLastElanInterface = false;
170 long elanTag = elanInfo.getElanTag();
171 WriteTransaction tx = broker.newWriteOnlyTransaction();
172 WriteTransaction deleteFlowGroupTx = broker.newWriteOnlyTransaction();
173 Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, tx);
174 if (elanState == null) {
177 List<String> elanInterfaces = elanState.getElanInterfaces();
178 if (elanInterfaces.size() == 0) {
179 isLastElanInterface = true;
181 if (interfaceInfo != null) {
182 BigInteger dpId = interfaceInfo.getDpId();
183 DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName,
186 * If there are not elan ports, remove the unknown dmac, terminating
187 * service table flows, remote/local bc group
189 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
190 || dpnInterfaces.getInterfaces().isEmpty()) {
191 // No more Elan Interfaces in this DPN
192 LOG.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
193 removeDefaultTermFlow(dpId, elanInfo.getElanTag());
194 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, elanInfo.getElanTag());
195 removeEtreeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx);
196 removeElanBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
197 removeLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
198 removeEtreeBroadcastGrups(elanInfo, interfaceInfo, deleteFlowGroupTx);
199 if (ElanUtils.isVxlan(elanInfo)) {
200 unsetExternalTunnelTable(dpId, elanInfo);
203 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
206 futures.add(ElanUtils.waitForTransactionToComplete(tx));
207 futures.add(ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx));
208 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
209 InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(
210 interfaceName, elanInfo, interfaceInfo, isInterfaceStateRemoved, this, isLastElanInterface);
211 coordinator.enqueueJob(interfaceName, removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES);
214 private void removeEtreeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo,
215 WriteTransaction deleteFlowGroupTx) {
216 EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanInfo.getElanTag());
217 if (etreeLeafTag != null) {
218 long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
219 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, leafTag);
223 private void removeEtreeBroadcastGrups(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
224 WriteTransaction deleteFlowGroupTx) {
225 removeLeavesEtreeBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
226 removeLeavesLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
229 private void removeLeavesLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
230 WriteTransaction deleteFlowGroupTx) {
231 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
232 if (etreeInstance != null) {
233 BigInteger dpnId = interfaceInfo.getDpId();
234 long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeInstance.getEtreeLeafTagVal().getValue());
235 List<Bucket> listBuckets = new ArrayList<>();
237 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
238 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
239 MDSALUtil.buildBucketLists(listBuckets));
240 LOG.trace("deleted the localBroadCast Group:{}", group);
241 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
245 private void removeLeavesEtreeBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
246 WriteTransaction deleteFlowGroupTx) {
247 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
248 if (etreeInstance != null) {
249 long etreeTag = etreeInstance.getEtreeLeafTagVal().getValue();
252 List<Bucket> listBuckets = new ArrayList<>();
253 List<Action> listAction = new ArrayList<>();
254 listAction.add(new ActionInfo(ActionType.group,
255 new String[] { String.valueOf(ElanUtils.getEtreeLeafLocalBCGId(etreeTag)) }, ++actionKey)
257 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
258 MDSALUtil.WATCH_GROUP));
260 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, etreeTag));
261 BigInteger dpnId = interfaceInfo.getDpId();
262 long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeTag);
263 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
264 MDSALUtil.buildBucketLists(listBuckets));
265 LOG.trace("deleting the remoteBroadCast group:{}", group);
266 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
270 private Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
271 String elanName = elanInfo.getElanInstanceName();
272 Elan elanState = ElanUtils.getElanByName(broker, elanName);
273 if (elanState == null) {
276 List<String> elanInterfaces = elanState.getElanInterfaces();
277 elanInterfaces.remove(interfaceName);
278 if (elanInterfaces.isEmpty()) {
279 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
280 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
281 tx.delete(LogicalDatastoreType.OPERATIONAL,
282 ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
284 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName)
285 .setKey(new ElanKey(elanName)).build();
286 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName),
292 private void deleteElanInterfaceFromConfigDS(String interfaceName, WriteTransaction tx) {
293 // removing the ElanInterface from the config data_store if interface is
294 // not present in Interface config DS
295 if (interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName) == null) {
296 tx.delete(LogicalDatastoreType.CONFIGURATION,
297 ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
301 void removeEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo,
302 InterfaceInfo interfaceInfo, String interfaceName, boolean isInterfaceStateRemoved,
303 boolean isLastElanInterface) {
304 String elanName = elanInfo.getElanInstanceName();
305 WriteTransaction tx = broker.newWriteOnlyTransaction();
306 WriteTransaction deleteFlowGroupTx = broker.newWriteOnlyTransaction();
307 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils
308 .getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
309 LOG.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
310 if (interfaceInfo != null) {
311 Optional<ElanInterfaceMac> existingElanInterfaceMac = elanUtils.read(broker,
312 LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
313 if (existingElanInterfaceMac.isPresent()) {
314 List<PhysAddress> macAddresses = new ArrayList<>();
315 List<MacEntry> existingMacEntries = existingElanInterfaceMac.get().getMacEntry();
316 List<MacEntry> macEntries = new ArrayList<>();
317 if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
318 macEntries.addAll(existingMacEntries);
320 if (!macEntries.isEmpty()) {
321 for (MacEntry macEntry : macEntries) {
322 LOG.debug("removing the mac-entry:{} present on elanInterface:{}",
323 macEntry.getMacAddress().getValue(), interfaceName);
324 InstanceIdentifier<MacTable> elanMacTableId = ElanUtils.getElanMacTableOperationalDataPath(elanName);
325 Optional<MacTable> existingElanMacTable =
326 elanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanMacTableId);
327 if (!isLastElanInterface && existingElanMacTable.isPresent()) {
328 tx.delete(LogicalDatastoreType.OPERATIONAL,
329 ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
331 elanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, deleteFlowGroupTx);
332 macAddresses.add(macEntry.getMacAddress());
335 // Removing all those MACs from External Devices belonging
337 if (ElanUtils.isVxlan(elanInfo)) {
338 elanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
342 removeDefaultTermFlow(interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag());
343 removeFilterEqualsTable(elanInfo, interfaceInfo, deleteFlowGroupTx);
345 // Interface does not exist in ConfigDS, so lets remove everything
346 // about that interface related to Elan
347 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
348 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
349 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
350 for (MacEntry macEntry : macEntries) {
351 tx.delete(LogicalDatastoreType.OPERATIONAL,
352 ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
356 tx.delete(LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
357 if (!isInterfaceStateRemoved) {
358 unbindService(elanInfo, interfaceName, tx);
360 deleteElanInterfaceFromConfigDS(interfaceName, tx);
361 futures.add(ElanUtils.waitForTransactionToComplete(tx));
362 futures.add(ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx));
365 private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId,
366 String interfaceName, long elanTag, WriteTransaction tx) {
367 DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
368 if (dpnInterfaces != null) {
369 List<String> interfaceLists = dpnInterfaces.getInterfaces();
370 interfaceLists.remove(interfaceName);
372 if (interfaceLists == null || interfaceLists.isEmpty()) {
373 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
374 deleteElanDpnInterface(elanName, dpId, tx);
376 dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
379 return dpnInterfaces;
382 private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
383 List<DpnInterfaces> dpnInterfaces = elanUtils.getInvolvedDpnsInElan(elanName);
384 for (DpnInterfaces dpnInterface : dpnInterfaces) {
385 BigInteger currentDpId = dpnInterface.getDpId();
386 if (!currentDpId.equals(dpId)) {
387 for (String elanInterface : dpnInterface.getInterfaces()) {
388 ElanInterfaceMac macs = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
389 if (macs == null || macs.getMacEntry() == null) {
392 for (MacEntry mac : macs.getMacEntry()) {
393 removeTheMacFlowInTheDPN(dpId, elanTag, currentDpId, mac);
394 removeEtreeMacFlowInTheDPN(dpId, elanTag, currentDpId, mac);
401 private void removeEtreeMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) {
402 EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanTag);
403 if (etreeLeafTag != null) {
404 removeTheMacFlowInTheDPN(dpId, etreeLeafTag.getEtreeLeafTag().getValue(), currentDpId, mac);
408 private void removeTheMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) {
411 MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE,
412 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, currentDpId,
413 mac.getMacAddress().getValue(), elanTag)));
417 protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
418 // updating the static-Mac Entries for the existing elanInterface
419 String elanName = update.getElanInstanceName();
420 String interfaceName = update.getName();
421 List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
422 List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
423 if (updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
424 List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
425 if (existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
426 existingClonedPhyAddress.addAll(0, existingPhysAddress);
427 existingPhysAddress.removeAll(updatedPhysAddress);
428 updatedPhysAddress.removeAll(existingClonedPhyAddress);
429 // removing the PhyAddress which are not presented in the
431 for (PhysAddress physAddress : existingPhysAddress) {
432 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
435 // Adding the new PhysAddress which are presented in the updated
437 if (updatedPhysAddress.size() > 0) {
438 for (PhysAddress physAddress : updatedPhysAddress) {
439 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
440 Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
441 LogicalDatastoreType.OPERATIONAL, macId);
442 WriteTransaction tx = broker.newWriteOnlyTransaction();
443 if (existingMacEntry.isPresent()) {
444 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(
445 elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(),
448 elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(
449 ElanUtils.getElanInstanceByName(broker, elanName), interfaceName, physAddress, tx);
451 ElanUtils.waitForTransactionToComplete(tx);
454 } else if (existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
455 for (PhysAddress physAddress : existingPhysAddress) {
456 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
462 protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
463 String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
464 String interfaceName = elanInterfaceAdded.getName();
465 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
466 if (interfaceInfo == null) {
467 LOG.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
470 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(broker, elanInstanceName);
472 if (elanInstance == null) {
473 elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
474 .setDescription(elanInterfaceAdded.getDescription()).build();
475 // Add the ElanInstance in the Configuration data-store
476 WriteTransaction tx = broker.newWriteOnlyTransaction();
477 List<String> elanInterfaces = new ArrayList<>();
478 elanInterfaces.add(interfaceName);
479 ElanUtils.updateOperationalDataStore(broker, idManager,
480 elanInstance, elanInterfaces, tx);
481 ElanUtils.waitForTransactionToComplete(tx);
482 elanInstance = ElanUtils.getElanInstanceByName(broker, elanInstanceName);
485 Long elanTag = elanInstance.getElanTag();
486 // If elan tag is not updated, then put the elan interface into
487 // unprocessed entry map and entry. Let entries
488 // in this map get processed during ELAN update DCN.
489 if (elanTag == null) {
490 ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
491 if (elanInterfaces == null) {
492 elanInterfaces = new ConcurrentLinkedQueue<>();
494 elanInterfaces.add(elanInterfaceAdded);
495 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
498 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
499 InterfaceAddWorkerOnElan addWorker = new InterfaceAddWorkerOnElan(elanInstanceName, elanInterfaceAdded,
500 interfaceInfo, elanInstance, this);
501 coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
504 void handleunprocessedElanInterfaces(ElanInstance elanInstance) throws ElanException {
505 List<ListenableFuture<Void>> futures = new ArrayList<>();
506 Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
507 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
510 for (ElanInterface elanInterface : elanInterfaces) {
511 String interfaceName = elanInterface.getName();
512 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
513 addElanInterface(futures, elanInterface, interfaceInfo, elanInstance);
517 void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
518 WriteTransaction writeFlowGroupTx) throws ElanException {
519 ElanDpnInterfacesList elanDpnInterfacesList = elanUtils
520 .getElanDpnInterfacesList(elanInstance.getElanInstanceName());
521 List<DpnInterfaces> dpnInterfaceLists = null;
522 if (elanDpnInterfacesList != null) {
523 dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
525 if (dpnInterfaceLists == null) {
526 dpnInterfaceLists = new ArrayList<>();
528 for (DpnInterfaces dpnInterfaces : dpnInterfaceLists) {
529 if (dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
532 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
533 for (String remoteIf : remoteElanInterfaces) {
534 ElanInterfaceMac elanIfMac = elanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
535 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
536 if (elanIfMac == null) {
539 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
540 if (remoteMacEntries != null) {
541 for (MacEntry macEntry : remoteMacEntries) {
542 PhysAddress physAddress = macEntry.getMacAddress();
543 elanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
544 remoteInterface.getInterfaceTag(), elanInstance.getElanTag(), physAddress.getValue(),
545 elanInstance.getElanInstanceName(), writeFlowGroupTx, remoteIf);
552 void addElanInterface(List<ListenableFuture<Void>> futures, ElanInterface elanInterface,
553 InterfaceInfo interfaceInfo, ElanInstance elanInstance) throws ElanException {
554 Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
555 Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
556 Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
558 String interfaceName = elanInterface.getName();
559 String elanInstanceName = elanInterface.getElanInstanceName();
561 Elan elanInfo = ElanUtils.getElanByName(broker, elanInstanceName);
562 WriteTransaction tx = broker.newWriteOnlyTransaction();
563 if (elanInfo == null) {
564 List<String> elanInterfaces = new ArrayList<>();
565 elanInterfaces.add(interfaceName);
566 ElanUtils.updateOperationalDataStore(broker, idManager,
567 elanInstance, elanInterfaces, tx);
569 createElanStateList(elanInstanceName, interfaceName, tx);
571 boolean isFirstInterfaceInDpn = false;
572 // Specific actions to the DPN where the ElanInterface has been added,
573 // for example, programming the
574 // External tunnel table if needed or adding the ElanInterface to the
575 // DpnInterfaces in the operational DS.
576 BigInteger dpId = interfaceInfo != null ? dpId = interfaceInfo.getDpId() : null;
577 DpnInterfaces dpnInterfaces = null;
578 if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
579 InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils
580 .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
581 Optional<DpnInterfaces> existingElanDpnInterfaces = elanUtils.read(broker,
582 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
583 if (!existingElanDpnInterfaces.isPresent()) {
584 isFirstInterfaceInDpn = true;
585 // ELAN's 1st ElanInterface added to this DPN
586 dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
587 // The 1st ElanInterface in a DPN must program the Ext Tunnel
588 // table, but only if Elan has VNI
589 if (ElanUtils.isVxlan(elanInstance)) {
590 setExternalTunnelTable(dpId, elanInstance);
592 elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
594 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
595 elanInterfaces.add(interfaceName);
596 if (elanInterfaces.size() == 1) { // 1st dpn interface
597 elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
599 dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
603 // add code to install Local/Remote BC group, unknow DMAC entry,
604 // terminating service table flow entry
605 // call bindservice of interfacemanager to create ingress table flow
607 // Add interface to the ElanInterfaceForwardingEntires Container
608 createElanInterfaceTablesList(interfaceName, tx);
609 if (interfaceInfo != null) {
610 installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn, tx);
612 futures.add(ElanUtils.waitForTransactionToComplete(tx));
614 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
615 InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(interfaceName,
616 elanInterface, interfaceInfo, elanInstance, isFirstInterfaceInDpn, this);
617 coordinator.enqueueJob(interfaceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
620 void setupEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInstance,
621 ElanInterface elanInterface, InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn)
622 throws ElanException {
623 String elanInstanceName = elanInstance.getElanInstanceName();
624 String interfaceName = elanInterface.getName();
625 WriteTransaction tx = broker.newWriteOnlyTransaction();
626 BigInteger dpId = interfaceInfo.getDpId();
627 WriteTransaction writeFlowGroupTx = broker.newWriteOnlyTransaction();
628 installEntriesForElanInterface(elanInstance, interfaceInfo, isFirstInterfaceInDpn, tx, writeFlowGroupTx);
629 List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
630 if (staticMacAddresses != null) {
631 boolean isInterfaceOperational = isOperational(interfaceInfo);
632 for (PhysAddress physAddress : staticMacAddresses) {
633 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
634 Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
635 LogicalDatastoreType.OPERATIONAL, macId);
636 if (existingMacEntry.isPresent()) {
637 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(
638 elanInstanceName, interfaceName, existingMacEntry.get().getInterface(),
639 existingMacEntry.get(), tx);
641 elanForwardingEntriesHandler
642 .addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress, tx);
645 if (isInterfaceOperational) {
646 // Setting SMAC, DMAC, UDMAC in this DPN and also in other
648 elanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT,
649 physAddress.getValue(), writeFlowGroupTx);
653 if (isInterfaceOperational) {
654 // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop
656 elanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId,
660 futures.add(ElanUtils.waitForTransactionToComplete(tx));
661 futures.add(ElanUtils.waitForTransactionToComplete(writeFlowGroupTx));
664 protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName,
665 PhysAddress physAddress) {
666 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
667 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
668 Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
669 LogicalDatastoreType.OPERATIONAL, macId);
671 if (!existingMacEntry.isPresent()) {
675 MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName)
676 .setKey(new MacEntryKey(physAddress)).build();
677 WriteTransaction tx = broker.newWriteOnlyTransaction();
678 elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(
679 ElanUtils.getElanInstanceByName(broker, elanInstanceName), interfaceInfo, macEntry, tx);
680 elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName,
682 ElanUtils.waitForTransactionToComplete(tx);
685 private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
686 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName))
687 .child(MacEntry.class, new MacEntryKey(physAddress)).build();
690 private void installEntriesForElanInterface(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
691 boolean isFirstInterfaceInDpn, WriteTransaction tx, WriteTransaction writeFlowGroupTx)
692 throws ElanException {
693 if (!isOperational(interfaceInfo)) {
696 BigInteger dpId = interfaceInfo.getDpId();
697 elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, writeFlowGroupTx);
698 setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx);
699 if (isFirstInterfaceInDpn) {
700 // Terminating Service , UnknownDMAC Table.
701 setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
702 setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
703 // update the remote-DPNs remoteBC group entry with Tunnels
704 if (ElanUtils.isVxlan(elanInstance)) {
705 setElanBCGrouponOtherDpns(elanInstance, elanInstance.getElanTag().longValue(), dpId, writeFlowGroupTx);
708 * Install remote DMAC flow. This is required since this DPN is
709 * added later to the elan instance and remote DMACs of other
710 * interfaces in this elan instance are not present in the current
713 programRemoteDmacFlow(elanInstance, interfaceInfo, writeFlowGroupTx);
715 // bind the Elan service to the Interface
716 bindService(elanInstance,
717 ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceInfo.getInterfaceName()), tx);
720 public void installEntriesForFirstInterfaceonDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
721 DpnInterfaces dpnInterfaces, boolean isFirstInterfaceInDpn, WriteTransaction tx) {
722 if (!isOperational(interfaceInfo)) {
725 // LocalBroadcast Group creation with elan-Interfaces
726 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
727 if (isFirstInterfaceInDpn) {
728 LOG.trace("waitTimeForSyncInstall is {}", WAIT_TIME_FOR_SYNC_INSTALL);
729 BigInteger dpId = interfaceInfo.getDpId();
730 // RemoteBroadcast Group creation
732 Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
733 } catch (InterruptedException e1) {
734 LOG.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
736 setupElanBroadcastGroups(elanInfo, dpnInterfaces, dpId);
738 Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
739 } catch (InterruptedException e1) {
740 LOG.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
745 public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
746 WriteTransaction writeFlowGroupTx) {
747 int ifTag = interfaceInfo.getInterfaceTag();
748 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
749 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
750 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
751 getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
752 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
754 mdsalManager.addFlowToTx(interfaceInfo.getDpId(), flow, writeFlowGroupTx);
756 Flow flowEntry = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
757 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000 + ifTag), 10, elanInfo.getElanInstanceName(), 0,
758 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
759 getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
761 mdsalManager.addFlowToTx(interfaceInfo.getDpId(), flowEntry, writeFlowGroupTx);
764 public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
765 WriteTransaction deleteFlowGroupTx) {
766 int ifTag = interfaceInfo.getInterfaceTag();
767 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
768 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
769 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
770 getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
771 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
773 mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
775 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
776 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000 + ifTag), 10, elanInfo.getElanInstanceName(), 0,
777 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
778 getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
780 mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flowEntity, deleteFlowGroupTx);
783 private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo, int bucketKeyStart,
784 InterfaceInfo interfaceInfo, long elanTag) {
785 return getRemoteBCGroupBuckets(elanInfo, null, interfaceInfo.getDpId(), bucketKeyStart, elanTag);
788 private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId,
789 int bucketId, long elanTag) {
790 List<Bucket> listBucketInfo = new ArrayList<>();
791 ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
792 listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId, elanTag));
793 listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId, bucketId));
794 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId));
795 return listBucketInfo;
798 @SuppressWarnings("checkstyle:IllegalCatch")
799 private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
801 List<Bucket> listBucketInfo = new ArrayList<>();
802 if (elanDpns != null) {
803 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
804 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId
805 && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
807 List<Action> listActionInfo = elanUtils.getInternalTunnelItmEgressAction(dpnId,
808 dpnInterface.getDpId(), elanTag);
809 if (listActionInfo.isEmpty()) {
812 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
813 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
815 } catch (Exception ex) {
816 LOG.error("Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
817 dpnId, dpnInterface.getDpId(), ex);
822 return listBucketInfo;
825 private List<Bucket> getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns,
826 DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) {
827 DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId);
828 if (currDpnInterfaces == null || !elanUtils.isDpnPresent(currDpnInterfaces.getDpId())
829 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
830 return Collections.emptyList();
833 List<Bucket> listBucketInfo = new ArrayList<>();
834 for (String interfaceName : currDpnInterfaces.getInterfaces()) {
835 if (elanUtils.isExternal(interfaceName)) {
836 List<Action> listActionInfo = elanUtils.getExternalPortItmEgressAction(interfaceName);
837 if (!listActionInfo.isEmpty()) {
838 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
839 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
844 return listBucketInfo;
847 private DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) {
848 if (elanDpns != null) {
849 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
850 if (dpnInterface.getDpId() == dpnId) {
858 @SuppressWarnings("checkstyle:IllegalCatch")
859 private void setElanBCGrouponOtherDpns(ElanInstance elanInfo, long elanTag, BigInteger dpId, WriteTransaction tx) {
860 long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
861 List<Bucket> listBucket = new ArrayList<>();
863 ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
864 if (elanDpns != null) {
865 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
866 for (DpnInterfaces dpnInterface : dpnInterfaceses) {
867 List<Bucket> remoteListBucketInfo = new ArrayList<>();
868 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpId)
869 && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
870 List<Action> listAction = new ArrayList<>();
872 listAction.add(new ActionInfo(ActionType.group,
873 new String[] { String.valueOf(ElanUtils.getElanLocalBCGId(elanTag)) }, ++actionKey)
875 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId,
876 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
878 remoteListBucketInfo.addAll(listBucket);
879 for (DpnInterfaces otherFes : dpnInterfaceses) {
880 if (elanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
881 && otherFes.getInterfaces() != null && !otherFes.getInterfaces().isEmpty()) {
883 List<Action> remoteListActionInfo = elanUtils.getInternalTunnelItmEgressAction(
884 dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
885 if (!remoteListActionInfo.isEmpty()) {
887 .add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT,
888 bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
891 } catch (Exception ex) {
892 LOG.error("setElanBCGrouponOtherDpns failed due to Exception caught; "
893 + "Logical Group Interface not found between source Dpn - {}, "
894 + "destination Dpn - {} ", dpnInterface.getDpId(), otherFes.getDpId(), ex);
899 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpId,
901 remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
903 if (remoteListBucketInfo.size() == 0) {
904 LOG.debug("No ITM is present on Dpn - {} ", dpnInterface.getDpId());
907 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
908 MDSALUtil.buildBucketLists(remoteListBucketInfo));
909 mdsalManager.addGroupToTx(dpnInterface.getDpId(), group, tx);
916 * Returns the bucket info with the given interface as the only bucket.
918 private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
919 return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart,
920 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
923 private List<MatchInfo> buildMatchesForVni(Long vni) {
924 List<MatchInfo> mkMatches = new ArrayList<>();
925 MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(vni) });
926 mkMatches.add(match);
930 private List<Instruction> getInstructionsForOutGroup(long groupId) {
931 List<Instruction> mkInstructions = new ArrayList<>();
932 List<Action> actions = new ArrayList<>();
933 actions.add(new ActionInfo(ActionType.group, new String[] { Long.toString(groupId) }).buildAction());
934 mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
935 return mkInstructions;
938 private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
939 List<MatchInfo> mkMatches = new ArrayList<>();
941 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
942 ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG }));
947 * Builds the list of instructions to be installed in the External Tunnel
948 * table (38), which so far consists in writing the elanTag in metadata and
949 * send packet to the new DHCP table.
952 * elanTag to be written in metadata when flow is selected
953 * @return the instructions ready to be installed in a flow
955 private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
956 List<InstructionInfo> mkInstructions = new ArrayList<>();
957 mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
958 new BigInteger[] { ElanUtils.getElanMetadataLabel(elanTag), ElanUtils.getElanMetadataMask() }));
959 // TODO: We should point to SMAC or DMAC depending on a configuration
960 // property to enable
962 mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.ELAN_DMAC_TABLE }));
964 return mkInstructions;
967 // Install DMAC entry on dst DPN
968 public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId)
969 throws ElanException {
970 String interfaceName = interfaceInfo.getInterfaceName();
971 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
972 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
973 WriteTransaction writeFlowTx = broker.newWriteOnlyTransaction();
974 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
975 for (MacEntry macEntry : macEntries) {
976 PhysAddress physAddress = macEntry.getMacAddress();
977 elanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue(),
980 writeFlowTx.submit();
984 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
985 setupElanBroadcastGroups(elanInfo, null, dpnId);
988 public void setupElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
989 setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
990 setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
993 public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
994 List<Bucket> listBucket = new ArrayList<>();
997 Long elanTag = elanInfo.getElanTag();
998 List<Action> listAction = new ArrayList<>();
999 listAction.add(new ActionInfo(ActionType.group,
1000 new String[] { String.valueOf(ElanUtils.getElanLocalBCGId(elanTag)) }, ++actionKey).buildAction());
1001 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
1002 MDSALUtil.WATCH_GROUP));
1004 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
1005 elanInfo.getElanTag());
1006 listBucket.addAll(listBucketInfoRemote);
1007 long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
1008 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1009 MDSALUtil.buildBucketLists(listBucket));
1010 LOG.trace("Installing the remote BroadCast Group:{}", group);
1011 mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
1014 public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
1015 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1016 if (etreeInstance != null) {
1017 long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
1018 List<Bucket> listBucket = new ArrayList<>();
1021 List<Action> listAction = new ArrayList<>();
1022 listAction.add(new ActionInfo(ActionType.group,
1023 new String[] { String.valueOf(ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag)) }, ++actionKey)
1025 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
1026 MDSALUtil.WATCH_GROUP));
1028 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
1030 listBucket.addAll(listBucketInfoRemote);
1031 long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
1032 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1033 MDSALUtil.buildBucketLists(listBucket));
1034 LOG.trace("Installing the remote BroadCast Group:{}", group);
1035 mdsalManager.syncInstallGroup(dpnId, group,
1036 ElanConstants.DELAY_TIME_IN_MILLISECOND);
1040 private void createDropBucket(List<Bucket> listBucket) {
1041 List<Action> actionsInfos = new ArrayList<>();
1042 actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}).buildAction());
1043 Bucket dropBucket = MDSALUtil.buildBucket(actionsInfos, MDSALUtil.GROUP_WEIGHT, 0, MDSALUtil.WATCH_PORT,
1044 MDSALUtil.WATCH_GROUP);
1045 listBucket.add(dropBucket);
1048 public void setupLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1049 InterfaceInfo interfaceInfo) {
1050 setupStandardLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo);
1051 setupLeavesLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo);
1054 public void setupStandardLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1055 InterfaceInfo interfaceInfo) {
1056 List<Bucket> listBucket = new ArrayList<>();
1058 long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag());
1060 List<String> interfaces = new ArrayList<>();
1061 if (newDpnInterface != null) {
1062 interfaces = newDpnInterface.getInterfaces();
1064 for (String ifName : interfaces) {
1065 // In case if there is a InterfacePort in the cache which is not in
1066 // operational state, skip processing it
1067 InterfaceInfo ifInfo = interfaceManager
1068 .getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
1069 if (!isOperational(ifInfo)) {
1073 if (!elanUtils.isExternal(ifName)) {
1074 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId,
1075 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1080 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1081 MDSALUtil.buildBucketLists(listBucket));
1082 LOG.trace("installing the localBroadCast Group:{}", group);
1083 mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group,
1084 ElanConstants.DELAY_TIME_IN_MILLISECOND);
1087 private void setupLeavesLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1088 InterfaceInfo interfaceInfo) {
1089 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1090 if (etreeInstance != null) {
1091 List<Bucket> listBucket = new ArrayList<>();
1094 List<String> interfaces = new ArrayList<>();
1095 if (newDpnInterface != null) {
1096 interfaces = newDpnInterface.getInterfaces();
1098 for (String ifName : interfaces) {
1099 // In case if there is a InterfacePort in the cache which is not
1101 // operational state, skip processing it
1102 InterfaceInfo ifInfo = interfaceManager
1103 .getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
1104 if (!isOperational(ifInfo)) {
1108 if (!elanUtils.isExternal(ifName)) {
1109 // only add root interfaces
1110 bucketId = addInterfaceIfRootInterface(bucketId, ifName, listBucket, ifInfo);
1114 if (listBucket.size() == 0) { // No Buckets
1115 createDropBucket(listBucket);
1118 long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
1119 long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag);
1120 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1121 MDSALUtil.buildBucketLists(listBucket));
1122 LOG.trace("installing the localBroadCast Group:{}", group);
1123 mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group,
1124 ElanConstants.DELAY_TIME_IN_MILLISECOND);
1128 private int addInterfaceIfRootInterface(int bucketId, String ifName, List<Bucket> listBucket,
1129 InterfaceInfo ifInfo) {
1130 EtreeInterface etreeInterface = ElanUtils.getEtreeInterfaceByElanInterfaceName(broker, ifName);
1131 if (etreeInterface != null && etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1132 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId,
1133 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1139 public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
1140 WriteTransaction deleteFlowGroupTx) {
1141 BigInteger dpnId = interfaceInfo.getDpId();
1142 long groupId = ElanUtils.getElanLocalBCGId(elanInfo.getElanTag());
1143 List<Bucket> listBuckets = new ArrayList<>();
1145 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
1146 // listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1,
1148 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1149 MDSALUtil.buildBucketLists(listBuckets));
1150 LOG.trace("deleted the localBroadCast Group:{}", group);
1151 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
1154 public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
1155 WriteTransaction deleteFlowGroupTx) {
1158 Long elanTag = elanInfo.getElanTag();
1159 List<Bucket> listBuckets = new ArrayList<>();
1160 List<Action> listAction = new ArrayList<>();
1161 listAction.add(new ActionInfo(ActionType.group,
1162 new String[] { String.valueOf(ElanUtils.getElanLocalBCGId(elanTag)) }, ++actionKey).buildAction());
1163 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
1164 MDSALUtil.WATCH_GROUP));
1166 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, elanInfo.getElanTag()));
1167 BigInteger dpnId = interfaceInfo.getDpId();
1168 long groupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag());
1169 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1170 MDSALUtil.buildBucketLists(listBuckets));
1171 LOG.trace("deleting the remoteBroadCast group:{}", group);
1172 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
1176 * Installs a flow in the External Tunnel table consisting in translating
1177 * the VNI retrieved from the packet that came over a tunnel with a TOR into
1178 * elanTag that will be used later in the ELANs pipeline.
1185 public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
1186 long elanTag = elanInfo.getElanTag();
1187 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.EXTERNAL_TUNNEL_TABLE,
1188 getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag), 5, // prio
1189 elanInfo.getElanInstanceName(), // flowName
1192 ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
1193 buildMatchesForVni(elanInfo.getSegmentationId()), getInstructionsExtTunnelTable(elanTag));
1195 mdsalManager.installFlow(flowEntity);
1199 * Removes, from External Tunnel table, the flow that translates from VNI to
1200 * elanTag. Important: ensure this method is only called whenever there is
1201 * no other ElanInterface in the specified DPN
1204 * DPN whose Ext Tunnel table is going to be modified
1206 * holds the elanTag needed for selecting the flow to be removed
1208 public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
1209 // TODO: Use DataStoreJobCoordinator in order to avoid that removing the
1210 // last ElanInstance plus
1211 // adding a new one does (almost at the same time) are executed in that
1214 String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
1215 FlowEntity flowEntity = new FlowEntity(dpnId);
1216 flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
1217 flowEntity.setFlowId(flowId);
1218 mdsalManager.removeFlow(flowEntity);
1221 public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
1222 setupTerminateServiceTable(elanInfo, dpId, elanInfo.getElanTag(), writeFlowGroupTx);
1223 setupEtreeTerminateServiceTable(elanInfo, dpId, writeFlowGroupTx);
1226 public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1227 WriteTransaction writeFlowGroupTx) {
1228 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1229 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag), 5,
1230 String.format("%s:%d", "ITM Flow Entry ", elanTag), 0, 0,
1231 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)),
1232 ElanUtils.getTunnelMatchesForServiceId((int) elanTag),
1233 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag)));
1235 mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
1238 private void setupEtreeTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId,
1239 WriteTransaction writeFlowGroupTx) {
1240 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1241 if (etreeInstance != null) {
1242 setupTerminateServiceTable(elanInfo, dpId, etreeInstance.getEtreeLeafTagVal().getValue(), writeFlowGroupTx);
1246 public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
1247 long elanTag = elanInfo.getElanTag();
1248 installLocalUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
1249 installRemoteUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
1250 setupEtreeUnknownDMacTable(elanInfo, dpId, elanTag, writeFlowGroupTx);
1253 private void setupEtreeUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1254 WriteTransaction writeFlowGroupTx) {
1255 EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanTag);
1256 if (etreeLeafTag != null) {
1257 long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
1258 installRemoteUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
1259 installLocalUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
1263 private void installLocalUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1264 WriteTransaction writeFlowGroupTx) {
1265 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1266 getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
1267 /* SH flag */false),
1268 5, elanInfo.getElanInstanceName(), 0, 0,
1269 ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
1270 getMatchesForElanTag(elanTag, /* SH flag */false),
1271 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGId(elanTag)));
1273 mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
1276 private void installRemoteUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1277 WriteTransaction writeFlowGroupTx) {
1278 // only if ELAN can connect to external network, perform the following
1279 if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) {
1280 Flow flowEntity2 = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1281 getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
1283 5, elanInfo.getElanInstanceName(), 0, 0,
1284 ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
1285 getMatchesForElanTag(elanTag, /* SH flag */true),
1286 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag)));
1287 mdsalManager.addFlowToTx(dpId, flowEntity2, writeFlowGroupTx);
1292 private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo, WriteTransaction deleteFlowGroupTx,
1294 Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1295 elanTag, /* SH flag */ false))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE).build();
1296 mdsalManager.removeFlowToTx(dpId, flow, deleteFlowGroupTx);
1298 if (ElanUtils.isVxlan(elanInfo)) {
1299 Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1300 elanTag, /* SH flag */ true))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE)
1302 mdsalManager.removeFlowToTx(dpId, flow2, deleteFlowGroupTx);
1306 private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
1307 elanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
1310 private void bindService(ElanInstance elanInfo, ElanInterface elanInterface, WriteTransaction tx) {
1311 if (isStandardElanService(elanInterface)) {
1312 bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), tx);
1313 } else { // Etree service
1314 bindEtreeService(elanInfo, elanInterface, tx);
1318 private void bindElanService(long elanTag, String elanInstanceName, String interfaceName, WriteTransaction tx) {
1319 int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
1320 int instructionKey = 0;
1321 List<Instruction> instructions = new ArrayList<>();
1322 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanTag),
1323 MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
1324 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ELAN_SMAC_TABLE, ++instructionKey));
1325 short elanServiceIndex = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX);
1326 BoundServices serviceInfo = ElanUtils.getBoundServices(
1327 String.format("%s.%s.%s", "vpn", elanInstanceName, interfaceName), elanServiceIndex,
1328 priority, NwConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
1329 tx.put(LogicalDatastoreType.CONFIGURATION,
1330 ElanUtils.buildServiceId(interfaceName, elanServiceIndex), serviceInfo, true);
1333 private void bindEtreeService(ElanInstance elanInfo, ElanInterface elanInterface, WriteTransaction tx) {
1334 if (elanInterface.getAugmentation(EtreeInterface.class).getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1335 bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), tx);
1337 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1338 if (etreeInstance == null) {
1339 LOG.error("EtreeInterface " + elanInterface.getName() + " is associated with a non EtreeInstance: "
1340 + elanInfo.getElanInstanceName());
1342 bindElanService(etreeInstance.getEtreeLeafTagVal().getValue(), elanInfo.getElanInstanceName(),
1343 elanInterface.getName(), tx);
1348 private boolean isStandardElanService(ElanInterface elanInterface) {
1349 return elanInterface.getAugmentation(EtreeInterface.class) == null;
1352 private boolean isStandardElanService(ElanInstance elanInstance) {
1353 return elanInstance.getAugmentation(EtreeInstance.class) == null;
1356 private void unbindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
1357 tx.delete(LogicalDatastoreType.CONFIGURATION, ElanUtils.buildServiceId(interfaceName,
1358 ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX)));
1361 private String getFlowRef(long tableId, long elanTag) {
1362 return new StringBuffer().append(tableId).append(elanTag).toString();
1365 private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) {
1366 return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString();
1369 private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
1370 List<Action> listAction = new ArrayList<>();
1372 listAction.add(new ActionInfo(ActionType.set_field_tunnel_id,
1373 new BigInteger[] { BigInteger.valueOf(interfaceInfo.getInterfaceTag()) }, actionKey).buildAction());
1375 listAction.add(new ActionInfo(ActionType.nx_resubmit,
1376 new String[] { String.valueOf(NwConstants.ELAN_FILTER_EQUALS_TABLE) }, actionKey).buildAction());
1380 private DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId,
1381 List<String> interfaceNames, WriteTransaction tx) {
1382 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
1383 .setKey(new DpnInterfacesKey(dpId)).build();
1384 tx.put(LogicalDatastoreType.OPERATIONAL,
1385 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, true);
1386 return dpnInterface;
1390 * Delete elan dpn interface from operational DS.
1392 * @param elanInstanceName
1393 * the elan instance name
1397 private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId, WriteTransaction tx) {
1398 tx.delete(LogicalDatastoreType.OPERATIONAL,
1399 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
1402 private DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId,
1403 WriteTransaction tx) {
1404 List<String> interfaceNames = new ArrayList<>();
1405 interfaceNames.add(interfaceName);
1406 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
1407 .setKey(new DpnInterfacesKey(dpId)).build();
1408 tx.put(LogicalDatastoreType.OPERATIONAL,
1409 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, true);
1410 return dpnInterface;
1413 private void createElanInterfaceTablesList(String interfaceName, WriteTransaction tx) {
1414 InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils
1415 .getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1416 Optional<ElanInterfaceMac> interfaceMacTables = elanUtils.read(broker,
1417 LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
1418 // Adding new Elan Interface Port to the operational DataStore without
1419 // Static-Mac Entries..
1420 if (!interfaceMacTables.isPresent()) {
1421 ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName)
1422 .setKey(new ElanInterfaceMacKey(interfaceName)).build();
1423 tx.put(LogicalDatastoreType.OPERATIONAL,
1424 ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), elanInterfaceMacTable,
1429 private void createElanStateList(String elanInstanceName, String interfaceName, WriteTransaction tx) {
1430 InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
1431 Optional<Elan> elanInterfaceLists = elanUtils.read(broker,
1432 LogicalDatastoreType.OPERATIONAL, elanInstance);
1433 // Adding new Elan Interface Port to the operational DataStore without
1434 // Static-Mac Entries..
1435 if (elanInterfaceLists.isPresent()) {
1436 List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
1437 if (interfaceLists == null) {
1438 interfaceLists = new ArrayList<>();
1440 interfaceLists.add(interfaceName);
1441 Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists)
1442 .setKey(new ElanKey(elanInstanceName)).build();
1443 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName),
1448 private boolean isOperational(InterfaceInfo interfaceInfo) {
1449 if (interfaceInfo == null) {
1452 return interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED;
1455 public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) throws ElanException {
1456 ElanDpnInterfaces dpnInterfaceLists = elanUtils.getElanDpnInterfacesList();
1457 if (dpnInterfaceLists == null) {
1460 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1461 for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1463 String elanName = elanDpns.getElanInstanceName();
1464 List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
1465 if (dpnInterfaces == null) {
1468 for (DpnInterfaces dpnIf : dpnInterfaces) {
1469 if (dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
1474 LOG.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
1475 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, elanName);
1476 // update Remote BC Group
1477 setupElanBroadcastGroups(elanInfo, srcDpId);
1479 DpnInterfaces dpnInterface = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dstDpId);
1480 Set<String> interfaceLists = new HashSet<>();
1481 interfaceLists.addAll(dpnInterface.getInterfaces());
1482 for (String ifName : interfaceLists) {
1483 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
1484 if (isOperational(interfaceInfo)) {
1485 installDMacAddressTables(elanInfo, interfaceInfo, srcDpId);
1494 * Handle external tunnel state event.
1496 * @param externalTunnel
1497 * the external tunnel
1500 * @throws ElanException in case of issues creating the flow objects
1502 public void handleExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) throws ElanException {
1503 if (!validateExternalTunnelStateEvent(externalTunnel, intrf)) {
1506 // dpId/externalNodeId will be available either in source or destination
1507 // based on the tunnel end point
1508 BigInteger dpId = null;
1509 NodeId externalNodeId = null;
1510 if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
1511 dpId = new BigInteger(externalTunnel.getSourceDevice());
1512 externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
1513 } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
1514 dpId = new BigInteger(externalTunnel.getDestinationDevice());
1515 externalNodeId = new NodeId(externalTunnel.getSourceDevice());
1517 if (dpId == null || externalNodeId == null) {
1518 LOG.error("Dp ID / externalNodeId not found in external tunnel {}", externalTunnel);
1522 ElanDpnInterfaces dpnInterfaceLists = elanUtils.getElanDpnInterfacesList();
1523 if (dpnInterfaceLists == null) {
1526 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1527 for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1528 String elanName = elanDpns.getElanInstanceName();
1529 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(broker, elanName);
1531 DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1532 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
1533 || dpnInterfaces.getInterfaces().isEmpty()) {
1536 LOG.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
1538 setupElanBroadcastGroups(elanInfo, dpId);
1539 // install L2gwDevices local macs in dpn.
1540 elanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo, intrf.getName());
1541 // Install dpn macs on external device
1542 elanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
1545 LOG.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
1549 * Validate external tunnel state event.
1551 * @param externalTunnel
1552 * the external tunnel
1555 * @return true, if successful
1557 private boolean validateExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1558 if (intrf.getOperStatus() == Interface.OperStatus.Up) {
1559 String srcDevice = externalTunnel.getDestinationDevice();
1560 String destDevice = externalTunnel.getSourceDevice();
1561 ExternalTunnel otherEndPointExtTunnel = elanUtils.getExternalTunnel(srcDevice, destDevice,
1562 LogicalDatastoreType.CONFIGURATION);
1563 if (LOG.isTraceEnabled()) {
1564 LOG.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
1565 otherEndPointExtTunnel);
1567 if (otherEndPointExtTunnel != null) {
1568 boolean otherEndPointInterfaceOperational = ElanUtils.isInterfaceOperational(
1569 otherEndPointExtTunnel.getTunnelInterfaceName(), broker);
1570 if (otherEndPointInterfaceOperational) {
1573 LOG.debug("Other end [{}] of the external tunnel is not yet UP for {}",
1574 otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
1581 private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int lportTag) {
1582 List<MatchInfo> mkMatches = new ArrayList<>();
1583 // Matching metadata
1584 mkMatches.add(new MatchInfo(MatchFieldType.metadata,
1585 new BigInteger[] { MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1586 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(lportTag) }));
1590 private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int lportTag) {
1591 List<MatchInfo> mkMatches = new ArrayList<>();
1592 // Matching metadata
1593 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(lportTag) }));
1597 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
1598 List<DpnInterfaces> dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
1602 for (DpnInterfaces dpn : dpns) {
1603 setupElanBroadcastGroups(elanInfo, dpn.getDpId());
1607 public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
1609 List<Bucket> listBucketInfo = new ArrayList<>();
1610 ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
1611 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
1612 for (L2GatewayDevice device : map.values()) {
1613 String interfaceName = elanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
1614 device.getHwvtepNodeId());
1615 if (interfaceName == null) {
1618 List<Action> listActionInfo = elanUtils.buildTunnelItmEgressActions(interfaceName,
1619 elanInfo.getSegmentationId());
1620 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
1621 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1624 return listBucketInfo;
1628 protected ElanInterfaceManager getDataTreeChangeListener() {