NETVIRT-1501: ACL: Used Batched transactions 24/78024/2
authorShashidhar Raja <shashidharr@altencalsoftlabs.com>
Tue, 13 Nov 2018 13:46:48 +0000 (19:16 +0530)
committerAswin Suryanarayanan <asuryana@redhat.com>
Thu, 22 Nov 2018 18:11:13 +0000 (18:11 +0000)
Currently, each ACL flow is configured in a separate transaction.
With the updated changes, flows programmed are batched to fewer
transactions. This will reduce number of transactions used
significantly to program same set of flows.

Change-Id: I8b4192b3b2d362102a2b297da1a6098f9321424c
Signed-off-by: Shashidhar Raja <shashidharr@altencalsoftlabs.com>
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/EgressAclServiceImpl.java
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/IngressAclServiceImpl.java
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclConstants.java

index cf159147c75a64825e23d8efa7c0a012ff40b998..40ee1cdff47f37966d4264501abadf3cf08121d4 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.netvirt.aclservice;
 
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+
 import com.google.common.collect.Lists;
 import java.math.BigInteger;
 import java.util.ArrayList;
@@ -22,7 +24,6 @@ import java.util.SortedSet;
 import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.genius.infra.Datastore;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
@@ -126,8 +127,10 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             return false;
         }
         LOG.debug("Applying ACL on port {} with DpId {}", port, dpId);
-        programAcl(port, Action.ADD, NwConstants.ADD_FLOW);
-        updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW);
+        List<FlowEntity> flowEntries = new ArrayList<>();
+        programAcl(flowEntries, port, Action.ADD, NwConstants.ADD_FLOW);
+        updateRemoteAclFilterTable(flowEntries, port, NwConstants.ADD_FLOW);
+        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.ADD_FLOW);
         return true;
     }
 
@@ -183,22 +186,27 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
     }
 
     private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
+        List<FlowEntity> addFlowEntries = new ArrayList<>();
+        List<FlowEntity> deleteFlowEntries = new ArrayList<>();
         List<AllowedAddressPairs> addedAaps = AclServiceUtils
                 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
         List<AllowedAddressPairs> 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);
+            programAclWithAllowedAddress(deleteFlowEntries, portBefore, deletedAaps, Action.UPDATE,
+                    NwConstants.DEL_FLOW);
+            updateRemoteAclFilterTable(deleteFlowEntries, 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);
+            programAclWithAllowedAddress(addFlowEntries, portAfter, addedAaps, Action.UPDATE, NwConstants.ADD_FLOW);
+            updateRemoteAclFilterTable(addFlowEntries, portAfter, portAfter.getSecurityGroups(), addedAaps,
+                    NwConstants.ADD_FLOW);
         }
         if (portAfter.getSubnetInfo() != null && portBefore.getSubnetInfo() == null) {
-            programBroadcastRules(portAfter, NwConstants.ADD_FLOW);
+            programBroadcastRules(addFlowEntries, portAfter, NwConstants.ADD_FLOW);
         }
-        handleSubnetChange(portBefore, portAfter);
+        handleSubnetChange(portBefore, portAfter, addFlowEntries, deleteFlowEntries);
 
         List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter.getSecurityGroups(),
                 portBefore.getSecurityGroups());
@@ -209,29 +217,35 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             return;
         }
 
-        handleAclChange(portBefore, deletedAcls, NwConstants.DEL_FLOW);
-        handleAclChange(portAfter, addedAcls, NwConstants.ADD_FLOW);
+        handleAclChange(deleteFlowEntries, portBefore, deletedAcls, NwConstants.DEL_FLOW);
+        handleAclChange(addFlowEntries, portAfter, addedAcls, NwConstants.ADD_FLOW);
+        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), deleteFlowEntries,
+                NwConstants.DEL_FLOW);
+        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), addFlowEntries,
+                NwConstants.ADD_FLOW);
     }
 
-    private void handleSubnetChange(AclInterface portBefore, AclInterface portAfter) {
+    private void handleSubnetChange(AclInterface portBefore, AclInterface portAfter,
+            List<FlowEntity> addFlowEntries, List<FlowEntity> deleteFlowEntries) {
         List<SubnetInfo> deletedSubnets =
                 AclServiceUtils.getSubnetDiff(portBefore.getSubnetInfo(), portAfter.getSubnetInfo());
         List<SubnetInfo> addedSubnets =
                 AclServiceUtils.getSubnetDiff(portAfter.getSubnetInfo(), portBefore.getSubnetInfo());
 
         if (deletedSubnets != null && !deletedSubnets.isEmpty()) {
-            programIcmpv6RARule(portAfter, deletedSubnets, NwConstants.DEL_FLOW);
+            programIcmpv6RARule(deleteFlowEntries, portAfter, deletedSubnets, NwConstants.DEL_FLOW);
         }
         if (addedSubnets != null && !addedSubnets.isEmpty()) {
-            programIcmpv6RARule(portAfter, addedSubnets, NwConstants.ADD_FLOW);
+            programIcmpv6RARule(addFlowEntries, portAfter, addedSubnets, NwConstants.ADD_FLOW);
         }
     }
 
-    private void handleAclChange(AclInterface port, List<Uuid> aclList, int addOrRemove) {
+    private void handleAclChange(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> 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);
+        programAclRules(flowEntries, port, aclList, operationForAclRules);
+        updateRemoteAclFilterTable(flowEntries, port, aclList, port.getAllowedAddressPairs(), addOrRemove);
+        programAclDispatcherTable(flowEntries, port, addOrRemove);
     }
 
     protected SortedSet<Integer> getRemoteAclTags(AclInterface port) {
@@ -239,7 +253,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
                 : port.getEgressRemoteAclTags();
     }
 
-    protected void programAclDispatcherTable(AclInterface port, int addOrRemove) {
+    protected void programAclDispatcherTable(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
         SortedSet<Integer> remoteAclTags = getRemoteAclTags(port);
         if (remoteAclTags.isEmpty()) {
             LOG.debug("No {} rules with remote group id for port={}", this.directionString, port.getInterfaceId());
@@ -248,8 +262,8 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         Integer firstRemoteAclTag = remoteAclTags.first();
         Integer lastRemoteAclTag = remoteAclTags.last();
 
-        programFirstRemoteAclEntryInDispatcherTable(port, firstRemoteAclTag, addOrRemove);
-        programLastRemoteAclEntryInDispatcherTable(port, lastRemoteAclTag, addOrRemove);
+        programFirstRemoteAclEntryInDispatcherTable(flowEntries, port, firstRemoteAclTag, addOrRemove);
+        programLastRemoteAclEntryInDispatcherTable(flowEntries, port, lastRemoteAclTag, addOrRemove);
 
         Integer previousRemoteAclTag = firstRemoteAclTag;
         for (Integer remoteAclTag : remoteAclTags) {
@@ -265,7 +279,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             List<InstructionInfo> instructions =
                     AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
             instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(remoteAclTag));
-            syncFlow(port.getDpId(), port.getInterfaceId(), getAclFilterCumDispatcherTable(), flowId,
+            addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId,
                     AclConstants.ACE_GOTO_NEXT_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
                     instructions, addOrRemove);
 
@@ -273,8 +287,8 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         }
     }
 
-    protected void programFirstRemoteAclEntryInDispatcherTable(AclInterface port, Integer firstRemoteAclTag,
-            int addOrRemove) {
+    protected void programFirstRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
+            Integer firstRemoteAclTag, int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
         String flowId = this.directionString + "_ACL_Dispatcher_First_" + port.getDpId() + "_" + port.getLPortTag()
@@ -283,13 +297,13 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         List<InstructionInfo> instructions =
                 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
         instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(firstRemoteAclTag));
-        syncFlow(port.getDpId(), port.getInterfaceId(), getAclFilterCumDispatcherTable(), flowId,
+        addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId,
                 AclConstants.ACE_FIRST_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
                 addOrRemove);
     }
 
-    protected void programLastRemoteAclEntryInDispatcherTable(AclInterface port, Integer lastRemoteAclTag,
-            int addOrRemove) {
+    protected void programLastRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
+            Integer lastRemoteAclTag, int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), lastRemoteAclTag,
                 serviceMode));
