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.l2gw.utils.ElanL2GatewayUtils;
46 import org.opendaylight.netvirt.elan.utils.ElanConstants;
47 import org.opendaylight.netvirt.elan.utils.ElanForwardingEntriesHandler;
48 import org.opendaylight.netvirt.elan.utils.ElanUtils;
49 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
50 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTableKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
90 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
91 import org.slf4j.Logger;
92 import org.slf4j.LoggerFactory;
95 * Class in charge of handling creations, modifications and removals of
98 * @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 final ElanL2GatewayUtils elanL2GatewayUtils;
111 private final ElanUtils elanUtils;
113 private static final long waitTimeForSyncInstall = Long.getLong("wait.time.sync.install", 300L);
115 private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces = new ConcurrentHashMap<>();
117 private static final Logger logger = 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 final ElanL2GatewayUtils elanL2GatewayUtils, ElanUtils elanUtils) {
125 super(ElanInterface.class, ElanInterfaceManager.class);
126 this.broker = dataBroker;
127 this.idManager = managerService;
128 this.mdsalManager = mdsalApiManager;
129 this.interfaceManager = interfaceManager;
130 this.elanForwardingEntriesHandler = elanForwardingEntriesHandler;
131 this.elanL2GatewayUtils = elanL2GatewayUtils;
132 this.elanUtils = elanUtils;
136 registerListener(LogicalDatastoreType.CONFIGURATION, broker);
140 protected InstanceIdentifier<ElanInterface> getWildCardPath() {
141 return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
145 protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
146 String interfaceName = del.getName();
147 ElanInstance elanInfo = elanUtils.getElanInstanceByName(del.getElanInstanceName());
149 * Handling in case the elan instance is deleted.If the Elan instance is
150 * deleted, there is no need to explicitly delete the elan interfaces
152 if (elanInfo == null) {
155 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
156 String elanInstanceName = elanInfo.getElanInstanceName();
157 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
158 InterfaceRemoveWorkerOnElan configWorker = new InterfaceRemoveWorkerOnElan(elanInstanceName, elanInfo,
159 interfaceName, interfaceInfo, false, this);
160 coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
163 public void removeElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo,
164 boolean isInterfaceStateRemoved) {
165 String elanName = elanInfo.getElanInstanceName();
166 boolean isLastElanInterface = false;
167 long elanTag = elanInfo.getElanTag();
168 WriteTransaction tx = broker.newWriteOnlyTransaction();
169 WriteTransaction deleteFlowGroupTx = broker.newWriteOnlyTransaction();
170 Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, tx);
171 if (elanState == null) {
174 List<String> elanInterfaces = elanState.getElanInterfaces();
175 if (elanInterfaces.size() == 0) {
176 isLastElanInterface = true;
178 if (interfaceInfo != null) {
179 BigInteger dpId = interfaceInfo.getDpId();
180 DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName,
183 * If there are not elan ports, remove the unknown dmac, terminating
184 * service table flows, remote/local bc group
186 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
187 || dpnInterfaces.getInterfaces().isEmpty()) {
188 // No more Elan Interfaces in this DPN
189 logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
190 removeDefaultTermFlow(dpId, elanInfo.getElanTag());
191 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, elanInfo.getElanTag());
192 removeEtreeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx);
193 removeElanBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
194 removeLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
195 removeEtreeBroadcastGrups(elanInfo, interfaceInfo, deleteFlowGroupTx);
196 if (ElanUtils.isVxlan(elanInfo)) {
197 unsetExternalTunnelTable(dpId, elanInfo);
200 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
203 futures.add(ElanUtils.waitForTransactionToComplete(tx));
204 futures.add(ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx));
205 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
206 InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(
207 interfaceName, elanInfo, interfaceInfo, isInterfaceStateRemoved, this, isLastElanInterface);
208 coordinator.enqueueJob(interfaceName, removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES);
211 private void removeEtreeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo,
212 WriteTransaction deleteFlowGroupTx) {
213 EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanInfo.getElanTag());
214 if (etreeLeafTag != null) {
215 long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
216 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, leafTag);
220 private void removeEtreeBroadcastGrups(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
221 WriteTransaction deleteFlowGroupTx) {
222 removeLeavesEtreeBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
223 removeLeavesLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
226 private void removeLeavesLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
227 WriteTransaction deleteFlowGroupTx) {
228 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
229 if (etreeInstance != null) {
230 BigInteger dpnId = interfaceInfo.getDpId();
231 long groupId = ElanUtils.getEtreeLeafLocalBCGID(etreeInstance.getEtreeLeafTagVal().getValue());
232 List<Bucket> listBuckets = new ArrayList<>();
234 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
235 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
236 MDSALUtil.buildBucketLists(listBuckets));
237 logger.trace("deleted the localBroadCast Group:{}", group);
238 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
242 private void removeLeavesEtreeBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
243 WriteTransaction deleteFlowGroupTx) {
244 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
245 if (etreeInstance != null) {
246 long etreeTag = etreeInstance.getEtreeLeafTagVal().getValue();
249 List<Bucket> listBuckets = new ArrayList<>();
250 List<Action> listAction = new ArrayList<Action>();
251 listAction.add((new ActionInfo(ActionType.group,
252 new String[] { String.valueOf(ElanUtils.getEtreeLeafLocalBCGID(etreeTag)) }, ++actionKey))
254 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
255 MDSALUtil.WATCH_GROUP));
257 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, etreeTag));
258 BigInteger dpnId = interfaceInfo.getDpId();
259 long groupId = ElanUtils.getEtreeLeafRemoteBCGID(etreeTag);
260 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
261 MDSALUtil.buildBucketLists(listBuckets));
262 logger.trace("deleting the remoteBroadCast group:{}", group);
263 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
267 private Elan removeElanStateForInterface(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
268 String elanName = elanInfo.getElanInstanceName();
269 Elan elanState = elanUtils.getElanByName(elanName);
270 if (elanState == null) {
273 List<String> elanInterfaces = elanState.getElanInterfaces();
274 elanInterfaces.remove(interfaceName);
275 if (elanInterfaces.isEmpty()) {
276 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
277 tx.delete(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
278 tx.delete(LogicalDatastoreType.OPERATIONAL,
279 ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
281 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName)
282 .setKey(new ElanKey(elanName)).build();
283 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName),
289 private void deleteElanInterfaceFromConfigDS(String interfaceName, WriteTransaction tx) {
290 // removing the ElanInterface from the config data_store if interface is
291 // not present in Interface config DS
292 if (interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName) == null) {
293 tx.delete(LogicalDatastoreType.CONFIGURATION,
294 ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
298 void removeEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo, InterfaceInfo interfaceInfo, String interfaceName,
299 boolean isInterfaceStateRemoved, boolean isLastElanInterface) {
300 String elanName = elanInfo.getElanInstanceName();
301 WriteTransaction tx = broker.newWriteOnlyTransaction();
302 WriteTransaction deleteFlowGroupTx = broker.newWriteOnlyTransaction();
303 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils
304 .getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
305 logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
306 if (interfaceInfo != null) {
307 Optional<ElanInterfaceMac> existingElanInterfaceMac = elanUtils.read(broker,
308 LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
309 if (existingElanInterfaceMac.isPresent()) {
310 List<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
311 List<MacEntry> existingMacEntries = existingElanInterfaceMac.get().getMacEntry();
312 List<MacEntry> macEntries = new ArrayList<>();
313 if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
314 macEntries.addAll(existingMacEntries);
316 if (!macEntries.isEmpty()) {
317 for (MacEntry macEntry : macEntries) {
318 logger.debug("removing the mac-entry:{} present on elanInterface:{}",
319 macEntry.getMacAddress().getValue(), interfaceName);
320 if (!isLastElanInterface) {
321 tx.delete(LogicalDatastoreType.OPERATIONAL,
322 ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
324 elanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry, deleteFlowGroupTx);
325 macAddresses.add(macEntry.getMacAddress());
328 // Removing all those MACs from External Devices belonging
330 if (ElanUtils.isVxlan(elanInfo)) {
331 elanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
335 removeDefaultTermFlow(interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag());
336 removeFilterEqualsTable(elanInfo, interfaceInfo, deleteFlowGroupTx);
338 // Interface does not exist in ConfigDS, so lets remove everything
339 // about that interface related to Elan
340 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
341 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
342 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
343 for (MacEntry macEntry : macEntries) {
344 tx.delete(LogicalDatastoreType.OPERATIONAL,
345 ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
349 tx.delete(LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
350 if (!isInterfaceStateRemoved) {
351 unbindService(elanInfo, interfaceName, tx);
353 deleteElanInterfaceFromConfigDS(interfaceName, tx);
354 futures.add(ElanUtils.waitForTransactionToComplete(tx));
355 futures.add(ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx));
358 private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId,
359 String interfaceName, long elanTag, WriteTransaction tx) {
360 DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
361 if (dpnInterfaces != null) {
362 List<String> interfaceLists = dpnInterfaces.getInterfaces();
363 interfaceLists.remove(interfaceName);
365 if (interfaceLists == null || interfaceLists.isEmpty()) {
366 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
367 deleteElanDpnInterface(elanName, dpId, tx);
369 dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
372 return dpnInterfaces;
375 private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
376 List<DpnInterfaces> dpnInterfaces = elanUtils.getInvolvedDpnsInElan(elanName);
377 for (DpnInterfaces dpnInterface : dpnInterfaces) {
378 BigInteger currentDpId = dpnInterface.getDpId();
379 if (!currentDpId.equals(dpId)) {
380 for (String elanInterface : dpnInterface.getInterfaces()) {
381 ElanInterfaceMac macs = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
382 if (macs == null || macs.getMacEntry() == null) {
385 for (MacEntry mac : macs.getMacEntry()) {
386 removeTheMacFlowInTheDPN(dpId, elanTag, currentDpId, mac);
387 removeEtreeMacFlowInTheDPN(dpId, elanTag, currentDpId, mac);
394 private void removeEtreeMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) {
395 EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanTag);
396 if (etreeLeafTag != null) {
397 removeTheMacFlowInTheDPN(dpId, etreeLeafTag.getEtreeLeafTag().getValue(), currentDpId, mac);
401 private void removeTheMacFlowInTheDPN(BigInteger dpId, long elanTag, BigInteger currentDpId, MacEntry mac) {
404 MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE,
405 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, currentDpId,
406 mac.getMacAddress().getValue(), elanTag)));
410 protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
411 // updating the static-Mac Entries for the existing elanInterface
412 String elanName = update.getElanInstanceName();
413 String interfaceName = update.getName();
414 List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
415 List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
416 if (updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
417 List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
418 if (existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
419 existingClonedPhyAddress.addAll(0, existingPhysAddress);
420 existingPhysAddress.removeAll(updatedPhysAddress);
421 updatedPhysAddress.removeAll(existingClonedPhyAddress);
422 // removing the PhyAddress which are not presented in the
424 for (PhysAddress physAddress : existingPhysAddress) {
425 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
428 // Adding the new PhysAddress which are presented in the updated
430 if (updatedPhysAddress.size() > 0) {
431 for (PhysAddress physAddress : updatedPhysAddress) {
432 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
433 Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
434 LogicalDatastoreType.OPERATIONAL, macId);
435 WriteTransaction tx = broker.newWriteOnlyTransaction();
436 if (existingMacEntry.isPresent()) {
437 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(
438 elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(),
441 elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(
442 elanUtils.getElanInstanceByName(elanName), interfaceName, physAddress, tx);
444 ElanUtils.waitForTransactionToComplete(tx);
447 } else if (existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
448 for (PhysAddress physAddress : existingPhysAddress) {
449 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
455 protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
456 String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
457 String interfaceName = elanInterfaceAdded.getName();
458 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
459 if (interfaceInfo == null) {
460 logger.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
463 ElanInstance elanInstance = elanUtils.getElanInstanceByName(elanInstanceName);
465 if (elanInstance == null) {
466 elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
467 .setDescription(elanInterfaceAdded.getDescription()).build();
468 // Add the ElanInstance in the Configuration data-store
469 WriteTransaction tx = broker.newWriteOnlyTransaction();
470 List<String> elanInterfaces = new ArrayList<String>();
471 elanInterfaces.add(interfaceName);
472 ElanUtils.updateOperationalDataStore(broker, idManager,
473 elanInstance, elanInterfaces, tx);
474 ElanUtils.waitForTransactionToComplete(tx);
475 elanInstance = elanUtils.getElanInstanceByName(elanInstanceName);
478 Long elanTag = elanInstance.getElanTag();
479 // If elan tag is not updated, then put the elan interface into
480 // unprocessed entry map and entry. Let entries
481 // in this map get processed during ELAN update DCN.
482 if (elanTag == null) {
483 ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
484 if (elanInterfaces == null) {
485 elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
487 elanInterfaces.add(elanInterfaceAdded);
488 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
491 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
492 InterfaceAddWorkerOnElan addWorker = new InterfaceAddWorkerOnElan(elanInstanceName, elanInterfaceAdded,
493 interfaceInfo, elanInstance, this);
494 coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
497 void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
498 List<ListenableFuture<Void>> futures = new ArrayList<>();
499 Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
500 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
503 for (ElanInterface elanInterface : elanInterfaces) {
504 String interfaceName = elanInterface.getName();
505 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
506 addElanInterface(futures, elanInterface, interfaceInfo, elanInstance);
510 void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
511 WriteTransaction writeFlowGroupTx) {
512 ElanDpnInterfacesList elanDpnInterfacesList = elanUtils
513 .getElanDpnInterfacesList(elanInstance.getElanInstanceName());
514 List<DpnInterfaces> dpnInterfaceLists = null;
515 if (elanDpnInterfacesList != null) {
516 dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
518 if (dpnInterfaceLists == null) {
519 dpnInterfaceLists = new ArrayList<DpnInterfaces>();
521 for (DpnInterfaces dpnInterfaces : dpnInterfaceLists) {
522 if (dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
525 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
526 for (String remoteIf : remoteElanInterfaces) {
527 ElanInterfaceMac elanIfMac = elanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
528 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
529 if (elanIfMac == null) {
532 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
533 if (remoteMacEntries != null) {
534 for (MacEntry macEntry : remoteMacEntries) {
535 PhysAddress physAddress = macEntry.getMacAddress();
536 elanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
537 remoteInterface.getInterfaceTag(), elanInstance.getElanTag(), physAddress.getValue(),
538 elanInstance.getElanInstanceName(), writeFlowGroupTx, remoteIf);
545 void addElanInterface(List<ListenableFuture<Void>> futures, ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
546 Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
547 Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
548 Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
550 String interfaceName = elanInterface.getName();
551 String elanInstanceName = elanInterface.getElanInstanceName();
553 Elan elanInfo = elanUtils.getElanByName(elanInstanceName);
554 WriteTransaction tx = broker.newWriteOnlyTransaction();
555 if (elanInfo == null) {
556 List<String> elanInterfaces = new ArrayList<String>();
557 elanInterfaces.add(interfaceName);
558 ElanUtils.updateOperationalDataStore(broker, idManager,
559 elanInstance, elanInterfaces, tx);
561 createElanStateList(elanInstanceName, interfaceName, tx);
563 boolean isFirstInterfaceInDpn = false;
564 // Specific actions to the DPN where the ElanInterface has been added,
565 // for example, programming the
566 // External tunnel table if needed or adding the ElanInterface to the
567 // DpnInterfaces in the operational DS.
568 BigInteger dpId = (interfaceInfo != null) ? dpId = interfaceInfo.getDpId() : null;
569 DpnInterfaces dpnInterfaces = null;
570 if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
571 InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils
572 .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
573 Optional<DpnInterfaces> existingElanDpnInterfaces = elanUtils.read(broker,
574 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
575 if (!existingElanDpnInterfaces.isPresent()) {
576 isFirstInterfaceInDpn = true;
577 // ELAN's 1st ElanInterface added to this DPN
578 dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
579 // The 1st ElanInterface in a DPN must program the Ext Tunnel
580 // table, but only if Elan has VNI
581 if (ElanUtils.isVxlan(elanInstance)) {
582 setExternalTunnelTable(dpId, elanInstance);
584 elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
586 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
587 elanInterfaces.add(interfaceName);
588 if (elanInterfaces.size() == 1) {// 1st dpn interface
589 elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
591 dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
595 // add code to install Local/Remote BC group, unknow DMAC entry,
596 // terminating service table flow entry
597 // call bindservice of interfacemanager to create ingress table flow
599 // Add interface to the ElanInterfaceForwardingEntires Container
600 createElanInterfaceTablesList(interfaceName, tx);
601 if (interfaceInfo != null) {
602 installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn, tx);
604 futures.add(ElanUtils.waitForTransactionToComplete(tx));
606 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
607 InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(interfaceName,
608 elanInterface, interfaceInfo, elanInstance, isFirstInterfaceInDpn, this);
609 coordinator.enqueueJob(interfaceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
612 void setupEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInstance, ElanInterface elanInterface,
613 InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) {
614 String elanInstanceName = elanInstance.getElanInstanceName();
615 String interfaceName = elanInterface.getName();
616 WriteTransaction tx = broker.newWriteOnlyTransaction();
617 BigInteger dpId = interfaceInfo.getDpId();
618 WriteTransaction writeFlowGroupTx = broker.newWriteOnlyTransaction();
619 installEntriesForElanInterface(elanInstance, interfaceInfo, isFirstInterfaceInDpn, tx, writeFlowGroupTx);
620 List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
621 if (staticMacAddresses != null) {
622 boolean isInterfaceOperational = isOperational(interfaceInfo);
623 for (PhysAddress physAddress : staticMacAddresses) {
624 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
625 Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
626 LogicalDatastoreType.OPERATIONAL, macId);
627 if (existingMacEntry.isPresent()) {
628 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(
629 elanInstanceName, interfaceName, existingMacEntry.get().getInterface(),
630 existingMacEntry.get(), tx);
632 elanForwardingEntriesHandler
633 .addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress, tx);
636 if (isInterfaceOperational) {
637 // Setting SMAC, DMAC, UDMAC in this DPN and also in other
639 elanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT,
640 physAddress.getValue(), writeFlowGroupTx);
644 if (isInterfaceOperational) {
645 // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop
647 elanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId,
651 futures.add(ElanUtils.waitForTransactionToComplete(tx));
652 futures.add(ElanUtils.waitForTransactionToComplete(writeFlowGroupTx));
655 protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName,
656 PhysAddress physAddress) {
657 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
658 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
659 Optional<MacEntry> existingMacEntry = elanUtils.read(broker,
660 LogicalDatastoreType.OPERATIONAL, macId);
662 if (!existingMacEntry.isPresent()) {
666 MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName)
667 .setKey(new MacEntryKey(physAddress)).build();
668 WriteTransaction tx = broker.newWriteOnlyTransaction();
669 elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(
670 elanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry, tx);
671 elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName,
673 ElanUtils.waitForTransactionToComplete(tx);
676 private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
677 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName))
678 .child(MacEntry.class, new MacEntryKey(physAddress)).build();
681 private void installEntriesForElanInterface(ElanInstance elanInstance, InterfaceInfo interfaceInfo,
682 boolean isFirstInterfaceInDpn, WriteTransaction tx, WriteTransaction writeFlowGroupTx) {
683 if (!isOperational(interfaceInfo)) {
686 BigInteger dpId = interfaceInfo.getDpId();
687 elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, writeFlowGroupTx);
688 setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx);
689 if (isFirstInterfaceInDpn) {
690 // Terminating Service , UnknownDMAC Table.
691 setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
692 setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
693 // update the remote-DPNs remoteBC group entry with Tunnels
694 setElanBCGrouponOtherDpns(elanInstance, elanInstance.getElanTag().longValue(), dpId, writeFlowGroupTx);
696 * Install remote DMAC flow. This is required since this DPN is
697 * added later to the elan instance and remote DMACs of other
698 * interfaces in this elan instance are not present in the current
701 programRemoteDmacFlow(elanInstance, interfaceInfo, writeFlowGroupTx);
703 // bind the Elan service to the Interface
704 bindService(elanInstance, elanUtils.getElanInterfaceByElanInterfaceName(interfaceInfo.getInterfaceName()), tx);
707 public void installEntriesForFirstInterfaceonDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
708 DpnInterfaces dpnInterfaces, boolean isFirstInterfaceInDpn, WriteTransaction tx) {
709 if (!isOperational(interfaceInfo)) {
712 // LocalBroadcast Group creation with elan-Interfaces
713 setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
714 if (isFirstInterfaceInDpn) {
715 logger.trace("waitTimeForSyncInstall is {}", waitTimeForSyncInstall);
716 BigInteger dpId = interfaceInfo.getDpId();
717 // RemoteBroadcast Group creation
719 Thread.sleep(waitTimeForSyncInstall);
720 } catch (InterruptedException e1) {
721 logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
723 setupElanBroadcastGroups(elanInfo, dpnInterfaces, dpId);
725 Thread.sleep(waitTimeForSyncInstall);
726 } catch (InterruptedException e1) {
727 logger.warn("Error while waiting for local BC group for ELAN {} to install", elanInfo);
732 public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
733 WriteTransaction writeFlowGroupTx) {
734 int ifTag = interfaceInfo.getInterfaceTag();
735 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
736 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
737 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
738 getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
739 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
741 mdsalManager.addFlowToTx(interfaceInfo.getDpId(), flow, writeFlowGroupTx);
743 Flow flowEntry = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
744 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000 + ifTag), 10, elanInfo.getElanInstanceName(), 0,
745 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
746 getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
748 mdsalManager.addFlowToTx(interfaceInfo.getDpId(), flowEntry, writeFlowGroupTx);
751 public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
752 WriteTransaction deleteFlowGroupTx) {
753 int ifTag = interfaceInfo.getInterfaceTag();
754 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
755 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
756 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
757 getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
758 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
760 mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
762 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
763 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, 1000 + ifTag), 10, elanInfo.getElanInstanceName(), 0,
764 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
765 getMatchesForFilterEqualsLPortTag(ifTag), MDSALUtil.buildInstructionsDrop());
767 mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flowEntity, deleteFlowGroupTx);
770 private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo, int bucketKeyStart,
771 InterfaceInfo interfaceInfo, long elanTag) {
772 return getRemoteBCGroupBuckets(elanInfo, null, interfaceInfo.getDpId(), bucketKeyStart, elanTag);
775 private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId,
776 int bucketId, long elanTag) {
777 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
778 ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
779 listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId, elanTag));
780 listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId, bucketId));
781 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId));
782 return listBucketInfo;
785 private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
787 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
788 if (elanDpns != null) {
789 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
790 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId
791 && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
793 List<Action> listActionInfo = elanUtils.getInternalTunnelItmEgressAction(dpnId,
794 dpnInterface.getDpId(), elanTag);
795 if (listActionInfo.isEmpty()) {
798 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
799 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
801 } catch (Exception ex) {
802 logger.error("Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
803 dpnId, dpnInterface.getDpId());
808 return listBucketInfo;
811 private List<Bucket> getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns,
812 DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) {
813 DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId);
814 if (currDpnInterfaces == null || !elanUtils.isDpnPresent(currDpnInterfaces.getDpId())
815 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
816 return Collections.emptyList();
819 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
820 for (String interfaceName : currDpnInterfaces.getInterfaces()) {
821 if (elanUtils.isExternal(interfaceName)) {
822 List<Action> listActionInfo = elanUtils.getExternalPortItmEgressAction(interfaceName);
823 if (!listActionInfo.isEmpty()) {
824 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
825 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
830 return listBucketInfo;
833 private DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) {
834 if (elanDpns != null) {
835 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
836 if (dpnInterface.getDpId() == dpnId) {
844 private void setElanBCGrouponOtherDpns(ElanInstance elanInfo, long elanTag, BigInteger dpId, WriteTransaction tx) {
845 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
846 List<Bucket> listBucket = new ArrayList<Bucket>();
848 ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
849 if (elanDpns != null) {
850 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
851 for (DpnInterfaces dpnInterface : dpnInterfaceses) {
852 List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
853 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpId)
854 && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
855 List<Action> listAction = new ArrayList<Action>();
857 listAction.add((new ActionInfo(ActionType.group,
858 new String[] { String.valueOf(ElanUtils.getElanLocalBCGID(elanTag)) }, ++actionKey))
860 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId,
861 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
863 remoteListBucketInfo.addAll(listBucket);
864 for (DpnInterfaces otherFes : dpnInterfaceses) {
865 if (elanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
866 && otherFes.getInterfaces() != null && !otherFes.getInterfaces().isEmpty()) {
868 List<Action> remoteListActionInfo = elanUtils.getInternalTunnelItmEgressAction(
869 dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
870 if (!remoteListActionInfo.isEmpty()) {
872 .add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT,
873 bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
876 } catch (Exception ex) {
878 "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
879 dpnInterface.getDpId(), otherFes.getDpId());
884 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpId,
886 remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
888 if (remoteListBucketInfo.size() == 0) {
889 logger.debug("No ITM is present on Dpn - {} ", dpnInterface.getDpId());
892 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
893 MDSALUtil.buildBucketLists(remoteListBucketInfo));
894 mdsalManager.addGroupToTx(dpnInterface.getDpId(), group, tx);
901 * Returns the bucket info with the given interface as the only bucket.
903 private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
904 return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart,
905 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
908 private List<MatchInfo> buildMatchesForVni(Long vni) {
909 List<MatchInfo> mkMatches = new ArrayList<>();
910 MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(vni) });
911 mkMatches.add(match);
915 private List<Instruction> getInstructionsForOutGroup(long groupId) {
916 List<Instruction> mkInstructions = new ArrayList<>();
917 List<Action> actions = new ArrayList<>();
918 actions.add(new ActionInfo(ActionType.group, new String[] { Long.toString(groupId) }).buildAction());
919 mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
920 return mkInstructions;
923 private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
924 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
926 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
927 ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG }));
932 * Builds the list of instructions to be installed in the External Tunnel
933 * table (38), which so far consists in writing the elanTag in metadata and
934 * send packet to the new DHCP table
937 * elanTag to be written in metadata when flow is selected
938 * @return the instructions ready to be installed in a flow
940 private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
941 List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
942 mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
943 new BigInteger[] { ElanUtils.getElanMetadataLabel(elanTag), ElanUtils.getElanMetadataMask() }));
944 // TODO: We should point to SMAC or DMAC depending on a configuration
945 // property to enable
947 mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.ELAN_DMAC_TABLE }));
949 return mkInstructions;
952 // Install DMAC entry on dst DPN
953 public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
954 String interfaceName = interfaceInfo.getInterfaceName();
955 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
956 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
957 WriteTransaction writeFlowTx = broker.newWriteOnlyTransaction();
958 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
959 for (MacEntry macEntry : macEntries) {
960 PhysAddress physAddress = macEntry.getMacAddress();
961 elanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue(),
964 writeFlowTx.submit();
968 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
969 setupElanBroadcastGroups(elanInfo, null, dpnId);
972 public void setupElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
973 setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
974 setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
977 public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
978 List<Bucket> listBucket = new ArrayList<Bucket>();
981 Long elanTag = elanInfo.getElanTag();
982 List<Action> listAction = new ArrayList<Action>();
983 listAction.add((new ActionInfo(ActionType.group,
984 new String[] { String.valueOf(ElanUtils.getElanLocalBCGID(elanTag)) }, ++actionKey)).buildAction());
985 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
986 MDSALUtil.WATCH_GROUP));
988 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
989 elanInfo.getElanTag());
990 listBucket.addAll(listBucketInfoRemote);
991 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
992 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
993 MDSALUtil.buildBucketLists(listBucket));
994 logger.trace("Installing the remote BroadCast Group:{}", group);
995 mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
998 public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
999 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1000 if (etreeInstance != null) {
1001 long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
1002 List<Bucket> listBucket = new ArrayList<Bucket>();
1005 List<Action> listAction = new ArrayList<Action>();
1006 listAction.add((new ActionInfo(ActionType.group,
1007 new String[] { String.valueOf(ElanUtils.getEtreeLeafLocalBCGID(etreeLeafTag)) }, ++actionKey))
1009 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
1010 MDSALUtil.WATCH_GROUP));
1012 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
1014 listBucket.addAll(listBucketInfoRemote);
1015 long groupId = ElanUtils.getEtreeLeafRemoteBCGID(etreeLeafTag);
1016 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1017 MDSALUtil.buildBucketLists(listBucket));
1018 logger.trace("Installing the remote BroadCast Group:{}", group);
1019 mdsalManager.syncInstallGroup(dpnId, group,
1020 ElanConstants.DELAY_TIME_IN_MILLISECOND);
1024 private void createDropBucket(List<Bucket> listBucket) {
1025 List<Action> actionsInfos = new ArrayList<Action>();
1026 actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {}).buildAction());
1027 Bucket dropBucket = MDSALUtil.buildBucket(actionsInfos, MDSALUtil.GROUP_WEIGHT, 0, MDSALUtil.WATCH_PORT,
1028 MDSALUtil.WATCH_GROUP);
1029 listBucket.add(dropBucket);
1032 public void setupLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1033 InterfaceInfo interfaceInfo) {
1034 setupStandardLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo);
1035 setupLeavesLocalBroadcastGroups(elanInfo, newDpnInterface, interfaceInfo);
1038 public void setupStandardLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1039 InterfaceInfo interfaceInfo) {
1040 List<Bucket> listBucket = new ArrayList<Bucket>();
1042 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
1044 List<String> interfaces = new ArrayList<String>();
1045 if (newDpnInterface != null) {
1046 interfaces = newDpnInterface.getInterfaces();
1048 for (String ifName : interfaces) {
1049 // In case if there is a InterfacePort in the cache which is not in
1050 // operational state, skip processing it
1051 InterfaceInfo ifInfo = interfaceManager
1052 .getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
1053 if (!isOperational(ifInfo)) {
1057 if (!elanUtils.isExternal(ifName)) {
1058 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId,
1059 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1064 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1065 MDSALUtil.buildBucketLists(listBucket));
1066 logger.trace("installing the localBroadCast Group:{}", group);
1067 mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group,
1068 ElanConstants.DELAY_TIME_IN_MILLISECOND);
1071 private void setupLeavesLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
1072 InterfaceInfo interfaceInfo) {
1073 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1074 if (etreeInstance != null) {
1075 long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
1076 List<Bucket> listBucket = new ArrayList<Bucket>();
1078 long groupId = ElanUtils.getEtreeLeafLocalBCGID(etreeLeafTag);
1080 List<String> interfaces = new ArrayList<String>();
1081 if (newDpnInterface != null) {
1082 interfaces = newDpnInterface.getInterfaces();
1084 for (String ifName : interfaces) {
1085 // In case if there is a InterfacePort in the cache which is not
1087 // operational state, skip processing it
1088 InterfaceInfo ifInfo = interfaceManager
1089 .getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
1090 if (!isOperational(ifInfo)) {
1094 if (!elanUtils.isExternal(ifName)) {
1095 // only add root interfaces
1096 bucketId = addInterfaceIfRootInterface(bucketId, ifName, listBucket, ifInfo);
1100 if (listBucket.size() == 0) { // No Buckets
1101 createDropBucket(listBucket);
1104 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1105 MDSALUtil.buildBucketLists(listBucket));
1106 logger.trace("installing the localBroadCast Group:{}", group);
1107 mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group,
1108 ElanConstants.DELAY_TIME_IN_MILLISECOND);
1112 private int addInterfaceIfRootInterface(int bucketId, String ifName, List<Bucket> listBucket,
1113 InterfaceInfo ifInfo) {
1114 EtreeInterface etreeInterface = elanUtils.getEtreeInterfaceByElanInterfaceName(ifName);
1115 if (etreeInterface != null && etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1116 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId,
1117 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1123 public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
1124 WriteTransaction deleteFlowGroupTx) {
1125 BigInteger dpnId = interfaceInfo.getDpId();
1126 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
1127 List<Bucket> listBuckets = new ArrayList<>();
1129 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
1130 // listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1,
1132 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1133 MDSALUtil.buildBucketLists(listBuckets));
1134 logger.trace("deleted the localBroadCast Group:{}", group);
1135 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
1138 public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
1139 WriteTransaction deleteFlowGroupTx) {
1142 Long elanTag = elanInfo.getElanTag();
1143 List<Bucket> listBuckets = new ArrayList<>();
1144 List<Action> listAction = new ArrayList<Action>();
1145 listAction.add((new ActionInfo(ActionType.group,
1146 new String[] { String.valueOf(ElanUtils.getElanLocalBCGID(elanTag)) }, ++actionKey)).buildAction());
1147 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
1148 MDSALUtil.WATCH_GROUP));
1150 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, elanInfo.getElanTag()));
1151 BigInteger dpnId = interfaceInfo.getDpId();
1152 long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
1153 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
1154 MDSALUtil.buildBucketLists(listBuckets));
1155 logger.trace("deleting the remoteBroadCast group:{}", group);
1156 mdsalManager.removeGroupToTx(dpnId, group, deleteFlowGroupTx);
1160 * Installs a flow in the External Tunnel table consisting in translating
1161 * the VNI retrieved from the packet that came over a tunnel with a TOR into
1162 * elanTag that will be used later in the ELANs pipeline.
1169 public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
1170 long elanTag = elanInfo.getElanTag();
1171 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.EXTERNAL_TUNNEL_TABLE,
1172 getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag), 5, // prio
1173 elanInfo.getElanInstanceName(), // flowName
1176 ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
1177 buildMatchesForVni(elanInfo.getSegmentationId()), getInstructionsExtTunnelTable(elanTag));
1179 mdsalManager.installFlow(flowEntity);
1183 * Removes, from External Tunnel table, the flow that translates from VNI to
1184 * elanTag. Important: ensure this method is only called whenever there is
1185 * no other ElanInterface in the specified DPN
1188 * DPN whose Ext Tunnel table is going to be modified
1190 * holds the elanTag needed for selecting the flow to be removed
1192 public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
1193 // TODO: Use DataStoreJobCoordinator in order to avoid that removing the
1194 // last ElanInstance plus
1195 // adding a new one does (almost at the same time) are executed in that
1198 String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
1199 FlowEntity flowEntity = new FlowEntity(dpnId);
1200 flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
1201 flowEntity.setFlowId(flowId);
1202 mdsalManager.removeFlow(flowEntity);
1205 public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
1206 setupTerminateServiceTable(elanInfo, dpId, elanInfo.getElanTag(), writeFlowGroupTx);
1207 setupEtreeTerminateServiceTable(elanInfo, dpId, writeFlowGroupTx);
1210 private void setupEtreeTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId,
1211 WriteTransaction writeFlowGroupTx) {
1212 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1213 if (etreeInstance != null) {
1214 setupTerminateServiceTable(elanInfo, dpId, etreeInstance.getEtreeLeafTagVal().getValue(), writeFlowGroupTx);
1218 public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1219 WriteTransaction writeFlowGroupTx) {
1220 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
1221 getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag), 5,
1222 String.format("%s:%d", "ITM Flow Entry ", elanTag), 0, 0,
1223 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)),
1224 ElanUtils.getTunnelMatchesForServiceId((int) elanTag),
1225 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
1227 mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
1230 public void setupUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, WriteTransaction writeFlowGroupTx) {
1231 long elanTag = elanInfo.getElanTag();
1232 installLocalUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
1233 installRemoteUnknownFlow(elanInfo, dpId, elanTag, writeFlowGroupTx);
1234 setupEtreeUnknownDMacTable(elanInfo, dpId, elanTag, writeFlowGroupTx);
1237 private void setupEtreeUnknownDMacTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1238 WriteTransaction writeFlowGroupTx) {
1239 EtreeLeafTagName etreeLeafTag = elanUtils.getEtreeLeafTagByElanTag(elanTag);
1240 if (etreeLeafTag != null) {
1241 long leafTag = etreeLeafTag.getEtreeLeafTag().getValue();
1242 installRemoteUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
1243 installLocalUnknownFlow(elanInfo, dpId, leafTag, writeFlowGroupTx);
1247 private void installLocalUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1248 WriteTransaction writeFlowGroupTx) {
1249 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1250 getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
1251 /* SH flag */false),
1252 5, elanInfo.getElanInstanceName(), 0, 0,
1253 ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
1254 getMatchesForElanTag(elanTag, /* SH flag */false),
1255 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
1257 mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
1260 private void installRemoteUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
1261 WriteTransaction writeFlowGroupTx) {
1262 // only if ELAN can connect to external network, perform the following
1263 if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) {
1264 Flow flowEntity2 = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1265 getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
1267 5, elanInfo.getElanInstanceName(), 0, 0,
1268 ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
1269 getMatchesForElanTag(elanTag, /* SH flag */true),
1270 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
1271 mdsalManager.addFlowToTx(dpId, flowEntity2, writeFlowGroupTx);
1276 private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo, WriteTransaction deleteFlowGroupTx,
1278 Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1279 elanTag, /* SH flag */ false))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE).build();
1280 mdsalManager.removeFlowToTx(dpId, flow, deleteFlowGroupTx);
1282 if (ElanUtils.isVxlan(elanInfo)) {
1283 Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
1284 elanTag, /* SH flag */ true))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE)
1286 mdsalManager.removeFlowToTx(dpId, flow2, deleteFlowGroupTx);
1290 private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
1291 elanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
1294 private void bindService(ElanInstance elanInfo, ElanInterface elanInterface, WriteTransaction tx) {
1295 if (isStandardElanService(elanInterface)) {
1296 bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), tx);
1297 } else { // Etree service
1298 bindEtreeService(elanInfo, elanInterface, tx);
1302 private void bindElanService(long elanTag, String elanInstanceName, String interfaceName, WriteTransaction tx) {
1303 int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
1304 int instructionKey = 0;
1305 List<Instruction> instructions = new ArrayList<Instruction>();
1306 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanTag),
1307 MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
1308 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ELAN_SMAC_TABLE, ++instructionKey));
1309 short elan_service_index = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX);
1310 BoundServices serviceInfo = ElanUtils.getBoundServices(
1311 String.format("%s.%s.%s", "vpn", elanInstanceName, interfaceName), elan_service_index,
1312 priority, NwConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
1313 tx.put(LogicalDatastoreType.CONFIGURATION,
1314 ElanUtils.buildServiceId(interfaceName, elan_service_index), serviceInfo, true);
1317 private void bindEtreeService(ElanInstance elanInfo, ElanInterface elanInterface, WriteTransaction tx) {
1318 if (elanInterface.getAugmentation(EtreeInterface.class).getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1319 bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(), tx);
1321 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
1322 if (etreeInstance == null) {
1323 logger.error("EtreeInterface " + elanInterface.getName() + " is associated with a non EtreeInstance: "
1324 + elanInfo.getElanInstanceName());
1326 bindElanService(etreeInstance.getEtreeLeafTagVal().getValue(), elanInfo.getElanInstanceName(),
1327 elanInterface.getName(), tx);
1332 private boolean isStandardElanService(ElanInterface elanInterface) {
1333 return elanInterface.getAugmentation(EtreeInterface.class) == null;
1336 private boolean isStandardElanService(ElanInstance elanInstance) {
1337 return elanInstance.getAugmentation(EtreeInstance.class) == null;
1340 private void unbindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
1341 tx.delete(LogicalDatastoreType.CONFIGURATION,
1342 ElanUtils.buildServiceId(interfaceName, ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX)));
1345 private String getFlowRef(long tableId, long elanTag) {
1346 return new StringBuffer().append(tableId).append(elanTag).toString();
1349 private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) {
1350 return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString();
1353 private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
1354 List<Action> listAction = new ArrayList<Action>();
1356 listAction.add((new ActionInfo(ActionType.set_field_tunnel_id,
1357 new BigInteger[] { BigInteger.valueOf(interfaceInfo.getInterfaceTag()) }, actionKey)).buildAction());
1359 listAction.add((new ActionInfo(ActionType.nx_resubmit,
1360 new String[] { String.valueOf(NwConstants.ELAN_FILTER_EQUALS_TABLE) }, actionKey)).buildAction());
1364 private DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId,
1365 List<String> interfaceNames, WriteTransaction tx) {
1366 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
1367 .setKey(new DpnInterfacesKey(dpId)).build();
1368 tx.put(LogicalDatastoreType.OPERATIONAL,
1369 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, true);
1370 return dpnInterface;
1374 * Delete elan dpn interface from operational DS.
1376 * @param elanInstanceName
1377 * the elan instance name
1381 private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId, WriteTransaction tx) {
1382 tx.delete(LogicalDatastoreType.OPERATIONAL,
1383 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
1386 private DpnInterfaces createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId,
1387 WriteTransaction tx) {
1388 List<String> interfaceNames = new ArrayList<String>();
1389 interfaceNames.add(interfaceName);
1390 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
1391 .setKey(new DpnInterfacesKey(dpId)).build();
1392 tx.put(LogicalDatastoreType.OPERATIONAL,
1393 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface, true);
1394 return dpnInterface;
1397 private void createElanInterfaceTablesList(String interfaceName, WriteTransaction tx) {
1398 InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils
1399 .getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1400 Optional<ElanInterfaceMac> interfaceMacTables = elanUtils.read(broker,
1401 LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
1402 // Adding new Elan Interface Port to the operational DataStore without
1403 // Static-Mac Entries..
1404 if (!interfaceMacTables.isPresent()) {
1405 ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName)
1406 .setKey(new ElanInterfaceMacKey(interfaceName)).build();
1407 tx.put(LogicalDatastoreType.OPERATIONAL,
1408 ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), elanInterfaceMacTable,
1413 private void createElanStateList(String elanInstanceName, String interfaceName, WriteTransaction tx) {
1414 InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
1415 Optional<Elan> elanInterfaceLists = elanUtils.read(broker,
1416 LogicalDatastoreType.OPERATIONAL, elanInstance);
1417 // Adding new Elan Interface Port to the operational DataStore without
1418 // Static-Mac Entries..
1419 if (elanInterfaceLists.isPresent()) {
1420 List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
1421 if (interfaceLists == null) {
1422 interfaceLists = new ArrayList<>();
1424 interfaceLists.add(interfaceName);
1425 Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists)
1426 .setKey(new ElanKey(elanInstanceName)).build();
1427 tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName),
1432 private boolean isOperational(InterfaceInfo interfaceInfo) {
1433 if (interfaceInfo == null) {
1436 return interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED;
1439 public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
1440 ElanDpnInterfaces dpnInterfaceLists = elanUtils.getElanDpnInterfacesList();
1441 if (dpnInterfaceLists == null) {
1444 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1445 for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1447 String elanName = elanDpns.getElanInstanceName();
1448 List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
1449 if (dpnInterfaces == null) {
1452 for (DpnInterfaces dpnIf : dpnInterfaces) {
1453 if (dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
1458 logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
1459 ElanInstance elanInfo = elanUtils.getElanInstanceByName(elanName);
1460 // update Remote BC Group
1461 setupElanBroadcastGroups(elanInfo, srcDpId);
1463 DpnInterfaces dpnInterface = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dstDpId);
1464 Set<String> interfaceLists = new HashSet<>();
1465 interfaceLists.addAll(dpnInterface.getInterfaces());
1466 for (String ifName : interfaceLists) {
1467 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
1468 if (isOperational(interfaceInfo)) {
1469 installDMacAddressTables(elanInfo, interfaceInfo, srcDpId);
1478 * Handle external tunnel state event.
1480 * @param externalTunnel
1481 * the external tunnel
1485 public void handleExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1486 if (!validateExternalTunnelStateEvent(externalTunnel, intrf)) {
1489 // dpId/externalNodeId will be available either in source or destination
1490 // based on the tunnel end point
1491 BigInteger dpId = null;
1492 NodeId externalNodeId = null;
1493 if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
1494 dpId = new BigInteger(externalTunnel.getSourceDevice());
1495 externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
1496 } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
1497 dpId = new BigInteger(externalTunnel.getDestinationDevice());
1498 externalNodeId = new NodeId(externalTunnel.getSourceDevice());
1500 if (dpId == null || externalNodeId == null) {
1501 logger.error("Dp ID / externalNodeId not found in external tunnel {}", externalTunnel);
1505 ElanDpnInterfaces dpnInterfaceLists = elanUtils.getElanDpnInterfacesList();
1506 if (dpnInterfaceLists == null) {
1509 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1510 for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1511 String elanName = elanDpns.getElanInstanceName();
1512 ElanInstance elanInfo = elanUtils.getElanInstanceByName(elanName);
1514 DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1515 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
1516 || dpnInterfaces.getInterfaces().isEmpty()) {
1519 logger.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
1521 setupElanBroadcastGroups(elanInfo, dpId);
1522 // install L2gwDevices local macs in dpn.
1523 elanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo, intrf.getName());
1524 // Install dpn macs on external device
1525 elanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
1528 logger.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
1532 * Validate external tunnel state event.
1534 * @param externalTunnel
1535 * the external tunnel
1538 * @return true, if successful
1540 private boolean validateExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1541 if (intrf.getOperStatus() == Interface.OperStatus.Up) {
1542 String srcDevice = externalTunnel.getDestinationDevice();
1543 String destDevice = externalTunnel.getSourceDevice();
1544 ExternalTunnel otherEndPointExtTunnel = elanUtils.getExternalTunnel(srcDevice, destDevice,
1545 LogicalDatastoreType.CONFIGURATION);
1546 if (logger.isTraceEnabled()) {
1547 logger.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
1548 otherEndPointExtTunnel);
1550 if (otherEndPointExtTunnel != null) {
1551 boolean otherEndPointInterfaceOperational = ElanUtils.isInterfaceOperational(
1552 otherEndPointExtTunnel.getTunnelInterfaceName(), broker);
1553 if (otherEndPointInterfaceOperational) {
1556 logger.debug("Other end [{}] of the external tunnel is not yet UP for {}",
1557 otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
1564 private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
1565 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1566 // Matching metadata
1567 mkMatches.add(new MatchInfo(MatchFieldType.metadata,
1568 new BigInteger[] { MetaDataUtil.getLportTagMetaData(LportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1569 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(LportTag) }));
1573 private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
1574 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1575 // Matching metadata
1576 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(LportTag) }));
1580 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
1581 List<DpnInterfaces> dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
1585 for (DpnInterfaces dpn : dpns) {
1586 setupElanBroadcastGroups(elanInfo, dpn.getDpId());
1590 public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
1592 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
1593 ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
1594 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
1595 for (L2GatewayDevice device : map.values()) {
1596 String interfaceName = elanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
1597 device.getHwvtepNodeId());
1598 if (interfaceName == null) {
1601 List<Action> listActionInfo = elanUtils.buildTunnelItmEgressActions(interfaceName,
1602 elanInfo.getSegmentationId());
1603 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
1604 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1607 return listBucketInfo;
1611 protected ElanInterfaceManager getDataTreeChangeListener() {