X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=elanmanager%2Felanmanager-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fvpnservice%2Felan%2Finternal%2FElanInterfaceManager.java;h=1b422c5d5b600c3baea4af94d20a1f72429312c1;hb=916aaebc7ed8eebcb4ae0a963c8cd6b95db650b9;hp=329eed0e440eb9484c3f05a55f35eb1a84ce1d12;hpb=ba45d7db37822f2566c2f4969dd59f66e0349268;p=vpnservice.git diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java index 329eed0e..1b422c5d 100644 --- a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java @@ -7,26 +7,64 @@ */ package org.opendaylight.vpnservice.elan.internal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; + import com.google.common.base.Optional; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayMulticastUtils; +import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils; import org.opendaylight.vpnservice.elan.utils.ElanConstants; import org.opendaylight.vpnservice.elan.utils.ElanUtils; import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType; import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; import org.opendaylight.vpnservice.itm.api.IITMProvider; - +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener; +import org.opendaylight.vpnservice.mdsalutil.ActionInfo; +import org.opendaylight.vpnservice.mdsalutil.ActionType; +import org.opendaylight.vpnservice.mdsalutil.BucketInfo; +import org.opendaylight.vpnservice.mdsalutil.FlowEntity; +import org.opendaylight.vpnservice.mdsalutil.GroupEntity; +import org.opendaylight.vpnservice.mdsalutil.InstructionInfo; +import org.opendaylight.vpnservice.mdsalutil.InstructionType; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; +import org.opendaylight.vpnservice.mdsalutil.MatchInfo; +import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil; +import org.opendaylight.vpnservice.mdsalutil.NwConstants; +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.vpnservice.mdsalutil.*; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanForwardingTables; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces; @@ -49,20 +87,23 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.f import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.math.BigInteger; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +/** + * Class in charge of handling creations, modifications and removals of ElanInterfaces. + * + * @see org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface + * + */ public class ElanInterfaceManager extends AbstractDataChangeListener implements AutoCloseable { private static ElanInterfaceManager elanInterfaceManager = new ElanInterfaceManager(); @@ -73,7 +114,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener> unProcessedElanInterfaces = new ConcurrentHashMap> (); @@ -108,10 +149,6 @@ public class ElanInterfaceManager extends AbstractDataChangeListener macEntries = elanInterfaceMac.getMacEntry(); @@ -176,15 +214,14 @@ public class ElanInterfaceManager extends AbstractDataChangeListener elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName); Optional existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId); if(existingElanInterface.isPresent()) { - List macEntries = existingElanInterface.get().getMacEntry(); - if(macEntries != null && !macEntries.isEmpty()) { + List macAddresses = new ArrayList(); + List existingMacEntries = existingElanInterface.get().getMacEntry(); + List macEntries = new ArrayList<>(); + if (existingMacEntries != null && !existingMacEntries.isEmpty()) { + macEntries.addAll(existingMacEntries); + } + if(!macEntries.isEmpty()) { for (MacEntry macEntry : macEntries) { logger.debug("removing the mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName); elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(elanInfo, interfaceInfo, macEntry); + macAddresses.add(macEntry.getMacAddress()); + } + + // Removing all those MACs from External Devices belonging to this ELAN + if ( elanInfo.getVni() != null && elanInfo.getVni() != 0 ) { + ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses); } } } - /* *This condition check is mainly to get DPN-ID in pre-provision deletion scenario after stopping CSS */ @@ -226,10 +273,11 @@ public class ElanInterfaceManager extends AbstractDataChangeListener elanInterfaces = elanState.getElanInterfaces(); elanInterfaces.remove(interfaceName); - removeStaticELanFlows(elanInfo, interfaceInfo); + if(elanInterfaces.isEmpty()) { ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName)); ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnOperationDataPath(elanName)); @@ -247,7 +295,13 @@ public class ElanInterfaceManager extends AbstractDataChangeListener interfaceLists = dpnInterfaces.getInterfaces(); interfaceLists.remove(interfaceName); - updateElanDpnInterfacesList(elanName, dpId, interfaceLists); + + if (interfaceLists == null || interfaceLists.isEmpty()) { + deleteElanDpnInterface(elanName, dpId); + ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName); + } else { + updateElanDpnInterfacesList(elanName, dpId, interfaceLists); + } } } @@ -294,12 +348,16 @@ public class ElanInterfaceManager extends AbstractDataChangeListener dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces(); + for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){ + if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) { + continue; + } + List remoteElanInterfaces = dpnInterfaces.getInterfaces(); + for(String remoteIf : remoteElanInterfaces) { + ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf); + InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf); + if(elanIfMac == null) { + continue; + } + List remoteMacEntries = elanIfMac.getMacEntry(); + if(remoteMacEntries != null) { + for (MacEntry macEntry : remoteMacEntries) { + PhysAddress physAddress = macEntry.getMacAddress(); + ElanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(), + remoteInterface.getInterfaceTag(), + elanInstance.getElanTag(), + physAddress.getValue(), + elanInstance.getElanInstanceName()); + } + } + } + } + } + void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) { + Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null"); + Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null"); + Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null"); + String interfaceName = elanInterface.getName(); String elanInstanceName = elanInterface.getElanInstanceName(); List staticMacAddresses = elanInterface.getStaticMacEntries(); + Elan elanInfo = ElanUtils.getElanByName(elanInstanceName); - BigInteger dpId = null; if(elanInfo == null) { - ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstance); - } - if(interfaceInfo != null) { - dpId = interfaceInfo.getDpId(); + ElanUtils.updateOperationalDataStore(broker, idManager, elanInstance); } + + // Specific actions to the DPN where the ElanInterface has been added, for example, programming the + // External tunnel table if needed or adding the ElanInterface to the DpnInterfaces in the operational DS. + BigInteger dpId = ( interfaceInfo != null ) ? dpId = interfaceInfo.getDpId() : null; if(dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) { InstanceIdentifier elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId); Optional existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces); if (!existingElanDpnInterfaces.isPresent()) { + // ELAN's 1st ElanInterface added to this DPN createElanInterfacesList(elanInstanceName, interfaceName, dpId); + /* + * Install remote DMAC flow. + * This is required since this DPN is added later to the elan instance + * and remote DMACs of other interfaces in this elan instance are not present in the current dpn. + */ + programRemoteDmacFlow(elanInstance, interfaceInfo); + // The 1st ElanInterface in a DPN must program the Ext Tunnel table, but only if Elan has VNI + if ( elanInstance.getVni() != null && elanInstance.getVni().longValue() != 0 ) { + setExternalTunnelTable(dpId, elanInstance); + } + ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanInstanceName); } else { List elanInterfaces = existingElanDpnInterfaces.get().getInterfaces(); elanInterfaces.add(interfaceName); + if (elanInterfaces.size() == 1) {//1st dpn interface + ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanInstanceName); + } updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces); } } @@ -360,11 +467,12 @@ public class ElanInterfaceManager extends AbstractDataChangeListener macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress); Optional existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId); @@ -373,28 +481,18 @@ public class ElanInterfaceManager extends AbstractDataChangeListener> readFePortsDbForElan(String elanName) { - ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName); - HashMap> fePortsDb = Maps.newHashMap(); - if (elanDpnInterfacesList == null) { - return fePortsDb; - } - List dpnInterfaces = elanDpnInterfacesList.getDpnInterfaces(); - if (dpnInterfaces == null) { - return fePortsDb; - } - for (DpnInterfaces dpnInterface : dpnInterfaces) { - fePortsDb.put(dpnInterface.getDpId(), dpnInterface.getInterfaces()); + if( isInterfaceOperational ) { + // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop on purpose. + ElanL2GatewayUtils.installMacsInElanExternalDevices(elanInstance, dpId, staticMacAddresses); + } } - return fePortsDb; } protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) { @@ -421,8 +519,9 @@ public class ElanInterfaceManager extends AbstractDataChangeListener getRemoteBCGroupBucketInfos(ElanInstance elanInfo, - InterfaceInfo interfaceInfo) { + public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + int ifTag = interfaceInfo.getInterfaceTag(); + Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), + 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName())); + + mdsalManager.removeFlow(interfaceInfo.getDpId(), flow); + + Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag), + 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag), + MDSALUtil.buildInstructionsDrop()); + + mdsalManager.removeFlow(interfaceInfo.getDpId(), flowEntity); + } + + private List getRemoteBCGroupBucketInfos(ElanInstance elanInfo, + int bucketKeyStart, InterfaceInfo interfaceInfo) { BigInteger dpnId = interfaceInfo.getDpId(); int elanTag = elanInfo.getElanTag().intValue(); - List listBucketInfo = new ArrayList(); + int bucketId = bucketKeyStart; + List listBuckets = new ArrayList(); ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); if(elanDpns != null) { List dpnInterfaceses = elanDpns.getDpnInterfaces(); for(DpnInterfaces dpnInterface : dpnInterfaceses) { if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { try { - //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. - //List listActionInfo = itmManager.ITMIngressGetActions(dpnId, dpnInterface.getDpId(), (int) elanTag); - //listBucketInfo.add(new BucketInfo(listActionInfo)); + List listAction = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag); + listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); + bucketId++; } catch (Exception ex) { logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() ); } } } + List elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId); + listBuckets.addAll(elanL2GwDevicesBuckets); } - List listActionInfo = new ArrayList(); - listActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanInfo.getElanTag()))})); - listBucketInfo.add(new BucketInfo(listActionInfo)); - return listBucketInfo; + return listBuckets; } - public ActionInfo getTunnelIdActionInfo(int interfaceTag) { - return new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[]{BigInteger.valueOf(interfaceTag)}); + private List getRemoteBCGroupBuckets(ElanInstance elanInfo, + InterfaceInfo interfaceInfo, int bucketId) { + BigInteger dpnId = interfaceInfo.getDpId(); + int elanTag = elanInfo.getElanTag().intValue(); + List listBucketInfo = new ArrayList(); + ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); + if(elanDpns != null) { + List dpnInterfaceses = elanDpns.getDpnInterfaces(); + for(DpnInterfaces dpnInterface : dpnInterfaceses) { + if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { + try { + List listActionInfo = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag); + listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL)); + bucketId++; + } catch (Exception ex) { + logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() ); + } + } + } + + List elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId); + listBucketInfo.addAll(elanL2GwDevicesBuckets); + } + return listBucketInfo; } - private void setRemoteBCGrouponOtherDpns(ElanInstance elanInfo, - InterfaceInfo interfaceInfo) { + private void setElanBCGrouponOtherDpns(ElanInstance elanInfo, + InterfaceInfo interfaceInfo) { BigInteger dpnId = interfaceInfo.getDpId(); int elanTag = elanInfo.getElanTag().intValue(); long groupId = ElanUtils.getElanRemoteBCGID(elanTag); + List listBucket = new ArrayList(); + int bucketId = 0; ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); if(elanDpns != null) { List dpnInterfaceses = elanDpns.getDpnInterfaces(); for(DpnInterfaces dpnInterface : dpnInterfaceses) { - List remoteListBucketInfo = new ArrayList(); + List remoteListBucketInfo = new ArrayList(); if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpnId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { + for(String ifName : dpnInterface.getInterfaces()) { + // In case if there is a InterfacePort in the cache which is not in + // operational state, skip processing it + InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType()); + if (!isOperational(ifInfo)) { + continue; + } + + listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); + bucketId++; + } + remoteListBucketInfo.addAll(listBucket); for(DpnInterfaces otherFes : dpnInterfaceses) { if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId() && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) { try { - //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. - //List remoteListActionInfo = itmManager.ITMIngressGetActions(dpnInterface.getDpId(), otherFes.getDpId(), (int) elanTag); - //remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); + List remoteListActionInfo = ElanUtils.getInternalItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), elanTag); + remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP)); + bucketId++; } catch (Exception ex) { logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() ); return; } } } - List remoteListActionInfo = new ArrayList(); - remoteListActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))})); - remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); - GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnInterface.getDpId(), groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, remoteListBucketInfo); - mdsalManager.installGroup(groupEntity); + List elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, + bucketId); + remoteListBucketInfo.addAll(elanL2GwDevicesBuckets); + + if (remoteListBucketInfo.size() == 0) { + logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId()); + continue; + } + Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo)); + mdsalManager.syncInstallGroup(dpnInterface.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND); } } } @@ -521,21 +674,26 @@ public class ElanInterfaceManager extends AbstractDataChangeListener elanDpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName()); if(elanDpns != null) { for(DpnInterfaces dpnInterface : elanDpns) { - List remoteListBucketInfo = new ArrayList(); + int bucketId = 0; + List remoteListBucket = new ArrayList(); if(ElanUtils.isDpnPresent(dstDpId) && dpnInterface.getDpId().equals(dstDpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { try { - //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. - //List remoteListActionInfo = itmManager.ITMIngressGetActions(interfaceInfo.getDpId(), dstDpId, (int) elanTag); - //remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); + List remoteListActionInfo = ElanUtils.getInternalItmEgressAction(interfaceInfo.getDpId(), dstDpId, elanTag); + remoteListBucket.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); + bucketId++; } catch (Exception ex) { logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), dstDpId); return; } - List remoteListActionInfo = new ArrayList(); - remoteListActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))})); - remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); - GroupEntity groupEntity = MDSALUtil.buildGroupEntity(interfaceInfo.getDpId(), groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, remoteListBucketInfo); - mdsalManager.installGroup(groupEntity); + List remoteListActionInfo = new ArrayList(); + remoteListActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))}).buildAction()); + remoteListBucket.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); + + List elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dstDpId, bucketId); + remoteListBucket.addAll(elanL2GwDevicesBuckets); + + Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucket)); + mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND); break; } } @@ -546,8 +704,8 @@ public class ElanInterfaceManager extends AbstractDataChangeListener getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo) { - return Lists.newArrayList(new BucketInfo(getInterfacePortActionInfos(interfaceInfo))); + private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) { + return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP); } private List getMatchesForElanTag(Long elanTag) { @@ -559,12 +717,55 @@ public class ElanInterfaceManager extends AbstractDataChangeListener getInstructionsForOutGroup( + + private List buildMatchesForVni(Long vni) { + List mkMatches = new ArrayList(); + MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id, + new BigInteger[]{BigInteger.valueOf(vni)} ); + mkMatches.add(match); + return mkMatches; + } + + private List getInstructionsForOutGroup( long groupId) { + List mkInstructions = new ArrayList(); + List actions = new ArrayList (); + actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction()); + mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0)); + return mkInstructions; + } + + private List getMatchesForElanTag(long elanTag, boolean isSHFlagSet) { + List mkMatches = new ArrayList(); + // Matching metadata + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet), + MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG})); + return mkMatches; + } + + + + + /** + * Builds the list of instructions to be installed in the External Tunnel table (38), which so far + * consists in writing the elanTag in metadata and send packet to the new DHCP table + * + * @param elanTag elanTag to be written in metadata when flow is selected + * @return the instructions ready to be installed in a flow + */ + private List getInstructionsExtTunnelTable(Long elanTag) { List mkInstructions = new ArrayList(); - List actionsInfos = new ArrayList (); - actionsInfos.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)})); - mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + mkInstructions.add(new InstructionInfo(InstructionType.write_metadata, + new BigInteger[] { + ElanUtils.getElanMetadataLabel(elanTag), + ElanUtils.getElanMetadataMask() + } ) ); + // TODO (eperefr) We should point to SMAC or DMAC depending on a configuration property to enable + // mac learning + mkInstructions.add(new InstructionInfo(InstructionType.goto_table, + new long[] { ElanConstants.ELAN_DMAC_TABLE })); + return mkInstructions; } @@ -574,6 +775,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener macEntries = elanInterfaceMac.getMacEntry(); for(MacEntry macEntry : macEntries) { PhysAddress physAddress = macEntry.getMacAddress(); - ElanUtils.setupMacFlows(elanInfo, interfaceInfo, macEntry.isIsStaticAddress() ? ElanConstants.STATIC_MAC_TIMEOUT : elanInfo.getMacTimeout(), physAddress.getValue()); + ElanUtils.setupMacFlows(elanInfo, + interfaceInfo, + macEntry.isIsStaticAddress() + ? ElanConstants.STATIC_MAC_TIMEOUT + : elanInfo.getMacTimeout(), physAddress.getValue()); } //Programming the remoteDMACFlows ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); @@ -601,7 +807,11 @@ public class ElanInterfaceManager extends AbstractDataChangeListener listBucket = new ArrayList(); + int bucketId = 0; + BigInteger dpnId = interfaceInfo.getDpId(); + long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag()); + + DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId); + for(String ifName : dpnInterfaces.getInterfaces()) { + // In case if there is a InterfacePort in the cache which is not in + // operational state, skip processing it + InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType()); + if (!isOperational(ifInfo)) { + continue; + } + + listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); + bucketId++; + } + List listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, interfaceInfo, bucketId); + listBucket.addAll(listBucketInfoRemote); + + Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket)); + logger.trace("installing the localBroadCast Group:{}", group); + mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND); + } + public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { - List listBucketInfo = new ArrayList(); + List listBucket = new ArrayList(); + int bucketId = 0; BigInteger dpnId = interfaceInfo.getDpId(); long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag()); @@ -646,82 +883,158 @@ public class ElanInterfaceManager extends AbstractDataChangeListener listBuckets = new ArrayList<>(); + int bucketId = 0; + listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId)); + //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo)); + Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets)); + logger.trace("deleted the localBroadCast Group:{}", group); + mdsalManager.syncRemoveGroup(dpnId, group); } - public void removeRemoteBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { - List listBucketInfo = getRemoteBCGroupBucketInfos(elanInfo, interfaceInfo); + public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + int bucketId = 0; + List listBuckets = new ArrayList<>(); + listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId)); + bucketId++; + listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo)); BigInteger dpnId = interfaceInfo.getDpId(); long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag()); - GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, listBucketInfo); - logger.trace("deleting the remoteBroadCast GroupEntity:{}", groupEntity); - mdsalManager.syncRemoveGroup(groupEntity); + Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets)); + logger.trace("deleting the remoteBroadCast group:{}", group); + mdsalManager.syncRemoveGroup(dpnId, group); + } + + /** + * Installs a flow in the External Tunnel table consisting in translating + * the VNI retrieved from the packet that came over a tunnel with a TOR into + * elanTag that will be used later in the ELANs pipeline. + * + * @param dpnId + * the dpn id + * @param elanInfo + * the elan info + */ + public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) { + long elanTag = elanInfo.getElanTag(); + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, + NwConstants.EXTERNAL_TUNNEL_TABLE, + getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag), + 5, // prio + elanInfo.getElanInstanceName(), // flowName + 0, // idleTimeout + 0, // hardTimeout + ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)), + buildMatchesForVni(elanInfo.getVni()), + getInstructionsExtTunnelTable(elanTag) ); + + mdsalManager.installFlow(flowEntity); + } + + /** + * Removes, from External Tunnel table, the flow that translates from VNI to elanTag. + * Important: ensure this method is only called whenever there is no other ElanInterface in the specified DPN + * + * @param dpnId DPN whose Ext Tunnel table is going to be modified + * @param elanInfo holds the elanTag needed for selecting the flow to be removed + */ + public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) { + // TODO (eperefr): Use DataStoreJobCoordinator in order to avoid that removing the last ElanInstance plus + // adding a new one does (almost at the same time) are executed in that exact order + + String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag()); + FlowEntity flowEntity = new FlowEntity(dpnId); + flowEntity.setFlowId(flowId); + mdsalManager.removeFlow(flowEntity); } public void setupTerminateServiceTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { long elanTag = elanInfo.getElanTag(); - //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. -// FlowEntity flowEntity = MDSALUtil.buildFlowEntity(interfaceInfo.getDpId(), ITMConstants.TERMINATING_SERVICE_TABLE, getFlowRef(ITMConstants.TERMINATING_SERVICE_TABLE, elanTag), -// 5, elanInfo.getElanInstanceName(), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), itmManager.getTunnelMatchesForServiceId(elanTag), -// getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag))); -// -// mdsalManager.installFlow(flowEntity); + Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag), + 5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag), + getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag))); + + mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity); } public void setupUnknownDMacTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { long elanTag = elanInfo.getElanTag(); - FlowEntity flowEntity = MDSALUtil.buildFlowEntity(interfaceInfo.getDpId(), ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag), - 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag), + Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/false), + 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/false), + getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag))); + + mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity); + + // only if vni is present in elanInfo, perform the following + if (elanInfo.getVni() != null && elanInfo.getVni() != 0) { + Flow flowEntity2 = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true), + 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/true), getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag))); + mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity2); + } - mdsalManager.installFlow(flowEntity); } + private void removeStaticELanFlows(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) { BigInteger dpId = interfaceInfo.getDpId(); - long elanTag = elanInfo.getElanTag(); /* * If there are not elan ports, remove the unknown smac and default dmac * flows */ DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpId); - if(dpnInterfaces == null) { - return; - } - List elanInterfaces = dpnInterfaces.getInterfaces(); - if (elanInterfaces == null || elanInterfaces.isEmpty()) { - + if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) { + // No more Elan Interfaces in this DPN logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId); removeDefaultTermFlow(dpId, elanInfo.getElanTag()); removeUnknownDmacFlow(dpId, elanInfo); - removeRemoteBroadcastGroup(elanInfo, interfaceInfo); + removeElanBroadcastGroup(elanInfo, interfaceInfo); removeLocalBroadcastGroup(elanInfo, interfaceInfo); + if ( elanInfo.getVni() != null && elanInfo.getVni().longValue() != 0 ) { + unsetExternalTunnelTable(dpId, elanInfo); + } + removeFilterEqualsTable(elanInfo, interfaceInfo); } else { + setupElanBroadcastGroups(elanInfo, interfaceInfo); setupLocalBroadcastGroups(elanInfo, interfaceInfo); + removeFilterEqualsTable(elanInfo, interfaceInfo); } } private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo) { - FlowEntity flowEntity = getUnknownDmacFlowEntity(dpId, elanInfo); - mdsalManager.syncRemoveFlow(flowEntity, ElanConstants.DELAY_TIME_IN_MILLISECOND); +// Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo); +// mdsalManager.removeFlow(dpId, flow); + Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, + elanInfo.getElanTag(), /*SH flag*/ false))) + .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE) + .build(); + mdsalManager.removeFlow(dpId, flow); + + if ( elanInfo.getVni() != null && elanInfo.getVni() > 0 ) { + Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, + elanInfo.getElanTag(), /*SH flag*/ true))) + .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE) + .build(); + mdsalManager.removeFlow(dpId, flow2); + } + + } private void removeDefaultTermFlow(BigInteger dpId, long elanTag) { - //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. - //itmManager.removeTerminatingServiceAction(dpId, (int) elanTag); + ElanUtils.removeTerminatingServiceAction(dpId, (int) elanTag); } private void bindService(ElanInstance elanInfo, String interfaceName) { @@ -753,46 +1066,42 @@ public class ElanInterfaceManager extends AbstractDataChangeListener mkMatches = new ArrayList(); - // Matching metadata - mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { - ElanUtils.getElanMetadataLabel(elanTag), - MetaDataUtil.METADATA_MASK_SERVICE })); - - List mkInstructions = new ArrayList(); - List actionsInfos = new ArrayList (); - actionsInfos.add(new ActionInfo(ActionType.group, new String[]{Long.toString(ElanUtils.getElanRemoteBCGID(elanTag))})); - mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); - - FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag), - 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), - mkMatches, mkInstructions); - return flowEntity; - } - private String getFlowRef(long tableId, long elanTag) { return new StringBuffer().append(tableId).append(elanTag).toString(); } - private List getInterfacePortActionInfos(InterfaceInfo interfaceInfo) { - List listActionInfo = new ArrayList(); - listActionInfo.add(getTunnelIdActionInfo(interfaceInfo.getInterfaceTag())); - listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[]{})); - return listActionInfo; + private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) { + return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString(); + } + + private List getInterfacePortActions(InterfaceInfo interfaceInfo) { + List listAction = new ArrayList(); + int actionKey = 0; + listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction()); + actionKey++; + listAction.add((new ActionInfo(ActionType.nx_resubmit, + new String[] {String.valueOf(ElanConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction()); + return listAction; } private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List interfaceNames) { - if(!interfaceNames.isEmpty()) { - DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId) - .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build(); - MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), - dpnInterface); - } else { - MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId)); - } - + DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId) + .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), + dpnInterface); + } + + /** + * Delete elan dpn interface from operational DS. + * + * @param elanInstanceName + * the elan instance name + * @param dpId + * the dp id + */ + private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId) { + MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, + ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId)); } private List createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) { @@ -832,6 +1141,9 @@ public class ElanInterfaceManager extends AbstractDataChangeListener macAddresses = ElanUtils + .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName()); + if (macAddresses != null && !macAddresses.isEmpty()) { + ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInstance, macAddresses); + } + } } } @@ -973,27 +1294,97 @@ public class ElanInterfaceManager extends AbstractDataChangeListener dpns = ElanUtils.getInvolvedDpnsInElan(elanInfo + .getElanInstanceName()); + if (dpns == null) { + return; + } + for (DpnInterfaces dpn : dpns) { + bucketId = 0; + List listBucket = new ArrayList(); + bucketId = getLocalBcGroupBuckets(dpn, listBucket, bucketId); + getRemoteBCGroupBuckets(elanInfo, dpn.getDpId(), listBucket, + bucketId); + Group group = MDSALUtil.buildGroup(groupId, + elanInfo.getElanInstanceName(), GroupTypes.GroupAll, + MDSALUtil.buildBucketLists(listBucket)); + logger.trace("installing the localBroadCast Group:{}", group); + mdsalManager.syncInstallGroup(dpn.getDpId(), group, + ElanConstants.DELAY_TIME_IN_MILLISECOND); + } } - private List getInstructionsInPortForOutGroup( - String ifName) { - List mkInstructions = new ArrayList(); - List actionsInfos = new ArrayList (); - actionsInfos.addAll(ElanUtils.getEgressActionsForInterface(ifName)); - mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos)); - return mkInstructions; + private int getLocalBcGroupBuckets(DpnInterfaces dpn, + List listBucket, int bucketId) { + for (String intf : dpn.getInterfaces()) { + InterfaceInfo ifInfo = interfaceManager.getInterfaceInfo(intf); + if (!isOperational(ifInfo)) { + continue; + } + listBucket.add(MDSALUtil.buildBucket( + getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, + bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); + bucketId++; + } + return bucketId; } + private void getRemoteBCGroupBuckets(ElanInstance elanInfo, + BigInteger dpnId, List listBucket, int bucketId) { + int elanTag = elanInfo.getElanTag().intValue(); + ElanDpnInterfacesList elanDpns = ElanUtils + .getElanDpnInterfacesList(elanInfo.getElanInstanceName()); + if (elanDpns != null) { + List dpnInterfaceses = elanDpns.getDpnInterfaces(); + for (DpnInterfaces dpnInterface : dpnInterfaceses) { + if (ElanUtils.isDpnPresent(dpnInterface.getDpId()) + && dpnInterface.getDpId() != dpnId + && dpnInterface.getInterfaces() != null + && !dpnInterface.getInterfaces().isEmpty()) { + try { + List listActionInfo = ElanUtils + .getInternalItmEgressAction(dpnId, + dpnInterface.getDpId(), elanTag); + listBucket.add(MDSALUtil.buildBucket(listActionInfo, 0, + bucketId, 0xffffffffL, 0xffffffffL)); + bucketId++; + } catch (Exception ex) { + logger.error( + "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ", + dpnId, dpnInterface.getDpId()); + } + } + } + } + List elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId); + listBucket.addAll(elanL2GwDevicesBuckets); + } - - private List getInstructionsDrop() { - List mkInstructions = new ArrayList(); - List actionsInfos = new ArrayList (); - actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{})); - mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); - return mkInstructions; + public static List getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId, + int bucketId) { + List listBucketInfo = new ArrayList(); + ConcurrentMap map = ElanL2GwCacheUtils + .getAllElanL2GatewayDevicesFromCache(elanInfo.getElanInstanceName()); + for (L2GatewayDevice device : map.values()) { + String interfaceName = ElanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId), + device.getHwvtepNodeId()); + if (interfaceName == null) { + continue; + } + List listActionInfo = ElanUtils.buildItmEgressActions(interfaceName, elanInfo.getVni()); + listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, + MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP)); + bucketId++; + } + return listBucketInfo; } } + +