@@ -297,38 +311,40 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
                 + lastRemoteAclTag;
 
         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
-        syncFlow(port.getDpId(), port.getInterfaceId(), getAclFilterCumDispatcherTable(), flowId,
+        addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId,
                 AclConstants.ACE_LAST_REMOTE_ACL_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(port.getLPortTag()),
                 matches, instructions, addOrRemove);
     }
 
-    private void programAcl(AclInterface port, Action action, int addOrRemove) {
-        programAclWithAllowedAddress(port, port.getAllowedAddressPairs(), action, addOrRemove);
+    private void programAcl(List<FlowEntity> flowEntries, AclInterface port, Action action, int addOrRemove) {
+        programAclWithAllowedAddress(flowEntries, port, port.getAllowedAddressPairs(), action, addOrRemove);
     }
 
-    private void programAclWithAllowedAddress(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
-            Action action, int addOrRemove) {
+    private void programAclWithAllowedAddress(List<FlowEntity> flowEntries, AclInterface port,
+            List<AllowedAddressPairs> 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);
         String portId = port.getInterfaceId();
-        programAntiSpoofingRules(port, allowedAddresses, action, addOrRemove);
-        programAclPortSpecificFixedRules(dpId, allowedAddresses, lportTag, portId, action, addOrRemove);
+        programAntiSpoofingRules(flowEntries, port, allowedAddresses, action, addOrRemove);
+        programAclPortSpecificFixedRules(flowEntries, dpId, allowedAddresses, lportTag, portId, action, addOrRemove);
         if (action == Action.ADD || action == Action.REMOVE) {
-            programAclRules(port, port.getSecurityGroups(), addOrRemove);
-            programAclDispatcherTable(port, addOrRemove);
+            programAclRules(flowEntries, port, port.getSecurityGroups(), addOrRemove);
+            programAclDispatcherTable(flowEntries, port, addOrRemove);
         }
     }
 
     /**
      * Programs the acl custom rules.
      *
+     * @param flowEntries the flow entries
      * @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<Uuid> aclUuidList, int addOrRemove) {
+    protected boolean programAclRules(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclUuidList,
+            int addOrRemove) {
         BigInteger dpId = port.getDpId();
         LOG.debug("Applying custom rules on DpId {}, lportTag {}", dpId, port.getLPortTag());
         if (aclUuidList == null || dpId == null) {
@@ -345,7 +361,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             AccessListEntries accessListEntries = acl.getAccessListEntries();
             if (accessListEntries != null && accessListEntries.getAce() != null) {
                 for (Ace ace: accessListEntries.getAce()) {
-                    programAceRule(port, aclUuid.getValue(), ace, addOrRemove);
+                    programAceRule(flowEntries, port, aclUuid.getValue(), ace, addOrRemove);
                 }
             }
         }
@@ -355,12 +371,14 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
     /**
      * Programs the ace specific rule.
      *
+     * @param flowEntries flow entries
      * @param port acl interface
      * @param aclName the acl name
      * @param ace rule to be program
      * @param addOrRemove whether to delete or add flow
      */
-    protected void programAceRule(AclInterface port, String aclName, Ace ace, int addOrRemove) {
+    protected void programAceRule(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
+            int addOrRemove) {
         SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
         if (!isValidDirection(aceAttr.getDirection())) {
             LOG.trace("Ignoring {} direction while processing for {} ACE Rule {}", aceAttr.getDirection(),
@@ -376,17 +394,17 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             Map<String, List<MatchInfoBase>> flowMap = AclServiceOFFlowBuilder.programIpFlow(matches);
             if (!AclServiceUtils.doesAceHaveRemoteGroupId(aceAttr)) {
                 // programming for ACE which doesn't have any remote group Id
-                programForAceNotHavingRemoteAclId(port, aclName, ace, flowMap, addOrRemove);
+                programForAceNotHavingRemoteAclId(flowEntries, port, aclName, ace, flowMap, addOrRemove);
             } else {
                 Uuid remoteAclId = aceAttr.getRemoteGroupId();
                 // programming for ACE which have remote group Id
-                programAceSpecificFlows(port, aclName, ace, flowMap, remoteAclId, addOrRemove);
+                programAceSpecificFlows(flowEntries, port, aclName, ace, flowMap, remoteAclId, addOrRemove);
             }
         }
     }
 
-    protected void programForAceNotHavingRemoteAclId(AclInterface port, String aclName, Ace ace,
-            @Nullable Map<String, List<MatchInfoBase>> flowMap, int addOrRemove) {
+    protected void programForAceNotHavingRemoteAclId(List<FlowEntity> flowEntries, AclInterface port, String aclName,
+            Ace ace, @Nullable Map<String, List<MatchInfoBase>> flowMap, int addOrRemove) {
         if (null == flowMap) {
             return;
         }
@@ -402,7 +420,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
                     + ace.key().getRuleName();
 
             int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
-            syncFlow(port.getDpId(), port.getInterfaceId(), getAclFilterCumDispatcherTable(), flowId, flowPriority,
+            addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId, flowPriority,
                     0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
 
             if (addOrRemove != NwConstants.DEL_FLOW) {
@@ -411,7 +429,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         }
     }
 
-    protected void programAceSpecificFlows(AclInterface port, String aclName, Ace ace,
+    protected void programAceSpecificFlows(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
             @Nullable Map<String, List<MatchInfoBase>> flowMap, Uuid remoteAclId, int addOrRemove) {
         if (null == flowMap) {
             return;
@@ -434,12 +452,11 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
                     + ace.key().getRuleName();
 
             int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
-            syncFlow(port.getDpId(), port.getInterfaceId(), getAclRuleBasedFilterTable(), flowId, flowPriority,
-                    0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
+            addFlowEntryToList(flowEntries, port.getDpId(), getAclRuleBasedFilterTable(), flowId, flowPriority, 0, 0,
+                    AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
 
             if (addOrRemove != NwConstants.DEL_FLOW) {
-                programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches,
-                        flowPriority);
+                programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
             }
         }
     }
@@ -459,10 +476,12 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         List<InstructionInfo> instructions =
                 AclServiceUtils.createCtMarkInstructionForNewState(getAclFilterCumDispatcherTable(), port.getElanId());
         // Reversing the flow add/delete operation for this table.
+        List<FlowEntity> flowEntries = new ArrayList<>();
         int operation = (addOrRemove == NwConstants.ADD_FLOW) ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW;
-        syncFlow(port.getDpId(), port.getInterfaceId(), getAclForExistingTrafficTable(), newFlowName, priority, 0,
+        addFlowEntryToList(flowEntries, port.getDpId(), getAclForExistingTrafficTable(), newFlowName, priority, 0,
                 AclServiceUtils.getHardTimoutForApplyStatefulChangeOnExistingTraffic(ace, aclServiceUtils),
                 AclConstants.COOKIE_ACL_BASE, newMatches, instructions, operation);
+        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, operation);
     }
 
     @Override
@@ -471,8 +490,10 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             LOG.warn("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
             return false;
         }
-        programAcl(port, Action.REMOVE, NwConstants.DEL_FLOW);
-        updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW);
+        List<FlowEntity> flowEntries = new ArrayList<>();
+        programAcl(flowEntries, port, Action.REMOVE, NwConstants.DEL_FLOW);
+        updateRemoteAclFilterTable(flowEntries, port, NwConstants.DEL_FLOW);
+        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
         return true;
     }
 
@@ -481,7 +502,9 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
             return false;
         }
-        programAceRule(port, aclName, ace, NwConstants.ADD_FLOW);
+        List<FlowEntity> flowEntries = new ArrayList<>();
+        programAceRule(flowEntries, port, aclName, ace, NwConstants.ADD_FLOW);
+        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.ADD_FLOW);
         return true;
     }
 
@@ -490,7 +513,9 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
             return false;
         }
