X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=vpnservice%2Faclservice%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Faclservice%2FAbstractAclServiceImpl.java;h=8b67508feb744ef13ea2e1b7e8419b215d977eea;hb=2fb2ed59e65d70d801bad72f4a0f8d110c972597;hp=61914f3f937d5b65dc36f20b095120d809dc7115;hpb=a6b0153d497356daa7a9f9ad91076374535a1d9a;p=netvirt.git diff --git a/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java b/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java index 61914f3f93..8b67508feb 100644 --- a/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java +++ b/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java @@ -7,38 +7,58 @@ */ package org.opendaylight.netvirt.aclservice; -import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.collect.Lists; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - +import java.util.SortedSet; +import java.util.stream.Collectors; import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator; +import org.opendaylight.genius.infra.ManagedNewTransactionRunner; +import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; import org.opendaylight.genius.mdsalutil.ActionInfo; import org.opendaylight.genius.mdsalutil.FlowEntity; import org.opendaylight.genius.mdsalutil.InstructionInfo; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.genius.mdsalutil.MatchInfoBase; import org.opendaylight.genius.mdsalutil.NwConstants; +import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack; +import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction; import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit; import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions; import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType; +import org.opendaylight.genius.mdsalutil.matches.MatchMetadata; +import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState; +import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; +import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache; import org.opendaylight.netvirt.aclservice.api.AclServiceListener; import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action; import org.opendaylight.netvirt.aclservice.api.utils.AclInterface; -import org.opendaylight.netvirt.aclservice.api.utils.AclInterfaceCacheUtil; +import org.opendaylight.netvirt.aclservice.utils.AclConntrackClassifierType; +import org.opendaylight.netvirt.aclservice.utils.AclConstants; import org.opendaylight.netvirt.aclservice.utils.AclDataUtil; +import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder; import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils; +import org.opendaylight.netvirt.aclservice.utils.StatefulAclServiceHelper; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs; import org.slf4j.Logger; @@ -50,31 +70,42 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { protected final IMdsalApiManager mdsalManager; protected final DataBroker dataBroker; + protected final ManagedNewTransactionRunner txRunner; protected final Class serviceMode; protected final AclDataUtil aclDataUtil; protected final AclServiceUtils aclServiceUtils; + protected final JobCoordinator jobCoordinator; + protected final AclInterfaceCache aclInterfaceCache; + + protected final Class direction; + protected final String directionString; /** * Initialize the member variables. * - * @param serviceMode - * the service mode - * @param dataBroker - * the data broker instance. - * @param mdsalManager - * the mdsal manager instance. - * @param aclDataUtil - * the acl data util. - * @param aclServiceUtils - * the acl service util. + * @param serviceMode the service mode + * @param dataBroker the data broker instance. + * @param mdsalManager the mdsal manager instance. + * @param aclDataUtil the acl data util. + * @param aclServiceUtils the acl service util. + * @param jobCoordinator the job coordinator + * @param aclInterfaceCache the acl interface cache */ public AbstractAclServiceImpl(Class serviceMode, DataBroker dataBroker, - IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, AclServiceUtils aclServiceUtils) { + IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, AclServiceUtils aclServiceUtils, + JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) { this.dataBroker = dataBroker; + this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); this.mdsalManager = mdsalManager; this.serviceMode = serviceMode; this.aclDataUtil = aclDataUtil; this.aclServiceUtils = aclServiceUtils; + this.jobCoordinator = jobCoordinator; + this.aclInterfaceCache = aclInterfaceCache; + + this.direction = + this.serviceMode.equals(ServiceModeEgress.class) ? DirectionIngress.class : DirectionEgress.class; + this.directionString = this.direction.equals(DirectionEgress.class) ? "Egress" : "Ingress"; } @Override @@ -84,7 +115,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { return false; } if (port.getSecurityGroups() == null) { - LOG.error("port security groups cannot be null"); + LOG.info("Port {} without SGs", port.getInterfaceId()); return false; } BigInteger dpId = port.getDpId(); @@ -93,7 +124,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { return false; } LOG.debug("Applying ACL on port {} with DpId {}", port, dpId); - programAclWithAllowedAddress(port, port.getAllowedAddressPairs(), Action.ADD, NwConstants.ADD_FLOW); + programAcl(port, Action.ADD, NwConstants.ADD_FLOW); updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW); return true; } @@ -101,7 +132,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { @Override public boolean bindAcl(AclInterface port) { if (port == null || port.getSecurityGroups() == null) { - LOG.error("port and port security groups cannot be null"); + LOG.error("Port and port security groups cannot be null for binding ACL service, port={}", port); return false; } bindService(port); @@ -113,13 +144,14 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { @Override public boolean unbindAcl(AclInterface port) { - BigInteger dpId = port.getDpId(); - if (dpId == null) { - LOG.error("Unable to find DpId from ACL interface with id {}", port.getInterfaceId()); + if (port == null) { + LOG.error("Port cannot be null for unbinding ACL service"); return false; } - unbindService(port); - updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW); + if (port.getDpId() != null) { + unbindService(port); + updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW); + } return true; } @@ -132,16 +164,16 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { return false; } boolean result = true; - boolean isPortSecurityEnable = portAfter.getPortSecurityEnabled(); - boolean isPortSecurityEnableBefore = portBefore.getPortSecurityEnabled(); + boolean isPortSecurityEnable = portAfter.isPortSecurityEnabled(); + boolean isPortSecurityEnableBefore = portBefore.isPortSecurityEnabled(); // if port security is changed, apply/remove Acls if (isPortSecurityEnableBefore != isPortSecurityEnable) { LOG.debug("On ACL update, Port security is {} for {}", isPortSecurityEnable ? "Enabled" : "Disabled", portAfter.getInterfaceId()); if (isPortSecurityEnable) { - result = applyAcl(portAfter) && bindAcl(portAfter); + result = applyAcl(portAfter); } else { - result = removeAcl(portBefore) && unbindAcl(portBefore); + result = removeAcl(portBefore); } } else if (isPortSecurityEnable) { // Acls has been updated, find added/removed Acls and act accordingly. @@ -154,94 +186,270 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) { BigInteger dpId = portAfter.getDpId(); - List addedAllowedAddressPairs = - AclServiceUtils.getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), - portBefore.getAllowedAddressPairs()); - List deletedAllowedAddressPairs = - AclServiceUtils.getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), - portAfter.getAllowedAddressPairs()); - if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) { - programAclWithAllowedAddress(portAfter, deletedAllowedAddressPairs, Action.UPDATE, NwConstants.DEL_FLOW); - } - if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) { - programAclWithAllowedAddress(portAfter, addedAllowedAddressPairs, Action.UPDATE, NwConstants.ADD_FLOW); - } - updateArpForAllowedAddressPairs(dpId, portAfter.getLPortTag(), deletedAllowedAddressPairs, - portAfter.getAllowedAddressPairs()); + List addedAaps = AclServiceUtils + .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs()); + List deletedAaps = AclServiceUtils + .getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs()); + if (deletedAaps != null && !deletedAaps.isEmpty()) { + programAclWithAllowedAddress(portBefore, deletedAaps, Action.UPDATE, NwConstants.DEL_FLOW); + updateRemoteAclFilterTable(portBefore, portBefore.getSecurityGroups(), deletedAaps, NwConstants.DEL_FLOW); + } + if (addedAaps != null && !addedAaps.isEmpty()) { + programAclWithAllowedAddress(portAfter, addedAaps, Action.UPDATE, NwConstants.ADD_FLOW); + updateRemoteAclFilterTable(portAfter, portAfter.getSecurityGroups(), addedAaps, NwConstants.ADD_FLOW); + } + updateArpForAllowedAddressPairs(dpId, portAfter.getLPortTag(), deletedAaps, portAfter.getAllowedAddressPairs()); if (portAfter.getSubnetIpPrefixes() != null && portBefore.getSubnetIpPrefixes() == null) { programBroadcastRules(portAfter, NwConstants.ADD_FLOW); } - updateAclInterfaceInCache(portBefore); - // Have to delete and add all rules because there can be following scenario: Interface1 with SG1, Interface2 - // with SG2 (which has ACE with remote SG1). Now When we add SG3 to Interface1, the rule for Interface2 which - // match the IP of Interface1 will not be installed (but it have to be because Interface1 has more than one SG). - // So we need to remove all rules and install them from 0, and we cannot handle only the delta. - updateCustomRules(portBefore, portBefore.getSecurityGroups(), NwConstants.DEL_FLOW, - portAfter.getAllowedAddressPairs()); - updateRemoteAclFilterTable(portBefore, NwConstants.DEL_FLOW); - - updateAclInterfaceInCache(portAfter); + List addedAcls = AclServiceUtils.getUpdatedAclList(portAfter.getSecurityGroups(), + portBefore.getSecurityGroups()); + List deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore.getSecurityGroups(), + portAfter.getSecurityGroups()); + if (deletedAcls.isEmpty() && addedAcls.isEmpty()) { + LOG.trace("No change w.r.t ACL list for port={}", portAfter.getInterfaceId()); + return; + } - updateCustomRules(portAfter, portAfter.getSecurityGroups(), NwConstants.ADD_FLOW, - portAfter.getAllowedAddressPairs()); - updateRemoteAclFilterTable(portAfter, NwConstants.ADD_FLOW); + handleAclChange(portBefore, deletedAcls, NwConstants.DEL_FLOW); + handleAclChange(portAfter, addedAcls, NwConstants.ADD_FLOW); } - private void updateAclInterfaceInCache(AclInterface aclInterfaceNew) { - AclInterfaceCacheUtil.addAclInterfaceToCache(aclInterfaceNew.getInterfaceId(), aclInterfaceNew); - aclDataUtil.addOrUpdateAclInterfaceMap(aclInterfaceNew.getSecurityGroups(), aclInterfaceNew); + private void handleAclChange(AclInterface port, List aclList, int addOrRemove) { + int operationForAclRules = (addOrRemove == NwConstants.DEL_FLOW) ? NwConstants.MOD_FLOW : addOrRemove; + programAclRules(port, aclList, operationForAclRules); + updateRemoteAclFilterTable(port, aclList, port.getAllowedAddressPairs(), addOrRemove); + programAclDispatcherTable(port, addOrRemove); } - private void updateCustomRules(AclInterface port, List aclUuidList, int action, - List syncAllowedAddresses) { - programAclRules(port, aclUuidList, action); - syncRemoteAclRules(aclUuidList, action, port.getInterfaceId(), syncAllowedAddresses); + protected SortedSet getRemoteAclTags(AclInterface port) { + return this.direction == DirectionIngress.class ? port.getIngressRemoteAclTags() + : port.getEgressRemoteAclTags(); } - private void syncRemoteAclRules(List aclUuidList, int action, String currentPortId, - List syncAllowedAddresses) { - if (aclUuidList == null) { - LOG.warn("security groups are null"); + protected void programAclDispatcherTable(AclInterface port, int addOrRemove) { + SortedSet remoteAclTags = getRemoteAclTags(port); + if (remoteAclTags.isEmpty()) { + LOG.debug("No {} rules with remote group id for port={}", this.directionString, port.getInterfaceId()); return; } + Integer firstRemoteAclTag = remoteAclTags.first(); + Integer lastRemoteAclTag = remoteAclTags.last(); - for (Uuid remoteAclId : aclUuidList) { - Map> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(remoteAclId); - if (mapAclWithPortSet == null) { + programFirstRemoteAclEntryInDispatcherTable(port, firstRemoteAclTag, addOrRemove); + programLastRemoteAclEntryInDispatcherTable(port, lastRemoteAclTag, addOrRemove); + + Integer previousRemoteAclTag = firstRemoteAclTag; + for (Integer remoteAclTag : remoteAclTags) { + if (remoteAclTag.equals(firstRemoteAclTag)) { continue; } - for (Entry> entry : mapAclWithPortSet.entrySet()) { - String aclName = entry.getKey(); - for (AclInterface port : entry.getValue()) { - if (currentPortId.equals(port.getInterfaceId()) - || (port.getSecurityGroups() != null && port.getSecurityGroups().size() == 1)) { - continue; - } - List remoteAceList = AclServiceUtils.getAceWithRemoteAclId(dataBroker, port, remoteAclId); - for (Ace ace : remoteAceList) { - programAceRule(port, action, aclName, ace, syncAllowedAddresses); - } - } - } + List matches = new ArrayList<>(); + matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), + previousRemoteAclTag, serviceMode)); + String flowId = this.directionString + "_ACL_Dispatcher_" + port.getDpId() + "_" + port.getLPortTag() + "_" + + remoteAclTag; + + List instructions = + AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable()); + instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(remoteAclTag)); + syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId, + AclConstants.ACE_GOTO_NEXT_REMOTE_ACL_PRIORITY, "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, + instructions, addOrRemove); + + previousRemoteAclTag = remoteAclTag; } } + protected void programFirstRemoteAclEntryInDispatcherTable(AclInterface port, Integer firstRemoteAclTag, + int addOrRemove) { + List matches = new ArrayList<>(); + matches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode)); + String flowId = this.directionString + "_ACL_Dispatcher_First_" + port.getDpId() + "_" + port.getLPortTag() + + "_" + firstRemoteAclTag; + + List instructions = + AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable()); + instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(firstRemoteAclTag)); + syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId, AclConstants.ACE_FIRST_REMOTE_ACL_PRIORITY, + "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove); + } + + protected void programLastRemoteAclEntryInDispatcherTable(AclInterface port, Integer lastRemoteAclTag, + int addOrRemove) { + List matches = new ArrayList<>(); + matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), lastRemoteAclTag, + serviceMode)); + String flowId = this.directionString + "_ACL_Dispatcher_Last_" + port.getDpId() + "_" + port.getLPortTag() + "_" + + lastRemoteAclTag; + + List instructions = AclServiceOFFlowBuilder.getDropInstructionInfo(); + syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId, AclConstants.ACE_LAST_REMOTE_ACL_PRIORITY, + "ACL", 0, 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove); + } + + private void programAcl(AclInterface port, Action action, int addOrRemove) { + programAclWithAllowedAddress(port, port.getAllowedAddressPairs(), action, addOrRemove); + } + private void programAclWithAllowedAddress(AclInterface port, List allowedAddresses, Action action, int addOrRemove) { BigInteger dpId = port.getDpId(); int lportTag = port.getLPortTag(); LOG.debug("Applying ACL Allowed Address on DpId {}, lportTag {}, Action {}", dpId, lportTag, action); - List aclUuidList = port.getSecurityGroups(); String portId = port.getInterfaceId(); programGeneralFixedRules(port, "", allowedAddresses, action, addOrRemove); - programSpecificFixedRules(dpId, "", allowedAddresses, lportTag, portId, action, addOrRemove); + programAclPortSpecificFixedRules(dpId, allowedAddresses, lportTag, portId, action, addOrRemove); if (action == Action.ADD || action == Action.REMOVE) { - programAclRules(port, aclUuidList, addOrRemove); + programAclRules(port, port.getSecurityGroups(), addOrRemove); + programAclDispatcherTable(port, addOrRemove); + } + } + + + /** + * Programs the acl custom rules. + * + * @param port acl interface + * @param aclUuidList the list of acl uuid to be applied + * @param addOrRemove whether to delete or add flow + * @return program succeeded + */ + protected boolean programAclRules(AclInterface port, List aclUuidList, int addOrRemove) { + BigInteger dpId = port.getDpId(); + LOG.debug("Applying custom rules on DpId {}, lportTag {}", dpId, port.getLPortTag()); + if (aclUuidList == null || dpId == null) { + LOG.warn("{} ACL parameters can not be null. dpId={}, aclUuidList={}", this.directionString, dpId, + aclUuidList); + return false; + } + for (Uuid aclUuid : aclUuidList) { + Acl acl = AclServiceUtils.getAcl(dataBroker, aclUuid.getValue()); + if (null == acl) { + LOG.warn("The ACL {} not found in config DS", aclUuid.getValue()); + continue; + } + AccessListEntries accessListEntries = acl.getAccessListEntries(); + List aceList = accessListEntries.getAce(); + for (Ace ace: aceList) { + programAceRule(port, ace, addOrRemove); + } + } + return true; + } + + /** + * Programs the ace specific rule. + * + * @param port acl interface + * @param ace rule to be program + * @param addOrRemove whether to delete or add flow + */ + protected void programAceRule(AclInterface port, Ace ace, int addOrRemove) { + SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace); + if (!isValidDirection(aceAttr.getDirection())) { + LOG.trace("Ignoring {} direction while processing for {} ACE Rule {}", aceAttr.getDirection(), + this.directionString, ace.getRuleName()); + return; + } + LOG.debug("Program {} ACE rule for dpId={}, lportTag={}, addOrRemove={}, ace={}, portId={}", + this.directionString, port.getDpId(), port.getLPortTag(), addOrRemove, ace.getRuleName(), + port.getInterfaceId()); + + Matches matches = ace.getMatches(); + Map> flowMap = null; + if (matches.getAceType() instanceof AceIp) { + flowMap = AclServiceOFFlowBuilder.programIpFlow(matches); + if (!AclServiceUtils.doesAceHaveRemoteGroupId(aceAttr)) { + // programming for ACE which doesn't have any remote group Id + programForAceNotHavingRemoteAclId(port, ace, flowMap, addOrRemove); + } else { + Uuid remoteAclId = aceAttr.getRemoteGroupId(); + // programming for ACE which have remote group Id + programAceSpecificFlows(port, ace, flowMap, remoteAclId, addOrRemove); + } } - syncRemoteAclRules(aclUuidList, addOrRemove, portId, allowedAddresses); } + protected void programForAceNotHavingRemoteAclId(AclInterface port, Ace ace, + Map> flowMap, int addOrRemove) { + if (null == flowMap) { + return; + } + + MatchInfoBase lportTagMatch = AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode); + for (Entry> entry : flowMap.entrySet()) { + String flowName = entry.getKey(); + List matches = entry.getValue(); + matches.add(lportTagMatch); + String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_" + + ace.getKey().getRuleName(); + + List instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable()); + int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove; + syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId, + AclConstants.ACE_WITHOUT_REMOTE_ACL_PRIORITY, "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, + instructions, operation); + + if (addOrRemove != NwConstants.DEL_FLOW) { + programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, + AclConstants.ACE_WITHOUT_REMOTE_ACL_PRIORITY); + } + } + } + + protected void programAceSpecificFlows(AclInterface port, Ace ace, Map> flowMap, + Uuid remoteAclId, int addOrRemove) { + if (null == flowMap) { + return; + } + Integer remoteAclTag = this.aclServiceUtils.getAclTag(remoteAclId); + if (remoteAclTag == null || remoteAclTag == AclConstants.INVALID_ACL_TAG) { + LOG.error("Failed building metadata match for ACL={}. Failed to allocate id", remoteAclId.getValue()); + return; + } + + for (Entry> entry : flowMap.entrySet()) { + String flowName = entry.getKey(); + List matches = entry.getValue(); + matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), + remoteAclTag, serviceMode)); + String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_" + + ace.getKey().getRuleName(); + + List instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRemoteAclTable()); + int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove; + syncFlow(port.getDpId(), getAclRuleBasedFilterTable(), flowId, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, + 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation); + + if (addOrRemove != NwConstants.DEL_FLOW) { + programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, + AclConstants.ACL_DEFAULT_PRIORITY); + } + } + } + + private void programAclForExistingTrafficTable(AclInterface port, Ace ace, int addOrRemove, String flowName, + List matches, Integer priority) { + AceIp acl = (AceIp) ace.getMatches().getAceType(); + final String newFlowName = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + + "_" + ((acl.getAceIpVersion() instanceof AceIpv4) ? "_IPv4" : "_IPv6") + "_FlowAfterRuleDeleted"; + + final List newMatches = + matches.stream().filter(obj -> !(obj instanceof NxMatchCtState || obj instanceof MatchMetadata)) + .collect(Collectors.toList()); + newMatches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode)); + newMatches.add(new NxMatchCtState(AclConstants.TRACKED_RPL_CT_STATE, AclConstants.TRACKED_RPL_CT_STATE_MASK)); + + List instructions = StatefulAclServiceHelper + .createCtMarkInstructionForNewState(getAclFilterCumDispatcherTable(), port.getElanId()); + // Reversing the flow add/delete operation for this table. + int operation = (addOrRemove == NwConstants.ADD_FLOW) ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW; + syncFlow(port.getDpId(), getAclForExistingTrafficTable(), newFlowName, priority, "ACL", 0, + StatefulAclServiceHelper.getHardTimoutForApplyStatefulChangeOnExistingTraffic(ace, aclServiceUtils), + AclConstants.COOKIE_ACL_BASE, newMatches, instructions, operation); + } @Override public boolean removeAcl(AclInterface port) { @@ -250,8 +458,8 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { LOG.error("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId()); return false; } - programAclWithAllowedAddress(port, port.getAllowedAddressPairs(), Action.REMOVE, NwConstants.DEL_FLOW); - updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW, true); + programAcl(port, Action.REMOVE, NwConstants.DEL_FLOW); + updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW); return true; } @@ -260,8 +468,10 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { if (!port.isPortSecurityEnabled() || port.getDpId() == null) { return false; } - programAceRule(port, NwConstants.ADD_FLOW, aclName, ace, null); - updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW); + programAceRule(port, ace, NwConstants.ADD_FLOW); + // TODO: If this is the first port on the DPN for a remote ACL, add + // remote ACL flows. + // updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW); return true; } @@ -270,8 +480,10 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { if (!port.isPortSecurityEnabled() || port.getDpId() == null) { return false; } - programAceRule(port, NwConstants.DEL_FLOW, aclName, ace, null); - updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW); + programAceRule(port, ace, NwConstants.MOD_FLOW); + // TODO: If this is the last port on the DPN for a remote ACL, delete + // remote ACL flows. + // updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW); return true; } @@ -312,42 +524,6 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { protected abstract void updateArpForAllowedAddressPairs(BigInteger dpId, int lportTag, List deletedAAP, List addedAAP); - /** - * Program the default specific rules. - * - * @param dpid the dpid - * @param dhcpMacAddress the dhcp mac address. - * @param allowedAddresses the allowed addresses - * @param lportTag the lport tag - * @param portId the port id - * @param action add/modify/remove action - * @param addOrRemove addorRemove - */ - protected abstract void programSpecificFixedRules(BigInteger dpid, String dhcpMacAddress, - List allowedAddresses, int lportTag, String portId, Action action, int addOrRemove); - - /** - * Programs the acl custom rules. - * - * @param port acl interface - * @param aclUuidList the list of acl uuid to be applied - * @param addOrRemove whether to delete or add flow - * @return program succeeded - */ - protected abstract boolean programAclRules(AclInterface port, List aclUuidList, int addOrRemove); - - /** - * Programs the ace custom rule. - * - * @param port acl interface - * @param addOrRemove whether to delete or add flow - * @param aclName the acl name - * @param ace rule to be program - * @param syncAllowedAddresses the allowed addresses - */ - protected abstract void programAceRule(AclInterface port, int addOrRemove, String aclName, Ace ace, - List syncAllowedAddresses); - /** * Programs broadcast rules. * @@ -385,26 +561,27 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName, int idleTimeOut, int hardTimeOut, BigInteger cookie, List matches, List instructions, int addOrRemove) { - DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance(); - dataStoreCoordinator.enqueueJob(flowName, () -> { - List> futures = new ArrayList<>(); + jobCoordinator.enqueueJob(flowName, () -> { if (addOrRemove == NwConstants.DEL_FLOW) { FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, null); LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId); - futures.add(mdsalManager.removeFlow(dpId, flowEntity)); + return Collections.singletonList(mdsalManager.removeFlow(dpId, flowEntity)); } else { FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, instructions); LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId); - futures.add(mdsalManager.installFlow(dpId, flowEntity)); + return Collections.singletonList(mdsalManager.installFlow(dpId, flowEntity)); } - return futures; }); } + protected List getDispatcherTableResubmitInstructions() { + return getDispatcherTableResubmitInstructions(new ArrayList<>()); + } + /** * Gets the dispatcher table resubmit instructions based on ingress/egress service mode w.r.t switch. * @@ -425,43 +602,36 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { } private void updateRemoteAclFilterTable(AclInterface port, int addOrRemove) { - updateRemoteAclFilterTable(port, addOrRemove, false); + updateRemoteAclFilterTable(port, port.getSecurityGroups(), port.getAllowedAddressPairs(), addOrRemove); } - private void updateRemoteAclFilterTable(AclInterface port, int addOrRemove, boolean isAclDeleted) { - if (port.getSecurityGroups() == null) { + private void updateRemoteAclFilterTable(AclInterface port, List aclList, List aaps, + int addOrRemove) { + if (aclList == null) { LOG.debug("Port {} without SGs", port.getInterfaceId()); return; } - - if (AclServiceUtils.exactlyOneAcl(port)) { - Uuid acl = port.getSecurityGroups().get(0); - BigInteger aclId = aclServiceUtils.buildAclId(acl); + for (Uuid acl : aclList) { if (aclDataUtil.getRemoteAcl(acl) != null) { Map> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(acl); Set dpns = collectDpns(mapAclWithPortSet); + Integer aclTag = aclServiceUtils.getAclTag(acl); - for (AllowedAddressPairs ip : port.getAllowedAddressPairs()) { + for (AllowedAddressPairs ip : aaps) { if (!AclServiceUtils.isNotIpv4AllNetwork(ip)) { continue; } for (BigInteger dpId : dpns) { - updateRemoteAclTableForPort(port, acl, addOrRemove, ip, aclId, dpId); + programRemoteAclTableFlow(dpId, aclTag, ip, addOrRemove); } } - syncRemoteAclTableFromOtherDpns(port, acl, aclId, addOrRemove); - } else { - LOG.debug("Port {} with more than one SG ({}). Don't change ACL filter table", port.getInterfaceId(), - port.getSecurityGroups().size()); + syncRemoteAclTableFromOtherDpns(port, acl, aclTag, addOrRemove); } - } else if (port.getSecurityGroups() != null && port.getSecurityGroups().size() > 1) { - updateRemoteAclTableForMultipleAcls(port, addOrRemove, port.getInterfaceId()); } - syncRemoteAclTable(port, addOrRemove, port.getInterfaceId(), isAclDeleted); } - private void syncRemoteAclTableFromOtherDpns(AclInterface port, Uuid acl, BigInteger aclId, int addOrRemove) { - List aclInterfaces = aclDataUtil.getInterfaceList(acl); + private void syncRemoteAclTableFromOtherDpns(AclInterface port, Uuid acl, Integer aclTag, int addOrRemove) { + Collection aclInterfaces = aclDataUtil.getInterfaceList(acl); BigInteger dpId = port.getDpId(); boolean isFirstPortInDpn = true; if (aclInterfaces != null) { @@ -480,110 +650,15 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { continue; } for (AllowedAddressPairs ip : aclInterface.getAllowedAddressPairs()) { - updateRemoteAclTableForPort(aclInterface, acl, addOrRemove, ip, aclId, port.getDpId()); - } - } - } - } - } - - private void syncRemoteAclTable(AclInterface port, int addOrRemove, String ignorePort, boolean isAclDeleted) { - for (Uuid aclUuid : port.getSecurityGroups()) { - if (aclDataUtil.getRemoteAcl(aclUuid) == null) { - continue; - } - List aclInterfaces = aclDataUtil.getInterfaceList(aclUuid); - if (aclInterfaces != null) { - for (AclInterface aclInterface : aclInterfaces) { - if (aclInterface.getInterfaceId().equals(port.getInterfaceId()) - || AclServiceUtils.exactlyOneAcl(aclInterface)) { - continue; - } - boolean allMultipleAcls = true; - List remoteInterfaceRemoteAcls = aclInterface.getSecurityGroups(); - if (remoteInterfaceRemoteAcls != null) { - for (Uuid remoteInterfaceRemoteAcl : remoteInterfaceRemoteAcls) { - if (aclDataUtil.getRemoteAcl(remoteInterfaceRemoteAcl) == null) { - continue; - } - List aclInterfaces2 = aclDataUtil.getInterfaceList(remoteInterfaceRemoteAcl); - if (aclInterfaces2 != null) { - for (AclInterface aclInterface2 : aclInterfaces2) { - if (aclInterface2.getInterfaceId().equals(aclInterface.getInterfaceId())) { - continue; - } - if (aclInterface2.getSecurityGroups().size() == 1) { - allMultipleAcls = false; - break; - } - } - } - } - } - int addRremove = (allMultipleAcls) ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW; - addRremove = (isAclDeleted) ? NwConstants.DEL_FLOW : addRremove; - for (AllowedAddressPairs ip : aclInterface.getAllowedAddressPairs()) { - if (!AclServiceUtils.isNotIpv4AllNetwork(ip)) { - continue; - } - updateRemoteAclTableForPort(aclInterface, aclUuid, addRremove, ip, - aclServiceUtils.buildAclId(aclUuid), aclInterface.getDpId()); - } - } - } - } - } - - private void updateRemoteAclTableForMultipleAcls(AclInterface port, int addOrRemove, String ignorePort) { - for (Uuid aclUuid : port.getSecurityGroups()) { - if (aclDataUtil.getRemoteAcl(aclUuid) == null) { - continue; - } - Acl acl = AclServiceUtils.getAcl(dataBroker, aclUuid.getValue()); - if (null == acl) { - LOG.debug("The ACL {} is empty", aclUuid); - return; - } - - Map> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(aclUuid); - Set dpns = collectDpns(mapAclWithPortSet); - - AccessListEntries accessListEntries = acl.getAccessListEntries(); - List aceList = accessListEntries.getAce(); - for (Ace ace : aceList) { - SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace); - if (aceAttr.getRemoteGroupId() == null) { - continue; - } - List interfaceList = aclDataUtil.getInterfaceList(aceAttr.getRemoteGroupId()); - if (interfaceList == null) { - continue; - } - - for (AclInterface inter : interfaceList) { - if (ignorePort.equals(inter.getInterfaceId())) { - continue; - } - if (inter.getSecurityGroups() != null && inter.getSecurityGroups().size() == 1) { - BigInteger aclId = aclServiceUtils.buildAclId(aceAttr.getRemoteGroupId()); - for (AllowedAddressPairs ip : port.getAllowedAddressPairs()) { - if (!AclServiceUtils.isNotIpv4AllNetwork(ip)) { - continue; - } - for (BigInteger dpnId : dpns) { - updateRemoteAclTableForPort(port, aceAttr.getRemoteGroupId(), addOrRemove, ip, aclId, - dpnId); - } - } - syncRemoteAclTableFromOtherDpns(port, aclUuid, aclId, addOrRemove); + programRemoteAclTableFlow(port.getDpId(), aclTag, ip, addOrRemove); } } } } } - protected abstract void updateRemoteAclTableForPort(AclInterface port, Uuid acl, int addOrRemove, - AllowedAddressPairs ip, BigInteger aclId, BigInteger dpId); + protected abstract void programRemoteAclTableFlow(BigInteger dpId, Integer aclTag, AllowedAddressPairs ip, + int addOrRemove); protected String getOperAsString(int flowOper) { String oper; @@ -619,33 +694,216 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { return dpns; } - protected char[] getIpPrefixOrAddress(AllowedAddressPairs ip) { - if (ip.getIpAddress().getIpAddress() != null) { - return ip.getIpAddress().getIpAddress().getValue(); - } else if (ip.getIpAddress().getIpPrefix() != null) { - return ip.getIpAddress().getIpPrefix().getValue(); + /** + * Programs the port specific fixed rules. + * + * @param dpId the dp id + * @param allowedAddresses the allowed addresses + * @param lportTag the lport tag + * @param portId the portId + * @param action the action + * @param write whether to add or remove the flow. + */ + protected void programAclPortSpecificFixedRules(BigInteger dpId, List allowedAddresses, + int lportTag, String portId, Action action, int write) { + programGotoClassifierTableRules(dpId, allowedAddresses, lportTag, write); + if (action == Action.ADD || action == Action.REMOVE) { + programConntrackRecircRules(dpId, allowedAddresses, lportTag, portId, write); + programPortSpecificDropRules(dpId, lportTag, write); + programAclCommitRules(dpId, lportTag, portId, write); } - return null; + LOG.info("programAclPortSpecificFixedRules: flows for dpId={}, lportId={}, action={}, write={}", dpId, lportTag, + action, write); } + protected abstract void programGotoClassifierTableRules(BigInteger dpId, List aaps, + int lportTag, int addOrRemove); + /** - * Gets the priority of acl flow which is to be either removed or added. + * Adds the rule to send the packet to the netfilter to check whether it is a known packet. * - * @param poolName - * the acl pool name - * @param flowName - * the flow name - * @param addOrRemove - * add or remove the entries. - * @return the acl flow priority + * @param dpId the dpId + * @param aaps the allowed address pairs + * @param lportTag the lport tag + * @param portId the portId + * @param addOrRemove whether to add or remove the flow + */ + protected void programConntrackRecircRules(BigInteger dpId, List aaps, int lportTag, + String portId, int addOrRemove) { + if (AclServiceUtils.doesIpv4AddressExists(aaps)) { + programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove); + } + if (AclServiceUtils.doesIpv6AddressExists(aaps)) { + programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove); + } + } + + protected void programConntrackRecircRule(BigInteger dpId, int lportTag, String portId, + MatchEthernetType matchEtherType, int addOrRemove) { + List matches = new ArrayList<>(); + matches.add(matchEtherType); + matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode)); + + List instructions = new ArrayList<>(); + if (addOrRemove == NwConstants.ADD_FLOW) { + Long elanTag = getElanIdFromAclInterface(portId); + if (elanTag == null) { + LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={},", portId, + dpId, lportTag, addOrRemove); + return; + } + List actionsInfos = new ArrayList<>(); + actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(), getAclForExistingTrafficTable())); + instructions.add(new InstructionApplyActions(actionsInfos)); + } + + String flowName = + this.directionString + "_Fixed_Conntrk_" + dpId + "_" + lportTag + "_" + matchEtherType + "_Recirc"; + syncFlow(dpId, getAclConntrackSenderTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0, + AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove); + } + + /** + * Adds the rules to drop the unknown/invalid packets . + * + * @param dpId the dpId + * @param lportTag the lport tag + * @param addOrRemove whether to add or remove the flow + */ + protected void programPortSpecificDropRules(BigInteger dpId, int lportTag, int addOrRemove) { + LOG.debug("Programming Drop Rules: DpId={}, lportTag={}, addOrRemove={}", dpId, lportTag, addOrRemove); + programConntrackInvalidDropRule(dpId, lportTag, addOrRemove); + programAclRuleMissDropRule(dpId, lportTag, addOrRemove); + } + + /** + * Adds the rule to drop the conntrack invalid packets . + * + * @param dpId the dpId + * @param lportTag the lport tag + * @param addOrRemove whether to add or remove the flow + */ + protected void programConntrackInvalidDropRule(BigInteger dpId, int lportTag, int addOrRemove) { + List matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag, + AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, serviceMode); + List instructions = AclServiceOFFlowBuilder.getDropInstructionInfo(); + + String flowId = this.directionString + "_Fixed_Conntrk_Drop" + dpId + "_" + lportTag + "_Tracked_Invalid"; + syncFlow(dpId, getAclFilterCumDispatcherTable(), flowId, AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, "ACL", + 0, 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove); + } + + /** + * Program ACL rule miss drop rule for a port. + * + * @param dpId the dp id + * @param lportTag the lport tag + * @param addOrRemove the add or remove + */ + protected void programAclRuleMissDropRule(BigInteger dpId, int lportTag, int addOrRemove) { + List matches = new ArrayList<>(); + matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode)); + List instructions = AclServiceOFFlowBuilder.getDropInstructionInfo(); + + String flowId = this.directionString + "_Fixed_Acl_Rule_Miss_Drop_" + dpId + "_" + lportTag; + syncFlow(dpId, getAclFilterCumDispatcherTable(), flowId, AclConstants.CT_STATE_TRACKED_NEW_DROP_PRIORITY, "ACL", + 0, 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove); + } + + /** + * Program acl commit rules. + * + * @param dpId the dp id + * @param lportTag the lport tag + * @param portId the port id + * @param addOrRemove the add or remove + */ + protected void programAclCommitRules(BigInteger dpId, int lportTag, String portId, int addOrRemove) { + programAclCommitRuleForConntrack(dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove); + programAclCommitRuleForConntrack(dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove); + programAclCommitRuleForNonConntrack(dpId, lportTag, addOrRemove); + } + + /** + * Program acl commit rule for conntrack. + * + * @param dpId the dp id + * @param lportTag the lport tag + * @param portId the port id + * @param matchEtherType the match ether type + * @param addOrRemove the add or remove */ - protected int getAclFlowPriority(String poolName, String flowName, int addOrRemove) { - int priority; - if (addOrRemove == NwConstants.DEL_FLOW) { - priority = aclServiceUtils.releaseAndRemoveFlowPriorityFromCache(poolName, flowName); - } else { - priority = aclServiceUtils.allocateAndSaveFlowPriorityInCache(poolName, flowName); + protected void programAclCommitRuleForConntrack(BigInteger dpId, int lportTag, String portId, + MatchEthernetType matchEtherType, int addOrRemove) { + List matches = new ArrayList<>(); + matches.add(matchEtherType); + matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode)); + matches.add( + AclServiceUtils.buildAclConntrackClassifierTypeMatch(AclConntrackClassifierType.CONNTRACK_SUPPORTED)); + + List actionsInfos = new ArrayList<>(); + if (addOrRemove == NwConstants.ADD_FLOW) { + Long elanId = getElanIdFromAclInterface(portId); + if (elanId == null) { + LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={}", portId, dpId, + lportTag, addOrRemove); + return; + } + List ctActionsList = + Lists.newArrayList(new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_EST_STATE)); + actionsInfos.add(new ActionNxConntrack(2, 1, 0, elanId.intValue(), (short) 255, ctActionsList)); } - return priority; + List instructions = getDispatcherTableResubmitInstructions(actionsInfos); + + String flowName = directionString + "_Acl_Commit_Conntrack_" + dpId + "_" + lportTag + "_" + matchEtherType; + // Flow for conntrack traffic to commit and resubmit to dispatcher + syncFlow(dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0, + AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove); } + + /** + * Program acl commit rule for non conntrack. + * + * @param dpId the dp id + * @param lportTag the lport tag + * @param addOrRemove the add or remove + */ + protected void programAclCommitRuleForNonConntrack(BigInteger dpId, int lportTag, int addOrRemove) { + List matches = new ArrayList<>(); + matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode)); + matches.add(AclServiceUtils + .buildAclConntrackClassifierTypeMatch(AclConntrackClassifierType.NON_CONNTRACK_SUPPORTED)); + + List instructions = getDispatcherTableResubmitInstructions(); + String flowName = this.directionString + "_Acl_Commit_Non_Conntrack_" + dpId + "_" + lportTag; + // Flow for non-conntrack traffic to resubmit to dispatcher + syncFlow(dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0, + AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove); + } + + protected Long getElanIdFromAclInterface(String elanInterfaceName) { + AclInterface aclInterface = aclInterfaceCache.get(elanInterfaceName); + if (null != aclInterface) { + return aclInterface.getElanId(); + } + return null; + } + + protected abstract boolean isValidDirection(Class direction); + + protected abstract short getAclAntiSpoofingTable(); + + protected abstract short getAclConntrackClassifierTable(); + + protected abstract short getAclConntrackSenderTable(); + + protected abstract short getAclForExistingTrafficTable(); + + protected abstract short getAclFilterCumDispatcherTable(); + + protected abstract short getAclRuleBasedFilterTable(); + + protected abstract short getAclRemoteAclTable(); + + protected abstract short getAclCommitterTable(); }