ACL: Support for non-conntrack supported traffic.
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / listeners / AclNodeListener.java
index 2cf363a356bd25e11a02041c0029f660477da72c..fd8233a70ab73e1c0d5d7f4f1bc957a9614818be 100644 (file)
@@ -9,60 +9,36 @@
 package org.opendaylight.netvirt.aclservice.listeners;
 
 import java.math.BigInteger;
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
-
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
-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.MatchInfo;
-import org.opendaylight.genius.mdsalutil.MatchInfoBase;
-import org.opendaylight.genius.mdsalutil.NwConstants;
-import org.opendaylight.genius.mdsalutil.NxMatchInfo;
-import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
-import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
-import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
-import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
-import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
-import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
-import org.opendaylight.genius.mdsalutil.matches.MatchTcpFlags;
-import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
-import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 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.AclNodeDefaultFlowsTxBuilder;
 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig.DefaultBehavior;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig.SecurityGroupMode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Listener to handle flow capable node updates.
+ * Listener to handle flow capable node updates. Configures default ACL flows
+ * during when node is discovered.
  */
 @Singleton
-@SuppressWarnings("deprecation")
-public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapableNode, AclNodeListener>
-        implements AutoCloseable {
+public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapableNode, AclNodeListener> {
 
     private static final Logger LOG = LoggerFactory.getLogger(AclNodeListener.class);
 
@@ -70,21 +46,20 @@ public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapable
     private final AclserviceConfig config;
     private final DataBroker dataBroker;
     private final AclServiceUtils aclServiceUtils;
-    private final AclDataUtil aclDataUtil;
-    private final int dummyTag = 0;
+    private final JobCoordinator jobCoordinator;
 
     private SecurityGroupMode securityGroupMode = null;
 
     @Inject
     public AclNodeListener(final IMdsalApiManager mdsalManager, DataBroker dataBroker, AclserviceConfig config,
-            AclServiceUtils aclServiceUtils, AclDataUtil aclDataUtil) {
+            AclServiceUtils aclServiceUtils, JobCoordinator jobCoordinator) {
         super(FlowCapableNode.class, AclNodeListener.class);
 
         this.mdsalManager = mdsalManager;
         this.dataBroker = dataBroker;
         this.config = config;
         this.aclServiceUtils = aclServiceUtils;
-        this.aclDataUtil = aclDataUtil;
+        this.jobCoordinator = jobCoordinator;
     }
 
     @Override
@@ -112,20 +87,7 @@ public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapable
 
     @Override
     protected void remove(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
-        NodeKey nodeKey = key.firstKeyOf(Node.class);
-        BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
-        if (!aclDataUtil.doesDpnHaveAclInterface(dpnId)) {
-            // serialize ACL pool deletion per switch
-            DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-            dataStoreCoordinator.enqueueJob(String.valueOf(dpnId), () -> {
-                this.aclServiceUtils.deleteAclIdPools(dpnId);
-                return Collections.emptyList();
-            });
-            LOG.debug("On FlowCapableNode remove event, ACL pools for dpid: {} are deleted.", dpnId);
-        } else {
-            LOG.info("On FlowCapableNode remove event, ACL pools for dpid: {} are not deleted "
-                + "because ACL ports are associated.", dpnId);
-        }
+        // do nothing
     }
 
     @Override
@@ -136,582 +98,24 @@ public class AclNodeListener extends AsyncDataTreeChangeListenerBase<FlowCapable
 
     @Override
     protected void add(InstanceIdentifier<FlowCapableNode> key, FlowCapableNode dataObjectModification) {
-        LOG.trace("FlowCapableNode Added: key: {}", key);
         NodeKey nodeKey = key.firstKeyOf(Node.class);
-        BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
-        createTableDefaultEntries(dpnId);
-        // serialize ACL pool creation per switch
-        DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
-        dataStoreCoordinator.enqueueJob(String.valueOf(dpnId), () -> {
-            this.aclServiceUtils.createAclIdPools(dpnId);
-            return Collections.emptyList();
-        });
-        LOG.trace("FlowCapableNode (dpid: {}) add event is processed.", dpnId);
-    }
-
-    /**
-     * Creates the table miss entries.
-     *
-     * @param dpnId the dpn id
-     */
-    private void createTableDefaultEntries(BigInteger dpnId) {
-        LOG.info("Adding default ACL entries for mode {}",
-                securityGroupMode == null ? SecurityGroupMode.Stateful : securityGroupMode);
-
-        if (securityGroupMode == null || securityGroupMode == SecurityGroupMode.Stateful) {
-            addStatefulIngressAclTableMissFlow(dpnId);
-            addStatefulEgressAclTableMissFlow(dpnId);
-            addConntrackRules(dpnId, NwConstants.LPORT_DISPATCHER_TABLE, NwConstants.INGRESS_ACL_FILTER_TABLE,
-                    NwConstants.ADD_FLOW);
-            addConntrackRules(dpnId, NwConstants.EGRESS_LPORT_DISPATCHER_TABLE, NwConstants.EGRESS_ACL_FILTER_TABLE,
-                    NwConstants.ADD_FLOW);
-            addConntrackDummyLookup(dpnId, NwConstants.ADD_FLOW);
-        } else if (securityGroupMode == SecurityGroupMode.Transparent) {
-            addTransparentIngressAclTableMissFlow(dpnId);
-            addTransparentEgressAclTableMissFlow(dpnId);
-        } else if (securityGroupMode == SecurityGroupMode.Stateless) {
-            addStatelessIngressAclTableMissFlow(dpnId);
-            addStatelessEgressAclTableMissFlow(dpnId);
-        } else if (securityGroupMode == SecurityGroupMode.Learn) {
-            addLearnIngressAclTableMissFlow(dpnId);
-            addLearnEgressAclTableMissFlow(dpnId);
-        } else {
-            LOG.error("Invalid security group mode ({}) obtained from AclserviceConfig.", securityGroupMode);
-        }
-    }
-
-    /**
-     * Adds the egress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addStatefulEgressAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> instructionsAcl = config.getDefaultBehavior() == DefaultBehavior.Deny
-                ? AclServiceOFFlowBuilder.getDropInstructionInfo()
-                : AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.EGRESS_ACL_REMOTE_ACL_TABLE);
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Egress ACL Table Miss Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, mkMatches, instructionsAcl);
-        mdsalManager.installFlow(flowEntity);
-
-        addEgressAclRemoteAclTableMissFlow(dpId);
-
-        List<InstructionInfo> instructionsAclFilter = config.getDefaultBehavior() == DefaultBehavior.Deny
-                ? AclServiceOFFlowBuilder.getDropInstructionInfo()
-                : AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE);
-        FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0, "Egress ACL Filter Table Miss Flow",
-                0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, instructionsAclFilter);
-        mdsalManager.installFlow(nextTblFlowEntity);
-
-        LOG.debug("Added Egress ACL Table Miss Flows for dpn {}", dpId);
-    }
-
-    private void addEgressAclTableAllowFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> allowAllInstructions = new ArrayList<>();
-        allowAllInstructions.add(new InstructionGotoTable(NwConstants.EGRESS_ACL_REMOTE_ACL_TABLE));
-
-        FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Egress ACL Table allow all Flow",
-                0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
-        mdsalManager.installFlow(nextTblFlowEntity);
-
-        LOG.debug("Added Egress ACL Table Allow all Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the egress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addEgressAclRemoteAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
-        mkInstructions.add(new InstructionGotoTable(NwConstants.EGRESS_ACL_FILTER_TABLE));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_REMOTE_ACL_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_REMOTE_ACL_TABLE), 0, "Egress ACL Remote Table Miss Flow",
-                0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
-        mdsalManager.installFlow(flowEntity);
-
-        LOG.debug("Added Egress ACL Remote Table Miss Flows for dpn {}", dpId);
-    }
-
-    private void addEgressAclFilterTableAllowFlow(BigInteger dpId) {
-        short dispatcherTableId =  NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
-
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<ActionInfo> actionsInfos = new ArrayList<>();
-        List<InstructionInfo> instructions = new ArrayList<>();
-        actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0, "Egress ACL Filter Table allow all Flow",
-                0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, instructions);
-        mdsalManager.installFlow(flowEntity);
-
-        LOG.debug("Added Egress ACL Filter Table allow all Flows for dpn {}", dpId);
-    }
-
-    private void addLearnEgressAclTableMissFlow(BigInteger dpId) {
-        List<InstructionInfo> instructions = new ArrayList<>();
-        List<ActionInfo> actionsInfos = new ArrayList<>();
-
-        actionsInfos.add(new ActionNxResubmit(NwConstants.EGRESS_LEARN_TABLE));
-        actionsInfos.add(new ActionNxResubmit(NwConstants.EGRESS_LEARN_ACL_REMOTE_ACL_TABLE));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-
-        FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                "RESUB-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
-                AclConstants.PROTO_MATCH_PRIORITY, "Egress resubmit ACL Table Block", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, Collections.emptyList(), instructions);
-        mdsalManager.installFlow(doubleResubmitTable);
-
-        addLearnEgressAclRemoteAclTableMissFlow(dpId);
-
-        instructions = config.getDefaultBehavior() == DefaultBehavior.Deny
-                ? AclServiceOFFlowBuilder.getDropInstructionInfo()
-                : AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE);
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN_ACL_FILTER_TABLE,
-                "LEARN-" + getTableMissFlowId(NwConstants.EGRESS_LEARN_ACL_FILTER_TABLE), 0,
-                "Egress Learn2 ACL Table Miss Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, Collections.emptyList(), instructions);
-        mdsalManager.installFlow(flowEntity);
-
-        List<NxMatchInfo> nxMkMatches = new ArrayList<>();
-        nxMkMatches.add(new NxMatchRegister(NxmNxReg5.class, AclConstants.LEARN_MATCH_REG_VALUE));
-
-        actionsInfos = new ArrayList<>();
-        instructions = new ArrayList<>();
-        actionsInfos.add(new ActionNxResubmit(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-
-        flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN_ACL_FILTER_TABLE,
-                "LEARN2-REG-" + getTableMissFlowId(NwConstants.EGRESS_LEARN_ACL_FILTER_TABLE),
-                AclConstants.PROTO_MATCH_PRIORITY, "Egress Learn2 ACL Table match reg Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, nxMkMatches, instructions);
-        mdsalManager.installFlow(flowEntity);
-        LOG.debug("Added Learn Egress ACL Table Miss Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the egress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addLearnEgressAclRemoteAclTableMissFlow(BigInteger dpId) {
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
-        mkInstructions.add(new InstructionGotoTable(NwConstants.EGRESS_LEARN_ACL_FILTER_TABLE));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_LEARN_ACL_REMOTE_ACL_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_LEARN_ACL_REMOTE_ACL_TABLE), 0,
-                "Egress ACL Remote Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE, Collections.emptyList(),
-                mkInstructions);
-        mdsalManager.installFlow(flowEntity);
-
-        LOG.debug("Added Learn Egress ACL Remote Table Miss Flows for dpn {}", dpId);
-    }
-
-    private void addLearnIngressAclTableMissFlow(BigInteger dpId) {
-        List<InstructionInfo> instructions = new ArrayList<>();
-        List<ActionInfo> actionsInfos = new ArrayList<>();
-
-        actionsInfos.add(new ActionNxResubmit(NwConstants.INGRESS_LEARN_TABLE));
-        actionsInfos.add(new ActionNxResubmit(NwConstants.INGRESS_LEARN_ACL_REMOTE_ACL_TABLE));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-
-        FlowEntity doubleResubmitTable = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
-                "RESUB-" + getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE),
-                AclConstants.PROTO_MATCH_PRIORITY, "Ingress resubmit ACL Table Block", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, Collections.emptyList(), instructions);
-        mdsalManager.installFlow(doubleResubmitTable);
-
-        addLearnIngressAclRemoteAclTableMissFlow(dpId);
-
-        instructions = config.getDefaultBehavior() == DefaultBehavior.Deny
-                ? AclServiceOFFlowBuilder.getDropInstructionInfo()
-                : AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.LPORT_DISPATCHER_TABLE);
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN_ACL_FILTER_TABLE,
-                "LEARN-" + getTableMissFlowId(NwConstants.INGRESS_LEARN_ACL_FILTER_TABLE), 0,
-                "Ingress Learn2 ACL Table Miss Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, Collections.emptyList(), instructions);
-        mdsalManager.installFlow(flowEntity);
-
-        List<NxMatchInfo> nxMkMatches = new ArrayList<>();
-        nxMkMatches.add(new NxMatchRegister(NxmNxReg5.class, AclConstants.LEARN_MATCH_REG_VALUE));
-
-        actionsInfos = new ArrayList<>();
-        instructions = new ArrayList<>();
-        actionsInfos.add(new ActionNxResubmit(NwConstants.LPORT_DISPATCHER_TABLE));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-
-        flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN_ACL_FILTER_TABLE,
-                "LEARN2-REG-" + getTableMissFlowId(NwConstants.INGRESS_LEARN_ACL_FILTER_TABLE),
-                AclConstants.PROTO_MATCH_PRIORITY, "Egress Learn2 ACL Table match reg Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, nxMkMatches, instructions);
-        mdsalManager.installFlow(flowEntity);
-        LOG.debug("Added Learn ACL Table Miss Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the ingress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addLearnIngressAclRemoteAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
-        mkInstructions.add(new InstructionGotoTable(NwConstants.INGRESS_LEARN_ACL_FILTER_TABLE));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_LEARN_ACL_REMOTE_ACL_TABLE,
-                getTableMissFlowId(NwConstants.INGRESS_LEARN_ACL_REMOTE_ACL_TABLE), 0,
-                "Ingress ACL Remote Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
-        mdsalManager.installFlow(flowEntity);
-
-        LOG.debug("Added Learn Ingress ACL Table Miss Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the ingress acl table transparent flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addTransparentIngressAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> instructionsAcl =
-                AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.LPORT_DISPATCHER_TABLE);
+        BigInteger dpId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
+        LOG.info("Received ACL node [{}] add event", dpId);
 
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
-                getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Ingress ACL Table Miss Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, mkMatches, instructionsAcl);
-        mdsalManager.installFlow(flowEntity);
-        LOG.debug("Added Transparent Ingress ACL Table allow all Flows for dpn {}", dpId);
-    }
-
-    private void addIngressAclFilterTableAllowFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
-        List<ActionInfo> actionsInfos = new ArrayList<>();
-        List<InstructionInfo> dispatcherInstructions = new ArrayList<>();
-        actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
-        dispatcherInstructions.add(new InstructionApplyActions(actionsInfos));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
-                getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0, "Ingress ACL Filter Table allow all Flow",
-                0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, dispatcherInstructions);
-        mdsalManager.installFlow(flowEntity);
-
-        LOG.debug("Added Ingress ACL Filter Table allow all Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the egress acl table transparent flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addTransparentEgressAclTableMissFlow(BigInteger dpId) {
-
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> instructionsAcl =
-                AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE);
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Ingress ACL Table Miss Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, mkMatches, instructionsAcl);
-        mdsalManager.installFlow(flowEntity);
-        LOG.debug("Added Transparent Egress ACL Table allow all Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the ingress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addStatelessIngressAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> synMatches = new ArrayList<>();
-        synMatches.add(MatchEthernetType.IPV4);
-        synMatches.add(MatchIpProtocol.TCP);
-        synMatches.add(MatchTcpFlags.SYN);
-
-        List<ActionInfo> dropActionsInfos = new ArrayList<>();
-        dropActionsInfos.add(new ActionDrop());
-        List<InstructionInfo> synInstructions = new ArrayList<>();
-        synInstructions.add(new InstructionApplyActions(dropActionsInfos));
-
-        FlowEntity synFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
-                "SYN-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
-                AclConstants.PROTO_MATCH_SYN_DROP_PRIORITY, "Ingress Syn ACL Table Block", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, synMatches, synInstructions);
-        mdsalManager.installFlow(synFlowEntity);
-
-        synMatches = new ArrayList<>();
-        synMatches.add(MatchEthernetType.IPV4);
-        synMatches.add(MatchIpProtocol.TCP);
-        synMatches.add(MatchTcpFlags.SYN_ACK);
-
-        List<InstructionInfo> allowAllInstructions = new ArrayList<>();
-        allowAllInstructions.add(new InstructionGotoTable(NwConstants.INGRESS_ACL_REMOTE_ACL_TABLE));
-
-        FlowEntity synAckFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                "SYN-ACK-DEFAULT_ALLOW-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
-                AclConstants.PROTO_MATCH_SYN_ACK_ALLOW_PRIORITY, "Ingress Syn Ack ACL Table Allow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, synMatches, allowAllInstructions);
-        mdsalManager.installFlow(synAckFlowEntity);
-
-
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Ingress Stateless ACL Table Miss Flow",
-                0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
-        mdsalManager.installFlow(flowEntity);
-
-        addIngressAclRemoteAclTableMissFlow(dpId);
-
-        short dispatcherTableId =  NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
-        List<ActionInfo> actionsInfos = new ArrayList<>();
-        List<InstructionInfo> instructions = new ArrayList<>();
-        actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-        FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0,
-                "Ingress Stateless Next ACL Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE,
-                mkMatches, instructions);
-        mdsalManager.installFlow(nextTblFlowEntity);
-
-        LOG.debug("Added Stateless Ingress ACL Table Miss Flows for dpn {}.", dpId);
-    }
-
-    /**
-     * Adds the stateless egress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addStatelessEgressAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> synMatches = new ArrayList<>();
-        synMatches.add(MatchEthernetType.IPV4);
-        synMatches.add(MatchIpProtocol.TCP);
-        synMatches.add(MatchTcpFlags.SYN);
-
-        List<InstructionInfo> allowAllInstructions = new ArrayList<>();
-        allowAllInstructions.add(new InstructionGotoTable(NwConstants.EGRESS_ACL_FILTER_TABLE));
-        List<InstructionInfo> synInstructions;
-
-        if (config.getDefaultBehavior() == DefaultBehavior.Allow) {
-            synInstructions = allowAllInstructions;
-        } else {
-            synInstructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
+        if (securityGroupMode != null && securityGroupMode != SecurityGroupMode.Stateful) {
+            LOG.error("Invalid security group mode ({}) obtained from AclserviceConfig. dpId={}", securityGroupMode,
+                    dpId);
+            return;
         }
+        jobCoordinator.enqueueJob(String.valueOf(dpId), () -> {
+            WriteTransaction tx = this.dataBroker.newWriteOnlyTransaction();
+            new AclNodeDefaultFlowsTxBuilder(dpId, mdsalManager, config, tx).build();
 
-        FlowEntity synFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                "SYN-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
-                AclConstants.PROTO_MATCH_SYN_ALLOW_PRIORITY, "Egress Syn ACL Table " + config.getDefaultBehavior(),
-                0, 0, AclConstants.COOKIE_ACL_BASE, synMatches, synInstructions);
-        mdsalManager.installFlow(synFlowEntity);
-
-        synMatches = new ArrayList<>();
-        synMatches.add(MatchEthernetType.IPV4);
-        synMatches.add(MatchIpProtocol.TCP);
-        synMatches.add(MatchTcpFlags.SYN_ACK);
-
-        FlowEntity synAckFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                "SYN-ACK-DEFAULT_ALLOW-" + getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE),
-                AclConstants.PROTO_MATCH_SYN_ACK_ALLOW_PRIORITY, "Egress Syn Ack ACL Table Allow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, synMatches, allowAllInstructions);
-        mdsalManager.installFlow(synAckFlowEntity);
-
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_TABLE), 0, "Egress Stateless ACL Table Miss Flow", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, mkMatches, allowAllInstructions);
-        mdsalManager.installFlow(flowEntity);
-
-        addEgressAclRemoteAclTableMissFlow(dpId);
-
-        short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
-        List<ActionInfo> actionsInfos = new ArrayList<>();
-        List<InstructionInfo> dispatcherInstructions = new ArrayList<>();
-        actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
-        dispatcherInstructions.add(new InstructionApplyActions(actionsInfos));
-        FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
-                getTableMissFlowId(NwConstants.EGRESS_ACL_FILTER_TABLE), 0,
-                "Egress Stateless Next ACL Table Miss Flow", 0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches,
-                dispatcherInstructions);
-        mdsalManager.installFlow(nextTblFlowEntity);
-
-        LOG.debug("Added Stateless Egress ACL Table Miss Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the ingress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addStatefulIngressAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> instructionsAcl = config.getDefaultBehavior() == DefaultBehavior.Deny
-                ? AclServiceOFFlowBuilder.getDropInstructionInfo()
-                : AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.INGRESS_ACL_REMOTE_ACL_TABLE);
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_TABLE,
-            getTableMissFlowId(NwConstants.INGRESS_ACL_TABLE), 0, "Ingress ACL Table Miss Flow", 0, 0,
-            AclConstants.COOKIE_ACL_BASE, mkMatches, instructionsAcl);
-        mdsalManager.installFlow(flowEntity);
-
-        addIngressAclRemoteAclTableMissFlow(dpId);
-
-        List<InstructionInfo> instructionsAclFilter = config.getDefaultBehavior() == DefaultBehavior.Deny
-                ? AclServiceOFFlowBuilder.getDropInstructionInfo()
-                : AclServiceOFFlowBuilder.getResubmitInstructionInfo(NwConstants.LPORT_DISPATCHER_TABLE);
-        FlowEntity nextTblFlowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
-            getTableMissFlowId(NwConstants.INGRESS_ACL_FILTER_TABLE), 0, "Ingress ACL Table Miss Flow", 0, 0,
-            AclConstants.COOKIE_ACL_BASE, mkMatches, instructionsAclFilter);
-        mdsalManager.installFlow(nextTblFlowEntity);
-
-        LOG.debug("Added Stateful Ingress ACL Table Miss Flows for dpn {}", dpId);
-    }
-
-    /**
-     * Adds the ingress acl table miss flow.
-     *
-     * @param dpId the dp id
-     */
-    private void addIngressAclRemoteAclTableMissFlow(BigInteger dpId) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        List<InstructionInfo> mkInstructions = new ArrayList<>();
-        mkInstructions.add(new InstructionGotoTable(NwConstants.INGRESS_ACL_FILTER_TABLE));
-
-        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INGRESS_ACL_REMOTE_ACL_TABLE,
-                getTableMissFlowId(NwConstants.INGRESS_ACL_REMOTE_ACL_TABLE), 0, "Ingress ACL Remote Table Miss Flow",
-                0, 0, AclConstants.COOKIE_ACL_BASE, mkMatches, mkInstructions);
-        mdsalManager.installFlow(flowEntity);
-
-        LOG.debug("Added Ingress ACL Remote Table Miss Flows for dpn {}", dpId);
-    }
-
-    private void addConntrackRules(BigInteger dpnId, short dispatcherTableId,short tableId, int write) {
-        programConntrackForwardRule(dpnId, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,
-            "Tracked_Established", AclConstants.TRACKED_EST_CT_STATE, AclConstants.TRACKED_EST_CT_STATE_MASK,
-            dispatcherTableId, tableId, write);
-        programConntrackForwardRule(dpnId, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,"Tracked_Related", AclConstants
-            .TRACKED_REL_CT_STATE, AclConstants.TRACKED_REL_CT_STATE_MASK, dispatcherTableId, tableId, write);
-    }
-
-    private void addConntrackDummyLookup(BigInteger dpnId, int write) {
-        addConntrackIngressDummyLookup(dpnId, write);
-    }
-
-    private void addConntrackIngressDummyLookup(BigInteger dpnId, int write) {
-        List<MatchInfoBase> matches = new ArrayList<>();
-        matches.add(MatchEthernetType.IPV4);
-        matches.add(new NxMatchCtState(AclConstants.TRACKED_CT_STATE, AclConstants.TRACKED_CT_STATE_MASK));
-        int elanTag = dummyTag;
-        List<InstructionInfo> instructions = new ArrayList<>();
-        List<ActionInfo> actionsInfos = new ArrayList<>();
-        actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag, NwConstants.EGRESS_ACL_TABLE));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-        String flowName = "Egress_Fixed_Dummy_Table_Ipv4_" + dpnId;
-        syncFlow(dpnId, AclConstants.EGRESS_ACL_DUMMY_TABLE, flowName, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,
-                "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, write);
-        matches = new ArrayList<>();
-        matches.add(MatchEthernetType.IPV6);
-        matches.add(new NxMatchCtState(AclConstants.TRACKED_CT_STATE, AclConstants.TRACKED_CT_STATE_MASK));
-        flowName = "Egress_Fixed_Dummy_Table_Ipv6_" + dpnId;
-        syncFlow(dpnId, AclConstants.EGRESS_ACL_DUMMY_TABLE, flowName, AclConstants.CT_STATE_TRACKED_EXIST_PRIORITY,
-                "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, write);
-
-        //Adding dummy lookup miss entry
-        matches = new ArrayList<>();
-        instructions = new ArrayList<>();
-        instructions.add(new InstructionGotoTable(NwConstants.EGRESS_ACL_TABLE));
-        flowName = "Egress_Fixed_Dummy_Table_Miss_" + dpnId;
-        syncFlow(dpnId, AclConstants.EGRESS_ACL_DUMMY_TABLE, flowName, AclConstants.PROTO_MATCH_PRIORITY, "ACL", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, matches, instructions, write);
-    }
-
-    /**
-     * Adds the rule to forward the packets known packets.
-     *
-     * @param dpId the dpId
-     * @param priority the priority of the flow
-     * @param flowId the flowId
-     * @param conntrackState the conntrack state of the packets thats should be
-     *        send
-     * @param conntrackMask the conntrack mask
-     * @param dispatcherTableId the dispatcher table id
-     * @param tableId the table id
-     * @param addOrRemove whether to add or remove the flow
-     */
-    private void programConntrackForwardRule(BigInteger dpId, Integer priority, String flowId,
-            int conntrackState, int conntrackMask, short dispatcherTableId, short tableId, int addOrRemove) {
-        List<MatchInfoBase> matches = new ArrayList<>();
-        matches.add(new NxMatchCtState(conntrackState, conntrackMask));
-
-        List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(
-            new ArrayList<>(),dispatcherTableId);
-
-        flowId = "Fixed_Conntrk_Trk_" + dpId + "_" + flowId + dispatcherTableId;
-        syncFlow(dpId, tableId, flowId, priority, "ACL", 0, 0,
-                AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
-    }
-
-    /**
-     * Gets the dispatcher table resubmit instructions.
-     *
-     * @param actionsInfos the actions infos
-     * @param dispatcherTableId the dispatcher table id
-     * @return the instructions for dispatcher table resubmit
-     */
-    private List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos,
-                                                                         short dispatcherTableId) {
-        List<InstructionInfo> instructions = new ArrayList<>();
-        actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
-        instructions.add(new InstructionApplyActions(actionsInfos));
-        return instructions;
-    }
-
-    /**
-     * Writes/remove the flow to/from the datastore.
-     * @param dpId the dpId
-     * @param tableId the tableId
-     * @param flowId the flowId
-     * @param priority the priority
-     * @param flowName the flow name
-     * @param idleTimeOut the idle timeout
-     * @param hardTimeOut the hard timeout
-     * @param cookie the cookie
-     * @param matches the list of matches to be written
-     * @param instructions the list of instruction to be written.
-     * @param addOrRemove add or remove the entries.
-     */
-    protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
-                          int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase>  matches,
-                          List<InstructionInfo> instructions, int addOrRemove) {
-        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: {}, flowName: {}, tableId: {}", dpId,
-                flowId, flowName, tableId);
-            mdsalManager.removeFlow(flowEntity);
-        } else {
-            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId,
-                priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, instructions);
-            LOG.trace("Installing Acl Flow:: DpnId: {}, flowId: {}, flowName: {}, tableId: {}", dpId,
-                flowId, flowName, tableId);
-            mdsalManager.installFlow(flowEntity);
-        }
-    }
+            LOG.info("Adding default ACL flows for dpId={}", dpId);
+            return Collections.singletonList(tx.submit());
+        }, AclConstants.JOB_MAX_RETRIES);
 
-    /**
-     * Gets the table miss flow id.
-     *
-     * @param tableId the table id
-     * @return the table miss flow id
-     */
-    private String getTableMissFlowId(short tableId) {
-        return String.valueOf(tableId);
+        LOG.trace("FlowCapableNode (dpid: {}) add event is processed.", dpId);
     }
 
     @Override