-        programAceRule(port, aclName, ace, NwConstants.MOD_FLOW);
+        List<FlowEntity> flowEntries = new ArrayList<>();
+        programAceRule(flowEntries, port, aclName, ace, NwConstants.MOD_FLOW);
+        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
         return true;
     }
 
@@ -516,31 +541,32 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
     /**
      * Programs the anti-spoofing rules.
      *
+     * @param flowEntries the flow entries
      * @param port the acl interface
      * @param allowedAddresses the allowed addresses
      * @param action add/modify/remove action
      * @param addOrRemove addorRemove
      */
-    protected abstract void programAntiSpoofingRules(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
-            Action action, int addOrRemove);
+    protected abstract void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
+            List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove);
 
     /**
      * Programs broadcast rules.
      *
+     * @param flowEntries the flow entries
      * @param port the Acl Interface port
      * @param addOrRemove whether to delete or add flow
      */
-    protected abstract void programBroadcastRules(AclInterface port, int addOrRemove);
+    protected abstract void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove);
 
-    protected abstract void programIcmpv6RARule(AclInterface port, List<SubnetInfo> subnets, int addOrRemove);
+    protected abstract void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port,
+            List<SubnetInfo> subnets, int addOrRemove);
 
     /**
-     * Writes/remove the flow to/from the datastore.
+     * Add Flow to list.
      *
      * @param dpId
      *            the dpId
-     * @param interfaceId
-     *            the interfaceId
      * @param tableId
      *            the tableId
      * @param flowId
@@ -560,23 +586,36 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
      * @param addOrRemove
      *            add or remove the entries.
      */
-    protected void syncFlow(BigInteger dpId, String interfaceId, short tableId, String flowId, int priority,
-            int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
+    protected void addFlowEntryToList(List<FlowEntity> flowEntries, BigInteger dpId, short tableId, String flowId,
+            int priority, int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
             List<InstructionInfo> instructions, int addOrRemove) {
-        jobCoordinator.enqueueJob((AclConstants.ACL_JOB_KEY_PREFIX + interfaceId), () -> {
-            if (addOrRemove == NwConstants.DEL_FLOW) {
-                LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
-                return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(
-                    Datastore.CONFIGURATION, tx -> mdsalManager.removeFlow(tx, dpId, flowId, tableId)));
-            } else {
-                FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority,
-                        flowId, idleTimeOut, hardTimeOut, cookie, matches, instructions);
-                LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
-                return Collections.singletonList(
-                    txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION,
-                        tx -> mdsalManager.addFlow(tx, flowEntity)));
-            }
-        });
+        List<InstructionInfo> instructionInfos = null;
+        if (addOrRemove == NwConstants.ADD_FLOW) {
+            instructionInfos = instructions;
+        }
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority,
+                flowId, idleTimeOut, hardTimeOut, cookie, matches, instructionInfos);
+        LOG.trace("Adding flow to list: DpnId {}, flowId {}", dpId, flowId);
+        flowEntries.add(flowEntity);
+    }
+
+    protected void programFlows(String jobName, List<FlowEntity> flowEntries, int addOrRemove) {
+        List<List<FlowEntity>> flowEntityParts = Lists.partition(flowEntries, AclConstants.FLOWS_PER_TRANSACTION);
+        for (List<FlowEntity> part : flowEntityParts) {
+            jobCoordinator.enqueueJob(jobName,
+                () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+                    tx -> {
+                        if (addOrRemove == NwConstants.ADD_FLOW) {
+                            for (FlowEntity flowEntity: part) {
+                                mdsalManager.addFlow(tx, flowEntity);
+                            }
+                        } else {
+                            for (FlowEntity flowEntity: part) {
+                                mdsalManager.removeFlow(tx, flowEntity);
+                            }
+                        }
+                    })), AclConstants.JOB_MAX_RETRIES);
+        }
     }
 
     protected List<InstructionInfo> getDispatcherTableResubmitInstructions() {
@@ -618,23 +657,29 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         Set<Uuid> remoteAclsDeleted = new HashSet<>(remoteAclsBefore);
         remoteAclsDeleted.removeAll(remoteAclsAfter);
 
+        List<FlowEntity> addFlowEntries = new ArrayList<>();
+        List<FlowEntity> deleteFlowEntries = new ArrayList<>();
         if (!remoteAclsAdded.isEmpty() || !remoteAclsDeleted.isEmpty()) {
             // delete and add flows in ACL dispatcher table for all applicable
             // ports
             for (AclInterface portBefore : portsBefore) {
-                programAclDispatcherTable(portBefore, NwConstants.DEL_FLOW);
+                programAclDispatcherTable(deleteFlowEntries, portBefore, NwConstants.DEL_FLOW);
             }
             for (AclInterface port : interfaceList) {
-                programAclDispatcherTable(port, NwConstants.ADD_FLOW);
+                programAclDispatcherTable(addFlowEntries, port, NwConstants.ADD_FLOW);
             }
         }
         Set<BigInteger> dpns = interfaceList.stream().map(AclInterface::getDpId).collect(Collectors.toSet());
 
-        programRemoteAclTable(aclName, remoteAclsDeleted, dpns, NwConstants.DEL_FLOW);
-        programRemoteAclTable(aclName, remoteAclsAdded, dpns, NwConstants.ADD_FLOW);
+        programRemoteAclTable(deleteFlowEntries, aclName, remoteAclsDeleted, dpns, NwConstants.DEL_FLOW);
+        programRemoteAclTable(addFlowEntries, aclName, remoteAclsAdded, dpns, NwConstants.ADD_FLOW);
+
+        programFlows(aclName, deleteFlowEntries, NwConstants.DEL_FLOW);
+        programFlows(aclName, addFlowEntries, NwConstants.ADD_FLOW);
     }
 
