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=86a5b7e92ec548c846df8aca137e73fbbbf292b2;hb=00790a95c5e403cb62d2cc544af55e8ab3fef03b;hp=95460af6a37a1720e16c12cdcfbc099356c4b7e0;hpb=9c5a326cda49fd1ba17380c081e3dce70b9781a8;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 95460af6..86a5b7e9 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,30 +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.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; @@ -59,12 +93,17 @@ 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(); @@ -157,7 +196,9 @@ public class ElanInterfaceManager extends AbstractDataChangeListener macEntries = elanInterfaceMac.getMacEntry(); @@ -173,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); } } } @@ -244,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); + } } } @@ -291,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); } } @@ -357,11 +467,12 @@ public class ElanInterfaceManager extends AbstractDataChangeListener macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress); Optional existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId); @@ -370,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) { @@ -442,7 +543,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener listAction = ElanUtils.getItmEgressAction(dpnId, dpnInterface.getDpId(), (int) elanTag); + 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) { @@ -481,6 +582,8 @@ public class ElanInterfaceManager extends AbstractDataChangeListener elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId); + listBuckets.addAll(elanL2GwDevicesBuckets); } return listBuckets; } @@ -496,7 +599,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener listActionInfo = ElanUtils.getItmEgressAction(dpnId, dpnInterface.getDpId(), (int) elanTag); + List listActionInfo = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag); listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL)); bucketId++; } catch (Exception ex) { @@ -504,6 +607,9 @@ public class ElanInterfaceManager extends AbstractDataChangeListener elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId); + listBucketInfo.addAll(elanL2GwDevicesBuckets); } return listBucketInfo; } @@ -537,7 +643,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener remoteListActionInfo = ElanUtils.getItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), (int) elanTag); + 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) { @@ -546,7 +652,11 @@ public class ElanInterfaceManager extends AbstractDataChangeListener elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, + bucketId); + remoteListBucketInfo.addAll(elanL2GwDevicesBuckets); + + if (remoteListBucketInfo.size() == 0) { logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId()); continue; } @@ -568,7 +678,7 @@ public class ElanInterfaceManager extends AbstractDataChangeListener remoteListBucket = new ArrayList(); if(ElanUtils.isDpnPresent(dstDpId) && dpnInterface.getDpId().equals(dstDpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { try { - List remoteListActionInfo = ElanUtils.getItmEgressAction(interfaceInfo.getDpId(), dstDpId, (int) elanTag); + 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) { @@ -578,6 +688,10 @@ public class ElanInterfaceManager extends AbstractDataChangeListener 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; @@ -603,12 +717,55 @@ public class ElanInterfaceManager extends AbstractDataChangeListener 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(ElanUtils.getWriteActionInstruction(actions)); + 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(); + 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; } @@ -618,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()); @@ -645,7 +807,11 @@ public class ElanInterfaceManager extends AbstractDataChangeListener 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); removeElanBroadcastGroup(elanInfo, interfaceInfo); removeLocalBroadcastGroup(elanInfo, interfaceInfo); + if ( elanInfo.getVni() != null && elanInfo.getVni().longValue() != 0 ) { + unsetExternalTunnelTable(dpId, elanInfo); + } removeFilterEqualsTable(elanInfo, interfaceInfo); } else { setupElanBroadcastGroups(elanInfo, interfaceInfo); @@ -797,8 +1014,23 @@ public class ElanInterfaceManager extends AbstractDataChangeListener 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) { @@ -834,35 +1066,21 @@ 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))}, 0).buildAction()); - mkInstructions.add(ElanUtils.getWriteActionInstruction(actionsInfos)); - - Flow flow = MDSALUtil.buildFlowNew(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 flow; - } - private String getFlowRef(long tableId, long elanTag) { return new StringBuffer().append(tableId).append(elanTag).toString(); } + 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 BigInteger[] {BigInteger.valueOf(55)}, actionKey)).buildAction()); + listAction.add((new ActionInfo(ActionType.nx_resubmit, + new String[] {String.valueOf(ElanConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction()); return listAction; } @@ -873,6 +1091,19 @@ public class ElanInterfaceManager extends AbstractDataChangeListener createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) { List interfaceNames = new ArrayList(); interfaceNames.add(interfaceName); @@ -910,6 +1141,9 @@ public class ElanInterfaceManager extends AbstractDataChangeListener macAddresses = ElanUtils + .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName()); + if (macAddresses != null && !macAddresses.isEmpty()) { + ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInstance, macAddresses); + } + } } } @@ -1051,16 +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 getInstructionsDrop() { - List mkInstructions = new ArrayList(); - List actionsInfos = new ArrayList (); - actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{}).buildAction()); - mkInstructions.add(ElanUtils.getWriteActionInstruction(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); + } + + 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; } } + +