-    private void programRemoteAclTable(String aclName, Set<Uuid> remoteAclIds, Set<BigInteger> dpns, int addOrRemove) {
+    private void programRemoteAclTable(List<FlowEntity> flowEntries, String aclName, Set<Uuid> remoteAclIds,
+            Set<BigInteger> dpns, int addOrRemove) {
         for (Uuid remoteAclId : remoteAclIds) {
             Collection<AclInterface> remoteAclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
             if (remoteAclInterfaces.isEmpty()) {
@@ -648,7 +693,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             if (addOrRemove == NwConstants.ADD_FLOW) {
                 for (BigInteger dpn : dpns) {
                     for (AllowedAddressPairs aap : aaps) {
-                        programRemoteAclTableFlow(dpn, aclTag, aap, addOrRemove);
+                        programRemoteAclTableFlow(flowEntries, dpn, aclTag, aap, addOrRemove);
                     }
                 }
             } else if (addOrRemove == NwConstants.DEL_FLOW) {
@@ -669,19 +714,20 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
 
                 for (BigInteger dpn : dpnsToOperate) {
                     for (AllowedAddressPairs aap : aaps) {
-                        programRemoteAclTableFlow(dpn, aclTag, aap, addOrRemove);
+                        programRemoteAclTableFlow(flowEntries, dpn, aclTag, aap, addOrRemove);
                     }
                 }
             }
         }
     }
 
-    private void updateRemoteAclFilterTable(AclInterface port, int addOrRemove) {
-        updateRemoteAclFilterTable(port, port.getSecurityGroups(), port.getAllowedAddressPairs(), addOrRemove);
+    private void updateRemoteAclFilterTable(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
+        updateRemoteAclFilterTable(flowEntries, port, port.getSecurityGroups(), port.getAllowedAddressPairs(),
+                addOrRemove);
     }
 
-    private void updateRemoteAclFilterTable(AclInterface port, List<Uuid> aclList, List<AllowedAddressPairs> aaps,
-            int addOrRemove) {
+    private void updateRemoteAclFilterTable(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclList,
+            List<AllowedAddressPairs> aaps, int addOrRemove) {
         if (aclList == null) {
             LOG.debug("Port {} without SGs", port.getInterfaceId());
             return;
@@ -693,11 +739,14 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             if (aclDataUtil.getRemoteAcl(aclId, this.direction) != null) {
                 Integer aclTag = aclServiceUtils.getAclTag(aclId);
                 if (addOrRemove == NwConstants.ADD_FLOW) {
-                    syncRemoteAclTable(portId, aclId, aclTag, aaps, addOrRemove);
+                    syncRemoteAclTable(flowEntries, portId, aclId, aclTag, aaps, addOrRemove);
                 }
                 else if (addOrRemove == NwConstants.DEL_FLOW) {
                     jobCoordinator.enqueueJob(aclId.getValue().intern(), () -> {
-                        syncRemoteAclTable(portId, aclId, aclTag, aaps, addOrRemove);
+                        List<FlowEntity> remoteTableFlowEntries = new ArrayList<>();
+                        syncRemoteAclTable(remoteTableFlowEntries, portId, aclId, aclTag, aaps, addOrRemove);
+                        programFlows(AclConstants.ACL_JOB_KEY_PREFIX + aclId.getValue(),
+                                remoteTableFlowEntries, NwConstants.DEL_FLOW);
                         return Collections.emptyList();
                     });
                 }
@@ -705,12 +754,12 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         }
         Set<Uuid> remoteAclIds = aclServiceUtils.getRemoteAclIdsByDirection(aclList, direction);
         for (Uuid remoteAclId : remoteAclIds) {
-            syncRemoteAclTableFromOtherDpns(port, remoteAclId, addOrRemove);
+            syncRemoteAclTableFromOtherDpns(flowEntries, port, remoteAclId, addOrRemove);
         }
     }
 
-    private void syncRemoteAclTable(String portId, Uuid acl, Integer aclTag, List<AllowedAddressPairs> aaps,
-            int addOrRemove) {
+    private void syncRemoteAclTable(List<FlowEntity> flowEntries, String portId, Uuid acl, Integer aclTag,
+            List<AllowedAddressPairs> aaps, int addOrRemove) {
         Map<String, Set<AclInterface>> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(acl, this.direction);
         Set<BigInteger> dpns = collectDpns(mapAclWithPortSet);
         for (AllowedAddressPairs aap : aaps) {
@@ -724,12 +773,13 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
                 continue;
             }
             for (BigInteger dpId : dpns) {
-                programRemoteAclTableFlow(dpId, aclTag, aap, addOrRemove);
+                programRemoteAclTableFlow(flowEntries, dpId, aclTag, aap, addOrRemove);
             }
         }
     }
 
-    private void syncRemoteAclTableFromOtherDpns(AclInterface port, Uuid remoteAclId, int addOrRemove) {
+    private void syncRemoteAclTableFromOtherDpns(List<FlowEntity> flowEntries, AclInterface port, Uuid remoteAclId,
+            int addOrRemove) {
         Collection<AclInterface> aclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
 
         if (!aclInterfaces.isEmpty() && isFirstPortInDpnWithRemoteAclId(port, remoteAclId)) {
@@ -740,7 +790,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
                 }
                 for (AllowedAddressPairs aap : aclInterface.getAllowedAddressPairs()) {
                     if (AclServiceUtils.isNotIpAllNetwork(aap)) {
-                        programRemoteAclTableFlow(port.getDpId(), aclTag, aap, addOrRemove);
+                        programRemoteAclTableFlow(flowEntries, port.getDpId(), aclTag, aap, addOrRemove);
                     }
                 }
             }
@@ -767,8 +817,8 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         return true;
     }
 
-    protected abstract void programRemoteAclTableFlow(BigInteger dpId, Integer aclTag, AllowedAddressPairs aap,
-            int addOrRemove);
+    protected abstract void programRemoteAclTableFlow(List<FlowEntity> flowEntries, BigInteger dpId, Integer aclTag,
+            AllowedAddressPairs aap, int addOrRemove);
 
     protected Set<BigInteger> collectDpns(@Nullable Map<String, Set<AclInterface>> mapAclWithPortSet) {
         Set<BigInteger> dpns = new HashSet<>();
@@ -789,6 +839,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
     /**
      * Programs the port specific fixed rules.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dp id
      * @param allowedAddresses the allowed addresses
      * @param lportTag the lport tag
@@ -796,42 +847,43 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
      * @param action the action
      * @param write whether to add or remove the flow.
      */
-    protected void programAclPortSpecificFixedRules(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
-            int lportTag, String portId, Action action, int write) {
-        programGotoClassifierTableRules(dpId, allowedAddresses, lportTag, portId, write);
+    protected void programAclPortSpecificFixedRules(List<FlowEntity> flowEntries, BigInteger dpId,
+            List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int write) {
+        programGotoClassifierTableRules(flowEntries, dpId, allowedAddresses, lportTag, write);
         if (action == Action.ADD || action == Action.REMOVE) {
-            programConntrackRecircRules(dpId, allowedAddresses, lportTag, portId, write);
-            programPortSpecificDropRules(dpId, lportTag, portId, write);
-            programAclCommitRules(dpId, lportTag, portId, write);
+            programConntrackRecircRules(flowEntries, dpId, allowedAddresses, lportTag, portId, write);
+            programPortSpecificDropRules(flowEntries, dpId, lportTag, write);
+            programAclCommitRules(flowEntries, dpId, lportTag, portId, write);
         }
         LOG.info("programAclPortSpecificFixedRules: flows for dpId={}, lportId={}, action={}, write={}", dpId, lportTag,
                 action, write);
     }
 
-    protected abstract void programGotoClassifierTableRules(BigInteger dpId, List<AllowedAddressPairs> aaps,
-            int lportTag, String portId, int addOrRemove);
+    protected abstract void programGotoClassifierTableRules(List<FlowEntity> flowEntries, BigInteger dpId,
+            List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove);
 
     /**
      * Adds the rule to send the packet to the netfilter to check whether it is a known packet.
      *
+     * @param flowEntries the flow entries
      * @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<AllowedAddressPairs> aaps, int lportTag,
-            String portId, int addOrRemove) {
+    protected void programConntrackRecircRules(List<FlowEntity> flowEntries, BigInteger dpId,
+            List<AllowedAddressPairs> aaps, int lportTag, String portId, int addOrRemove) {
         if (AclServiceUtils.doesIpv4AddressExists(aaps)) {
-            programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
+            programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
         }
         if (AclServiceUtils.doesIpv6AddressExists(aaps)) {
-            programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
+            programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
         }
     }
 
-    protected void programConntrackRecircRule(BigInteger dpId, int lportTag, String portId,
-            MatchEthernetType matchEtherType, int addOrRemove) {
+    protected void programConntrackRecircRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            String portId, MatchEthernetType matchEtherType, int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(matchEtherType);
         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
@@ -851,37 +903,42 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
 
         String flowName =
                 this.directionString + "_Fixed_Conntrk_" + dpId + "_" + lportTag + "_" + matchEtherType + "_Recirc";
-        syncFlow(dpId, portId, getAclConntrackSenderTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, 0, 0,
-                AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclConntrackSenderTable(), flowName,
+                AclConstants.ACL_DEFAULT_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
+                addOrRemove);
     }
 
     /**
      * Adds the rules to drop the unknown/invalid packets .
      *
+     * @param flowEntries the flow entries
      * @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, String portId, int addOrRemove) {
+    protected void programPortSpecificDropRules(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         LOG.debug("Programming Drop Rules: DpId={}, lportTag={}, addOrRemove={}", dpId, lportTag, addOrRemove);
-        programConntrackInvalidDropRule(dpId, lportTag, portId, addOrRemove);
-        programAclRuleMissDropRule(dpId, lportTag, portId, addOrRemove);
+        programConntrackInvalidDropRule(flowEntries, dpId, lportTag, addOrRemove);
+        programAclRuleMissDropRule(flowEntries, dpId, lportTag, addOrRemove);
     }
 
     /**
      * Adds the rule to drop the conntrack invalid packets .
      *
+     * @param flowEntries the flow entries
      * @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, String portId, int addOrRemove) {
+    protected void programConntrackInvalidDropRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag,
                 AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, serviceMode);
         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
 
         String flowId = this.directionString + "_Fixed_Conntrk_Drop" + dpId + "_" + lportTag + "_Tracked_Invalid";
-        syncFlow(dpId, portId, getAclFilterCumDispatcherTable(), flowId,
+        addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
                 AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
                 matches, instructions, addOrRemove);
     }
@@ -889,45 +946,51 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
     /**
      * Program ACL rule miss drop rule for a port.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dp id
      * @param lportTag the lport tag
      * @param addOrRemove the add or remove
      */
-    protected void programAclRuleMissDropRule(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    protected void programAclRuleMissDropRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
 
         String flowId = this.directionString + "_Fixed_Acl_Rule_Miss_Drop_" + dpId + "_" + lportTag;
-        syncFlow(dpId, portId, getAclFilterCumDispatcherTable(), flowId, AclConstants.ACL_PORT_SPECIFIC_DROP_PRIORITY,
-                0, 0, AclServiceUtils.getDropFlowCookie(lportTag), matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
+                AclConstants.ACL_PORT_SPECIFIC_DROP_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
+                matches, instructions, addOrRemove);
     }
 
     /**
      * Program acl commit rules.
      *
+     * @param flowEntries the flow entries
      * @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, portId, addOrRemove);
+    protected void programAclCommitRules(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag, String portId,
+            int addOrRemove) {
+        programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
+        programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
+        programAclCommitRuleForNonConntrack(flowEntries, dpId, lportTag, addOrRemove);
     }
 
     /**
      * Program acl commit rule for conntrack.
      *
+     * @param flowEntries the flow entries
      * @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 void programAclCommitRuleForConntrack(BigInteger dpId, int lportTag, String portId,
-            MatchEthernetType matchEtherType, int addOrRemove) {
+    protected void programAclCommitRuleForConntrack(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            String portId, MatchEthernetType matchEtherType, int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(matchEtherType);
         matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
@@ -950,18 +1013,20 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
 
         String flowName = directionString + "_Acl_Commit_Conntrack_" + dpId + "_" + lportTag + "_" + matchEtherType;
         // Flow for conntrack traffic to commit and resubmit to dispatcher
-        syncFlow(dpId, portId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, 0, 0,
-                AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
+                0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
     }
 
     /**
      * Program acl commit rule for non conntrack.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dp id
      * @param lportTag the lport tag
      * @param addOrRemove the add or remove
      */
-    protected void programAclCommitRuleForNonConntrack(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    protected void programAclCommitRuleForNonConntrack(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
                 AclConntrackClassifierType.NON_CONNTRACK_SUPPORTED, serviceMode));
@@ -969,8 +1034,8 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
         String flowName = this.directionString + "_Acl_Commit_Non_Conntrack_" + dpId + "_" + lportTag;
         // Flow for non-conntrack traffic to resubmit to dispatcher
-        syncFlow(dpId, portId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, 0, 0,
-                AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
+                0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
     }
 
     @Nullable
index 2d8ad39af76f3401b5f547ca1186986c0a24a7c7..a80e61c2f5a4684e08d7f19101ed1ef93b30bfed 100644 (file)
@@ -17,6 +17,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
@@ -116,27 +117,27 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
     }
 
     @Override
-    protected void programAntiSpoofingRules(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
-            Action action, int addOrRemove) {
+    protected void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
+            List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
         LOG.info("{} programAntiSpoofingRules for port {}, AAPs={}, action={}, addOrRemove={}", this.directionString,
                 port.getInterfaceId(), allowedAddresses, action, addOrRemove);
 
         BigInteger dpid = port.getDpId();
         int lportTag = port.getLPortTag();
-        String portId = port.getInterfaceId();
         if (action != Action.UPDATE) {
-            programCommitterDropFlow(dpid, lportTag, portId, addOrRemove);
-            egressAclIcmpv6AllowedList(dpid, lportTag, portId, addOrRemove);
+            programCommitterDropFlow(flowEntries, dpid, lportTag, addOrRemove);
+            egressAclIcmpv6AllowedList(flowEntries, dpid, lportTag, addOrRemove);
         }
         List<AllowedAddressPairs> filteredAAPs = AclServiceUtils.excludeMulticastAAPs(allowedAddresses);
-        programL2BroadcastAllowRule(port, filteredAAPs, addOrRemove);
+        programL2BroadcastAllowRule(flowEntries, port, filteredAAPs, addOrRemove);
 
-        egressAclDhcpAllowClientTraffic(port, filteredAAPs, lportTag, addOrRemove);
-        egressAclDhcpv6AllowClientTraffic(port, filteredAAPs, lportTag, addOrRemove);
-        programArpRule(dpid, filteredAAPs, lportTag, portId, addOrRemove);
+        egressAclDhcpAllowClientTraffic(flowEntries, port, filteredAAPs, lportTag, addOrRemove);
+        egressAclDhcpv6AllowClientTraffic(flowEntries, port, filteredAAPs, lportTag, addOrRemove);
+        programArpRule(flowEntries, dpid, filteredAAPs, lportTag, addOrRemove);
     }
 
-    private void programCommitterDropFlow(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    private void programCommitterDropFlow(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
 
@@ -147,26 +148,27 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
         matches.add(new MatchMetadata(metaData, metaDataMask));
 
         String flowName = "Egress_" + dpId + "_" + lportTag + "_Drop";
-        syncFlow(dpId, portId, getAclCommitterTable(), flowName, AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY,
-                0, 0, AclServiceUtils.getDropFlowCookie(lportTag), matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName,
+                AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
+                matches, instructions, addOrRemove);
     }
 
     @Override
-    protected void programRemoteAclTableFlow(BigInteger dpId, Integer aclTag, AllowedAddressPairs aap,
-            int addOrRemove) {
+    protected void programRemoteAclTableFlow(List<FlowEntity> flowEntries, BigInteger dpId, Integer aclTag,
+            AllowedAddressPairs aap, int addOrRemove) {
         List<MatchInfoBase> flowMatches = new ArrayList<>();
         flowMatches.addAll(AclServiceUtils.buildIpAndDstServiceMatch(aclTag, aap));
 
         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
         String flowNameAdded = "Acl_Filter_Egress_" + aap.getIpAddress().stringValue() + "_" + aclTag;
 
-        syncFlow(dpId, dpId.toString(), getAclRemoteAclTable(), flowNameAdded, AclConstants.ACL_DEFAULT_PRIORITY,
+        addFlowEntryToList(flowEntries, dpId, getAclRemoteAclTable(), flowNameAdded, AclConstants.ACL_DEFAULT_PRIORITY,
                 0, 0, AclConstants.COOKIE_ACL_BASE, flowMatches, instructions, addOrRemove);
     }
 
     @Override
-    protected void programGotoClassifierTableRules(BigInteger dpId, List<AllowedAddressPairs> aaps, int lportTag,
-            String portId, int addOrRemove) {
+    protected void programGotoClassifierTableRules(List<FlowEntity> flowEntries, BigInteger dpId,
+            List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove) {
         List<AllowedAddressPairs> filteredAAPs = AclServiceUtils.excludeMulticastAAPs(aaps);
         for (AllowedAddressPairs aap : filteredAAPs) {
             IpPrefixOrAddress attachIp = aap.getIpAddress();
@@ -182,38 +184,44 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
 
             String flowName = "Egress_Fixed_Goto_Classifier_" + dpId + "_" + lportTag + "_" + mac.getValue() + "_"
                     + attachIp.stringValue();
-            syncFlow(dpId, portId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_MATCH_PRIORITY, 0, 0,
-                    AclConstants.COOKIE_ACL_BASE, matches, gotoInstructions, addOrRemove);
+            addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
+                    AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, gotoInstructions,
+                    addOrRemove);
         }
     }
 
     /**
      * Add rule to allow certain ICMPv6 traffic from VM ports.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dpId
      * @param lportTag the lport tag
      * @param addOrRemove add/remove the flow.
      */
-    private void egressAclIcmpv6AllowedList(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    private void egressAclIcmpv6AllowedList(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
 
         for (Integer icmpv6Type: AclConstants.allowedIcmpv6NdList()) {
             List<MatchInfoBase> matches = AclServiceUtils.buildIcmpV6Matches(icmpv6Type, 0, lportTag, serviceMode);
             String flowName = "Egress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + icmpv6Type + "_Permit_";
-            syncFlow(dpId, portId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY,
-                    0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+            addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
+                    AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
+                    instructions, addOrRemove);
         }
     }
 
     /**
      * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
+     *
+     * @param flowEntries the flow entries
      * @param port the Acl Interface port
      * @param allowedAddresses the allowed addresses
      * @param lportTag the lport tag
      * @param addOrRemove whether to add or remove the flow
      */
-    private void egressAclDhcpAllowClientTraffic(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
-            int lportTag, int addOrRemove) {
+    private void egressAclDhcpAllowClientTraffic(List<FlowEntity> flowEntries, AclInterface port,
+            List<AllowedAddressPairs> allowedAddresses, int lportTag, int addOrRemove) {
         // if there is a duplicate mac with different aap, do not delete the Dhcp Allow rule.
         if (hasDuplicateMac(port.getAllowedAddressPairs(), allowedAddresses)) {
             return;
@@ -231,22 +239,23 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
 
             String flowName =
                     "Egress_DHCP_Client_v4" + dpId + "_" + lportTag + "_" + aap.getMacAddress().getValue() + "_Permit_";
-            syncFlow(dpId, port.getInterfaceId(), getAclAntiSpoofingTable(), flowName,
+            addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
                     AclConstants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE,
                     matches, instructions, addOrRemove);
         }
     }
 
     /**
-     * Add rule to ensure only DHCPv6 server traffic from the specified mac is
-     * allowed.
+     * Add rule to ensure only DHCPv6 server traffic from the specified mac is allowed.
+     *
+     * @param flowEntries the flow entries
      * @param port the Acl Interface port
      * @param allowedAddresses the allowed addresses
      * @param lportTag the lport tag
      * @param addOrRemove whether to add or remove the flow
      */
-    private void egressAclDhcpv6AllowClientTraffic(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
-            int lportTag, int addOrRemove) {
+    private void egressAclDhcpv6AllowClientTraffic(List<FlowEntity> flowEntries, AclInterface port,
+            List<AllowedAddressPairs> allowedAddresses, int lportTag, int addOrRemove) {
         // if there is a duplicate mac with different aap, do not delete the Dhcp Allow rule.
         if (hasDuplicateMac(port.getAllowedAddressPairs(), allowedAddresses)) {
             return;
@@ -264,7 +273,7 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
 
             String flowName = "Egress_DHCP_Client_v6" + "_" + dpId + "_" + lportTag + "_"
                     + aap.getMacAddress().getValue() + "_Permit_";
-            syncFlow(dpId, port.getInterfaceId(), getAclAntiSpoofingTable(), flowName,
+            addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
                     AclConstants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE,
                     matches, instructions, addOrRemove);
         }
@@ -273,13 +282,14 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
     /**
      * Adds the rule to allow arp packets.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dpId
      * @param allowedAddresses the allowed addresses
      * @param lportTag the lport tag
      * @param addOrRemove whether to add or remove the flow
      */
-    protected void programArpRule(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses, int lportTag,
-            String portId, int addOrRemove) {
+    protected void programArpRule(List<FlowEntity> flowEntries, BigInteger dpId,
+            List<AllowedAddressPairs> allowedAddresses, int lportTag, int addOrRemove) {
         for (AllowedAddressPairs allowedAddress : allowedAddresses) {
             if (!AclServiceUtils.isIPv4Address(allowedAddress)) {
                 continue; // For IPv6 allowed addresses
@@ -300,36 +310,41 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
                     addOrRemove == NwConstants.DEL_FLOW ? "Deleting" : "Adding", dpId, lportTag);
             String flowName = "Egress_ARP_" + dpId + "_" + lportTag + "_" + allowedAddress.getMacAddress().getValue()
                     + allowedAddressIp.stringValue();
-            syncFlow(dpId, portId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY,
-                    0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+            addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
+                    AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
+                    instructions, addOrRemove);
         }
     }
 
     @Override
-    protected void programIcmpv6RARule(AclInterface port, List<SubnetInfo> subnets, int addOrRemove) {
+    protected void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port, List<SubnetInfo> subnets,
+            int addOrRemove) {
         // No action required on egress.
     }
 
     /**
      * Programs broadcast rules.
      *
+     * @param flowEntries the flow entries
      * @param port the Acl Interface port
      * @param addOrRemove whether to delete or add flow
      */
     @Override
-    protected void programBroadcastRules(AclInterface port, int addOrRemove) {
-        programL2BroadcastAllowRule(port, AclServiceUtils.excludeMulticastAAPs(port.getAllowedAddressPairs()),
-                addOrRemove);
+    protected void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
+        programL2BroadcastAllowRule(flowEntries, port,
+                AclServiceUtils.excludeMulticastAAPs(port.getAllowedAddressPairs()), addOrRemove);
     }
 
     /**
      * Programs Non-IP broadcast rules.
+     *
+     * @param flowEntries the flow entries
      * @param port the Acl Interface port
      * @param filteredAAPs the filtered AAPs list
      * @param addOrRemove whether to delete or add flow
      */
-    private void programL2BroadcastAllowRule(AclInterface port, List<AllowedAddressPairs> filteredAAPs,
-          int addOrRemove) {
+    private void programL2BroadcastAllowRule(List<FlowEntity> flowEntries, AclInterface port,
+            List<AllowedAddressPairs> filteredAAPs, int addOrRemove) {
         // if there is a duplicate mac with different aap, do not delete the Broadcast rule.
         if (hasDuplicateMac(port.getAllowedAddressPairs(), filteredAAPs)) {
             return;
@@ -346,7 +361,7 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
             List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
 
             String flowName = "Egress_L2Broadcast_" + dpId + "_" + lportTag + "_" + mac.getValue();
-            syncFlow(dpId, port.getInterfaceId(), getAclAntiSpoofingTable(), flowName,
+            addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
                     AclConstants.PROTO_L2BROADCAST_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE,
                     matches, instructions, addOrRemove);
         }
index 5c22dbcfc1334c12d185dd85f36b3709a3696c44..5727a6d19f7b8e6d8a32c86162515527ae2ad15d 100644 (file)
@@ -15,6 +15,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
@@ -127,27 +128,27 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
     }
 
     @Override
-    protected void programAntiSpoofingRules(AclInterface port,
+    protected void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
             List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
         LOG.info("{} programAntiSpoofingRules for port {}, AAPs={}, action={}, addOrRemove={}", this.directionString,
                 port.getInterfaceId(), allowedAddresses, action, addOrRemove);
 
         BigInteger dpid = port.getDpId();
         int lportTag = port.getLPortTag();
-        String portId = port.getInterfaceId();
         if (action == Action.ADD || action == Action.REMOVE) {
-            programCommitterDropFlow(dpid, lportTag, portId, addOrRemove);
-            ingressAclDhcpAllowServerTraffic(dpid, lportTag, portId, addOrRemove);
-            ingressAclDhcpv6AllowServerTraffic(dpid, lportTag, portId, addOrRemove);
-            ingressAclIcmpv6AllowedTraffic(port, addOrRemove);
-            programIcmpv6RARule(port, port.getSubnetInfo(), addOrRemove);
-
-            programArpRule(dpid, lportTag, portId, addOrRemove);
-            programIpv4BroadcastRule(port, addOrRemove);
+            programCommitterDropFlow(flowEntries, dpid, lportTag, addOrRemove);
+            ingressAclDhcpAllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
+            ingressAclDhcpv6AllowServerTraffic(flowEntries, dpid, lportTag, addOrRemove);
+            ingressAclIcmpv6AllowedTraffic(flowEntries, port, addOrRemove);
+            programIcmpv6RARule(flowEntries, port, port.getSubnetInfo(), addOrRemove);
+
+            programArpRule(flowEntries, dpid, lportTag, addOrRemove);
+            programIpv4BroadcastRule(flowEntries, port, addOrRemove);
         }
     }
 
-    private void programCommitterDropFlow(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    private void programCommitterDropFlow(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
 
@@ -160,13 +161,14 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
         matches.add(new MatchMetadata(metaData, metaDataMask));
 
         String flowName = "Ingress_" + dpId + "_" + lportTag + "_Drop";
-        syncFlow(dpId, portId, getAclCommitterTable(), flowName, AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY,
-                0, 0, AclServiceUtils.getDropFlowCookie(lportTag), matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName,
+                AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
+                matches, instructions, addOrRemove);
     }
 
     @Override
-    protected void programGotoClassifierTableRules(BigInteger dpId, List<AllowedAddressPairs> aaps, int lportTag,
-            String portId, int addOrRemove) {
+    protected void programGotoClassifierTableRules(List<FlowEntity> flowEntries, BigInteger dpId,
+            List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove) {
         for (AllowedAddressPairs aap : aaps) {
             IpPrefixOrAddress attachIp = aap.getIpAddress();
             MacAddress mac = aap.getMacAddress();
@@ -181,71 +183,76 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
 
             String flowName = "Ingress_Fixed_Goto_Classifier_" + dpId + "_" + lportTag + "_" + mac.getValue() + "_"
                     + attachIp.stringValue();
-            syncFlow(dpId, portId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_MATCH_PRIORITY, 0, 0,
-                    AclConstants.COOKIE_ACL_BASE, matches, gotoInstructions, addOrRemove);
+            addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
+                    AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, gotoInstructions,
+                    addOrRemove);
         }
     }
 
     @Override
-    protected void programRemoteAclTableFlow(BigInteger dpId, Integer aclTag, AllowedAddressPairs aap,
-            int addOrRemove) {
+    protected void programRemoteAclTableFlow(List<FlowEntity> flowEntries, BigInteger dpId, Integer aclTag,
+            AllowedAddressPairs aap, int addOrRemove) {
         List<MatchInfoBase> flowMatches = new ArrayList<>();
         flowMatches.addAll(AclServiceUtils.buildIpAndSrcServiceMatch(aclTag, aap));
 
         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
         String flowNameAdded = "Acl_Filter_Ingress_" + aap.getIpAddress().stringValue() + "_" + aclTag;
 
-        syncFlow(dpId, dpId.toString(), getAclRemoteAclTable(), flowNameAdded, AclConstants.ACL_DEFAULT_PRIORITY,
+        addFlowEntryToList(flowEntries, dpId, getAclRemoteAclTable(), flowNameAdded, AclConstants.ACL_DEFAULT_PRIORITY,
                 0, 0, AclConstants.COOKIE_ACL_BASE, flowMatches, instructions, addOrRemove);
     }
 
     /**
-     * Add rule to ensure only DHCP server traffic from the specified mac is
-     * allowed.
+     * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dpid
      * @param lportTag the lport tag
      * @param addOrRemove is write or delete
      */
-    protected void ingressAclDhcpAllowServerTraffic(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    protected void ingressAclDhcpAllowServerTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4,
                 AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag, serviceMode);
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
 
         String flowName = "Ingress_DHCP_Server_v4" + dpId + "_" + lportTag + "_Permit_";
-        syncFlow(dpId, portId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY,
-                0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
+                AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
+                instructions, addOrRemove);
     }
 
     /**
-     * Add rule to ensure only DHCPv6 server traffic from the specified mac is
-     * allowed.
+     * Add rule to ensure only DHCPv6 server traffic from the specified mac is allowed.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dpid
      * @param lportTag the lport tag
      * @param addOrRemove is write or delete
      */
-    protected void ingressAclDhcpv6AllowServerTraffic(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    protected void ingressAclDhcpv6AllowServerTraffic(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
+            int addOrRemove) {
         final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6,
                 AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag, serviceMode);
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
 
         String flowName = "Ingress_DHCP_Server_v6" + "_" + dpId + "_" + lportTag + "_Permit_";
-        syncFlow(dpId, portId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY,
-                0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
+                AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
+                instructions, addOrRemove);
     }
 
     /**
      * Add rules to ensure that certain ICMPv6 like MLD_QUERY (130), RS (134), NS (135), NA (136) are
      * allowed into the VM.
      *
+     * @param flowEntries the flow entries
      * @param port the port
      * @param addOrRemove is write or delete
      */
-    private void ingressAclIcmpv6AllowedTraffic(AclInterface port, int addOrRemove) {
+    private void ingressAclIcmpv6AllowedTraffic(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
         BigInteger dpId = port.getDpId();
         int lportTag = port.getLPortTag();
-        String portId = port.getInterfaceId();
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
 
         // Allow ICMPv6 Multicast Listener Query packets.
@@ -255,26 +262,27 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
         final short tableId = getAclAntiSpoofingTable();
         String flowName =
                 "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_MLD_QUERY + "_Permit_";
-        syncFlow(dpId, portId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
+        addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
 
         // Allow ICMPv6 Neighbor Solicitation packets.
         matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NS, 0, lportTag, serviceMode);
 
         flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_NS + "_Permit_";
-        syncFlow(dpId, portId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
+        addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
 
         // Allow ICMPv6 Neighbor Advertisement packets.
         matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NA, 0, lportTag, serviceMode);
 
         flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_NA + "_Permit_";
-        syncFlow(dpId, portId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
+        addFlowEntryToList(flowEntries, dpId, tableId, flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0,
                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
     }
 
     @Override
-    protected void programIcmpv6RARule(AclInterface port, List<SubnetInfo> subnets, int addOrRemove) {
+    protected void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port, List<SubnetInfo> subnets,
+            int addOrRemove) {
         if (AclServiceUtils.isIpv6Subnet(subnets)) {
             /* Allow ICMPv6 Router Advertisement packets from external routers as well as internal routers
              * if subnet is configured with IPv6 version
@@ -289,7 +297,7 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
                     AclServiceManager.MatchCriteria.MATCH_SOURCE));
             String flowName = "Ingress_ICMPv6" + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
                     + AclConstants.ICMPV6_TYPE_RA + "_LinkLocal_Permit_";
-            syncFlow(port.getDpId(), port.getInterfaceId(), getAclAntiSpoofingTable(), flowName,
+            addFlowEntryToList(flowEntries, port.getDpId(), getAclAntiSpoofingTable(), flowName,
                     AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
                     instructions, addOrRemove);
         }
@@ -298,11 +306,12 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
     /**
      * Adds the rule to allow arp packets.
      *
+     * @param flowEntries the flow entries
      * @param dpId the dpId
      * @param lportTag the lport tag
      * @param addOrRemove whether to add or remove the flow
      */
-    protected void programArpRule(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
+    protected void programArpRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag, int addOrRemove) {
         List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(MatchEthernetType.ARP);
         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
@@ -310,29 +319,32 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
         LOG.debug("{} ARP Rule on DPID {}, lportTag {}", addOrRemove == NwConstants.DEL_FLOW ? "Deleting" : "Adding",
                 dpId, lportTag);
         String flowName = "Ingress_ARP_" + dpId + "_" + lportTag;
-        syncFlow(dpId, portId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY,
-                0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
+        addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
+                AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
+                instructions, addOrRemove);
     }
 
 
     /**
      * Programs broadcast rules.
      *
+     * @param flowEntries the flow entries
      * @param port the Acl Interface port
      * @param addOrRemove whether to delete or add flow
      */
     @Override
-    protected void programBroadcastRules(AclInterface port, int addOrRemove) {
-        programIpv4BroadcastRule(port, addOrRemove);
+    protected void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
+        programIpv4BroadcastRule(flowEntries, port, addOrRemove);
     }
 
     /**
      * Programs IPv4 broadcast rules.
      *
+     * @param flowEntries the flow entries
      * @param port the Acl Interface port
      * @param addOrRemove whether to delete or add flow
      */
-    private void programIpv4BroadcastRule(AclInterface port, int addOrRemove) {
+    private void programIpv4BroadcastRule(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
         BigInteger dpId = port.getDpId();
         int lportTag = port.getLPortTag();
         MatchInfoBase lportMatchInfo = AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode);
@@ -346,7 +358,7 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
                 List<InstructionInfo> instructions = new ArrayList<>();
                 instructions.add(new InstructionGotoTable(getAclConntrackClassifierTable()));
                 String flowName = "Ingress_v4_Broadcast_" + dpId + "_" + lportTag + "_" + broadcastAddress + "_Permit";
-                syncFlow(dpId, port.getInterfaceId(), getAclAntiSpoofingTable(), flowName,
+                addFlowEntryToList(flowEntries, dpId, getAclAntiSpoofingTable(), flowName,
                         AclConstants.PROTO_MATCH_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
                         addOrRemove);
             }
index 7d30f8bf8c3cedc0ca401ff5083c43c9bbe4f610..5abb085ae0d2b9b08794accc42b534be91c2ebdb 100644 (file)
@@ -122,6 +122,7 @@ public interface AclConstants {
 
     String ACL_SYNC_KEY_EXT = "-acl";
     int JOB_MAX_RETRIES = 3;
+    int FLOWS_PER_TRANSACTION = 30;
 
     String ACL_JOB_KEY_PREFIX = "ACL-";