NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / utils / AclServiceUtils.java
index a477cd0604cbd94ff3b5b0608c5687e3ba0205ad..d75420ab8f20e2ad4a2bdfede11fb8eff380e9ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
+ * Copyright (c) 2016, 2018 Red Hat, Inc. and others. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -8,7 +8,10 @@
 
 package org.opendaylight.netvirt.aclservice.utils;
 
-import com.google.common.base.Optional;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
+import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
+import static org.opendaylight.mdsal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
+
 import com.google.common.collect.Lists;
 import com.google.common.net.InetAddresses;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -18,37 +21,29 @@ import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import javax.annotation.Nullable;
 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.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.genius.infra.Datastore.Operational;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
-import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
-import org.opendaylight.genius.mdsalutil.NxMatchInfo;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
@@ -68,6 +63,10 @@ import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
+import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.ReadTransaction;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
@@ -84,25 +83,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
@@ -117,10 +101,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.ser
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclPortsLookup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclserviceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.PortsSubnetIpPrefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpVersionV6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIpKey;
@@ -130,8 +116,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev16060
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
@@ -139,10 +124,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.NetvirtAcl;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -150,23 +136,21 @@ import org.slf4j.LoggerFactory;
 public final class AclServiceUtils {
 
     private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
-    public static final AclserviceConfig.DefaultBehavior DEFAULT_DENY = AclserviceConfig.DefaultBehavior.Deny;
-    public static final AclserviceConfig.DefaultBehavior DEFAULT_ALLOW = AclserviceConfig.DefaultBehavior.Allow;
 
     private final DataBroker dataBroker;
     private final ManagedNewTransactionRunner txRunner;
     private final AclDataUtil aclDataUtil;
     private final AclserviceConfig config;
-    private final IdManagerService idManager;
+    private final JobCoordinator jobCoordinator;
 
     @Inject
     public AclServiceUtils(DataBroker dataBroker, AclDataUtil aclDataUtil, AclserviceConfig config,
-            IdManagerService idManager) {
+            JobCoordinator jobCoordinator) {
         this.dataBroker = dataBroker;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.aclDataUtil = aclDataUtil;
         this.config = config;
-        this.idManager = idManager;
+        this.jobCoordinator = jobCoordinator;
     }
 
     /**
@@ -203,58 +187,12 @@ public final class AclServiceUtils {
      */
     public static <T extends DataObject> Optional<T> read(
             DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
-        try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
-            return tx.read(datastoreType, path).checkedGet();
-        } catch (ReadFailedException e) {
+        try (ReadTransaction tx = broker.newReadOnlyTransaction()) {
+            return tx.read(datastoreType, path).get();
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
-            return Optional.absent();
-        }
-    }
-
-    /**
-     * Retrieves the acl matching the key from the data store.
-     *
-     * @param broker the data broker
-     * @param aclKey the acl key
-     * @return the acl
-     */
-    public static Acl getAcl(DataBroker broker, String aclKey) {
-        return read(broker, LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey)).orNull();
-    }
-
-    /** Creates the Acl instance identifier.
-     *
-     * @param aclKey the acl key
-     * @return the instance identifier
-     */
-    public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
-        return InstanceIdentifier.builder(AccessLists.class).child(Acl.class, new AclKey(aclKey, Ipv4Acl.class))
-                .build();
-    }
-
-    /**
-     * Get the data path number for the interface.
-     * @param interfaceManagerRpcService interfaceManagerRpcService instance.
-     * @param ifName the interface name.
-     * @return the dpn.
-     */
-    public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
-        BigInteger nodeId = BigInteger.ZERO;
-        try {
-            GetDpidFromInterfaceInput dpIdInput =
-                    new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
-            Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
-                    interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
-            RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
-            if (dpIdResult.isSuccessful()) {
-                nodeId = dpIdResult.getResult().getDpid();
-            } else {
-                LOG.error("Could not retrieve DPN Id for interface {}", ifName);
-            }
-        } catch (NullPointerException | InterruptedException | ExecutionException e) {
-            LOG.error("Exception when getting dpn for interface {}", ifName,  e);
+            return Optional.empty();
         }
-        return nodeId;
     }
 
     /**
@@ -264,10 +202,10 @@ public final class AclServiceUtils {
      * @return the interface state.
      */
     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
-        .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
+        .@Nullable Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
             .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
-        return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
+        return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orElse(null);
     }
 
     /**
@@ -285,47 +223,18 @@ public final class AclServiceUtils {
         return idBuilder.build();
     }
 
-    /**
-     * Checks whether port security is enabled for the port.
-     * @param port the port.
-     * @return the port security is enabled/not.
-     */
-    public static boolean isPortSecurityEnabled(AclInterface port) {
-        return port.isPortSecurityEnabled();
-    }
-
-    /**
-     * Checks whether port security is enabled for the port.
-     * @param port the port.
-     * @return the list of security groups.
-     */
-    public static List<Uuid> getInterfaceAcls(Interface port) {
-        if (port == null) {
-            LOG.error("Port is Null");
-            return null;
-        }
-        InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
-        if (aclInPort == null) {
-            LOG.error("getSecurityGroupInPortList: no security group associated with port {}",
-                port.getName());
-            return null;
-        }
-        return aclInPort.getSecurityGroups();
-    }
-
     /**
      * Retrieves the security rule attribute augmentation from the access list.
      * @param ace the access list entry
      * @return the security rule attributes
      */
-    public static SecurityRuleAttr  getAccesssListAttributes(Ace ace) {
+    @Nullable
+    public static SecurityRuleAttr getAccessListAttributes(Ace ace) {
         if (ace == null) {
-            LOG.error("Ace is Null");
             return null;
         }
-        SecurityRuleAttr aceAttributes = ace.getAugmentation(SecurityRuleAttr.class);
+        SecurityRuleAttr aceAttributes = ace.augmentation(SecurityRuleAttr.class);
         if (aceAttributes == null) {
-            LOG.error("Ace is null");
             return null;
         }
         return aceAttributes;
@@ -382,7 +291,7 @@ public final class AclServiceUtils {
      */
     public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag,
             Class<? extends ServiceModeBase> serviceMode) {
-        List<MatchInfoBase> matches = new ArrayList<>(6);
+        List<MatchInfoBase> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV6);
         matches.add(MatchIpProtocol.ICMPV6);
         if (icmpType != 0) {
@@ -395,7 +304,7 @@ public final class AclServiceUtils {
     public static List<MatchInfoBase> buildBroadcastIpV4Matches(String ipAddr) {
         List<MatchInfoBase> matches = new ArrayList<>(2);
         matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
-        matches.addAll(AclServiceUtils.buildIpMatches(new IpPrefixOrAddress(ipAddr.toCharArray()),
+        matches.addAll(AclServiceUtils.buildIpMatches(IpPrefixOrAddressBuilder.getDefaultInstance(ipAddr),
                 MatchCriteria.MATCH_DESTINATION));
         return matches;
     }
@@ -432,10 +341,10 @@ public final class AclServiceUtils {
      * @return the bound services
      */
     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
-            BigInteger cookie, List<Instruction> instructions) {
+            Uint64 cookie, List<Instruction> instructions) {
         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
                 .setInstruction(instructions);
-        return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
+        return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
                 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
     }
@@ -449,22 +358,15 @@ public final class AclServiceUtils {
             return newAclList;
         }
         List<Uuid> origAclList = new ArrayList<>(currentAclList);
-        for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
-            Uuid updatedAclUuid = iterator.next();
-            for (Uuid currentAclUuid :origAclList) {
-                if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
-                    iterator.remove();
-                }
-            }
-        }
+        newAclList.removeAll(origAclList);
         return newAclList;
     }
 
     public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
-            List<AllowedAddressPairs> updatedAllowedAddressPairs,
-            List<AllowedAddressPairs> currentAllowedAddressPairs) {
+            @Nullable List<AllowedAddressPairs> updatedAllowedAddressPairs,
+            @Nullable List<AllowedAddressPairs> currentAllowedAddressPairs) {
         if (updatedAllowedAddressPairs == null) {
-            return null;
+            return Collections.emptyList();
         }
         List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
         if (currentAllowedAddressPairs == null) {
@@ -474,7 +376,7 @@ public final class AclServiceUtils {
         for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
             AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
             for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
-                if (updatedAllowedAddressPair.getKey().equals(currentAllowedAddressPair.getKey())) {
+                if (updatedAllowedAddressPair.key().equals(currentAllowedAddressPair.key())) {
                     iterator.remove();
                     break;
                 }
@@ -483,19 +385,7 @@ public final class AclServiceUtils {
         return newAllowedAddressPairs;
     }
 
-    public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
-        if (port == null) {
-            LOG.error("Port is Null");
-            return null;
-        }
-        InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
-        if (aclInPort == null) {
-            LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
-            return null;
-        }
-        return aclInPort.getAllowedAddressPairs();
-    }
-
+    @Nullable
     public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
             .interfaces.rev140508.interfaces.state.Interface interfaceState) {
         BigInteger dpId = null;
@@ -507,10 +397,10 @@ public final class AclServiceUtils {
         return dpId;
     }
 
-    public static List<String> getIpBroadcastAddresses(List<IpPrefixOrAddress> cidrs) {
+    public static List<String> getIpBroadcastAddresses(List<SubnetInfo> subnetInfoList) {
         List<String> ipBroadcastAddresses = new ArrayList<>();
-        for (IpPrefixOrAddress cidr : cidrs) {
-            IpPrefix cidrIpPrefix = cidr.getIpPrefix();
+        for (SubnetInfo subnetInfo : subnetInfoList) {
+            IpPrefix cidrIpPrefix = subnetInfo.getIpPrefix().getIpPrefix();
             if (cidrIpPrefix != null) {
                 Ipv4Prefix cidrIpv4Prefix = cidrIpPrefix.getIpv4Prefix();
                 if (cidrIpv4Prefix != null) {
@@ -602,8 +492,13 @@ public final class AclServiceUtils {
                 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
     }
 
-    public static BigInteger getRemoteAclTagMetadata(BigInteger remoteAclTag) {
-        return remoteAclTag.shiftLeft(4);
+    public static Uint64 getRemoteAclTagMetadata(BigInteger remoteAclTag) {
+        return Uint64.valueOf(remoteAclTag.shiftLeft(4));
+    }
+
+    public static Uint64 getDropFlowCookie(int lport) {
+        return Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lport).longValue()
+                   | AclConstants.COOKIE_ACL_DROP_FLOW.longValue());
     }
 
     /**
@@ -687,10 +582,10 @@ public final class AclServiceUtils {
             // In case of ingress service mode, only metadata is used for
             // matching both lportTag and aclTag. Hence performing "or"
             // operation on both lportTag and aclTag metadata.
-            BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
-                    .or(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)));
-            BigInteger metaDataMask =
-                    MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
+            Uint64 metaData = Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lportTag).longValue()
+                    | (getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)).longValue()));
+            Uint64 metaDataMask = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_LPORT_TAG.longValue()
+                    | MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG.longValue());
             matches.add(new MatchMetadata(metaData, metaDataMask));
         }
         return matches;
@@ -706,10 +601,11 @@ public final class AclServiceUtils {
             // In case of ingress service mode, only metadata is used for
             // matching both lportTag and conntrackClassifierType. Hence performing "or"
             // operation on both lportTag and conntrackClassifierType metadata.
-            BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
-                    .or(MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()));
-            BigInteger metaDataMask =
-                    MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
+            Uint64 metaData = Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lportTag).longValue()
+                    | (MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
+                       Uint64.valueOf(conntrackClassifierType.getValue()))).longValue());
+            Uint64 metaDataMask = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_LPORT_TAG.longValue()
+                   | MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE.longValue());
             matches.add(new MatchMetadata(metaData, metaDataMask));
         }
         return matches;
@@ -717,11 +613,16 @@ public final class AclServiceUtils {
 
     public static InstructionWriteMetadata getWriteMetadataForAclClassifierType(
             AclConntrackClassifierType conntrackClassifierType) {
-        return new InstructionWriteMetadata(
-                MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()),
+        return new InstructionWriteMetadata(MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
+                Uint64.valueOf(conntrackClassifierType.getValue())),
                 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
     }
 
+    public static InstructionWriteMetadata getWriteMetadataForDropFlag() {
+        return new InstructionWriteMetadata(MetaDataUtil.getAclDropMetaData(AclConstants.METADATA_DROP_FLAG),
+                MetaDataUtil.METADATA_MASK_ACL_DROP);
+    }
+
     public static InstructionWriteMetadata getWriteMetadataForRemoteAclTag(Integer remoteAclTag) {
         return new InstructionWriteMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
                 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
@@ -730,8 +631,9 @@ public final class AclServiceUtils {
     public static MatchInfoBase buildAclConntrackClassifierTypeMatch(
             AclConntrackClassifierType conntrackSupportedType) {
         return new MatchMetadata(
-                MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackSupportedType.getValue()),
-                MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
+                MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
+                    Uint64.valueOf(conntrackSupportedType.getValue())),
+                    MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
     }
 
     public AclserviceConfig getConfig() {
@@ -754,36 +656,6 @@ public final class AclServiceUtils {
         return false;
     }
 
-    public static Map<String, List<MatchInfoBase>> getFlowForAllowedAddresses(
-            List<AllowedAddressPairs> syncAllowedAddresses, Map<String, List<MatchInfoBase>> flowMatchesMap,
-            boolean isSourceIpMacMatch) {
-        if (flowMatchesMap == null) {
-            return null;
-        }
-        Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
-        MatchInfoBase ipv4Match = MatchEthernetType.IPV4;
-        MatchInfoBase ipv6Match = MatchEthernetType.IPV6;
-        for (Entry<String, List<MatchInfoBase>> entry : flowMatchesMap.entrySet()) {
-            String flowName = entry.getKey();
-            List<MatchInfoBase> flows = entry.getValue();
-            // iterate over allow address pair and update match type
-            for (AllowedAddressPairs aap : syncAllowedAddresses) {
-                List<MatchInfoBase> matchInfoBaseList;
-                String flowId;
-                if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) {
-                    matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
-                    flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap);
-                    updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
-                } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) {
-                    matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
-                    flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap);
-                    updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
-                }
-            }
-        }
-        return updatedFlowMatchesMap;
-    }
-
     public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) {
         IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
         if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null
@@ -806,22 +678,20 @@ public final class AclServiceUtils {
         return isNotIpv4AllNetwork(aap) && isNotIpv6AllNetwork(aap);
     }
 
-    private static String getAapFlowId(AllowedAddressPairs aap) {
-        return aap.getMacAddress().getValue() + "_" + String.valueOf(aap.getIpAddress().getValue());
-    }
-
-    public static Long getElanIdFromInterface(String elanInterfaceName,DataBroker broker) {
+    @Nullable
+    public static Long getElanIdFromInterface(String elanInterfaceName, DataBroker broker) {
         ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
         if (null != elanInterface) {
             ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
-            return elanInfo.getElanTag();
+            return elanInfo != null ? elanInfo.getElanTag().toJava() : null;
         }
         return null;
     }
 
+    @Nullable
     public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
-        return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
+        return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orElse(null);
     }
 
     public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
@@ -830,9 +700,10 @@ public final class AclServiceUtils {
     }
 
     // elan-instances config container
+    @Nullable
     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
-        return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
+        return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orElse(null);
     }
 
     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
@@ -840,191 +711,67 @@ public final class AclServiceUtils {
                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
     }
 
-    public static List<IpPrefixOrAddress> getSubnetIpPrefixes(DataBroker broker, String portId) {
-        InstanceIdentifier<PortSubnetIpPrefixes> id = InstanceIdentifier.builder(PortsSubnetIpPrefixes.class)
-                .child(PortSubnetIpPrefixes.class, new PortSubnetIpPrefixesKey(portId)).build();
-        Optional<PortSubnetIpPrefixes> portSubnetIpPrefixes = read(broker, LogicalDatastoreType.OPERATIONAL, id);
-        if (portSubnetIpPrefixes.isPresent()) {
-            return portSubnetIpPrefixes.get().getSubnetIpPrefixes();
-        }
-        return null;
-    }
-
-    public static void deleteSubnetIpPrefixes(DataBroker broker, String portId) {
-        InstanceIdentifier<PortSubnetIpPrefixes> id = InstanceIdentifier.builder(PortsSubnetIpPrefixes.class)
-                    .child(PortSubnetIpPrefixes.class, new PortSubnetIpPrefixesKey(portId)).build();
-        MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
-    }
-
-    private static List<MatchInfoBase> updateAAPMatches(boolean isSourceIpMacMatch, List<MatchInfoBase> flows,
-                                                        AllowedAddressPairs aap) {
-        List<MatchInfoBase> matchInfoBaseList;
-        if (isSourceIpMacMatch) {
-            matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_SOURCE);
-        } else {
-            matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_DESTINATION);
-        }
-        matchInfoBaseList.addAll(flows);
-        return matchInfoBaseList;
-    }
-
-    public static MatchInfoBase getMatchInfoByType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
-        for (MatchInfoBase mib : flows) {
-            if (type.isAssignableFrom(mib.getClass())) {
-                return mib;
-            }
-        }
-        return null;
-    }
-
-    public static boolean containsMatchFieldType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
-        return getMatchInfoByType(flows, type) != null;
-    }
-
-    public static boolean containsTcpMatchField(List<MatchInfoBase> flows) {
-        return flows.contains(MatchIpProtocol.TCP);
-    }
-
-    public static boolean containsUdpMatchField(List<MatchInfoBase> flows) {
-        return flows.contains(MatchIpProtocol.UDP);
-    }
-
-    public static Integer allocateId(IdManagerService idManager, String poolName, String idKey, Integer defaultId) {
-        AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
-        try {
-            Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
-            RpcResult<AllocateIdOutput> rpcResult = result.get();
-            if (rpcResult.isSuccessful()) {
-                Integer allocatedId = rpcResult.getResult().getIdValue().intValue();
-                LOG.debug("Allocated ACL ID: {} with key: {} into pool: {}", allocatedId, idKey, poolName);
-                return allocatedId;
-            } else {
-                LOG.error("RPC Call to Get Unique Id for key {} from pool {} returned with Errors {}",
-                        idKey, poolName, rpcResult.getErrors());
-            }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("Exception when getting Unique Id for key {} from pool {} ", idKey, poolName, e);
-        }
-        return defaultId;
-    }
-
-    public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
-        ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
-        try {
-            Future<RpcResult<Void>> result = idManager.releaseId(idInput);
-            RpcResult<Void> rpcResult = result.get();
-            if (!rpcResult.isSuccessful()) {
-                LOG.error("RPC Call to release Id with Key {} from pool {} returned with Errors {}",
-                        idKey, poolName, rpcResult.getErrors());
-            } else {
-                LOG.debug("Released ACL ID with key: {} from pool: {}", idKey, poolName);
-            }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("Exception when releasing Id for key {} from pool {} ", idKey, poolName, e);
+    public void deleteAcesFromConfigDS(String aclName, List<Ace> deletedAceRules) {
+        List<List<Ace>> acesParts = Lists.partition(deletedAceRules, AclConstants.ACES_PER_TRANSACTION);
+        for (List<Ace> acePart : acesParts) {
+            jobCoordinator.enqueueJob(aclName,
+                () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
+                    tx -> {
+                        for (Ace ace: acePart) {
+                            InstanceIdentifier<Ace> id = InstanceIdentifier.builder(AccessLists.class)
+                                    .child(Acl.class, new AclKey(aclName, Ipv4Acl.class)).child(AccessListEntries.class)
+                                    .child(Ace.class, ace.key()).build();
+                            tx.delete(id);
+                        }
+                    })), AclConstants.ACEDELETE_MAX_RETRIES);
         }
     }
 
     /**
-     * Gets the ACL tag from cache. If not found in cache, tries to allocate and
-     * return the value.
-     *
-     * @param aclId the acl id
+     * Gets ACL tag from Acl.
+     * @param acl Acl object
      * @return the acl tag
      */
-    public Integer getAclTag(final Uuid aclId) {
-        String aclName = aclId.getValue();
-        Integer aclTag = this.aclDataUtil.getAclTag(aclName);
-        if (aclTag == null) {
-            LOG.debug("ACL tag not found in cache for ACL={}, trying to allocate again.", aclName);
-            aclTag = allocateAclTag(aclName);
-            if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
-                this.aclDataUtil.addAclTag(aclName, aclTag);
-            }
+    public static Integer getAclTag(Acl acl) {
+        Integer aclTag = null;
+        AclserviceAugmentation aclserviceAugmentation = acl.augmentation(AclserviceAugmentation.class);
+        if (aclserviceAugmentation != null) {
+            aclTag = aclserviceAugmentation.getAclTag().intValue();
         }
         return aclTag;
     }
 
     /**
-     * Allocate ACL tag.
-     *
-     * @param aclName the ACL name
-     * @return the integer
-     */
-    public Integer allocateAclTag(String aclName) {
-        Integer aclTag = AclServiceUtils.allocateId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName,
-                AclConstants.INVALID_ACL_TAG);
-        return aclTag;
-    }
-
-    /**
-     * Release ACL tag.
+     * Gets the ACL tag from cache.
      *
-     * @param aclName the ACL name
+     * @param aclId the acl id
+     * @return the acl tag
      */
-    public void releaseAclTag(String aclName) {
-        AclServiceUtils.releaseId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName);
+    public Integer getAclTag(final Uuid aclId) {
+        String aclName = aclId.getValue();
+        return this.aclDataUtil.getAclTag(aclName);
     }
 
     /**
-     * Indicates whether the interface has port security enabled.
+     * Indicates whether the interface has port security enabled or interface is DHCP service port.
      *
      * @param aclInterface the interface.
-     * @return true if port is security enabled.
+     * @return true if port is security enabled or is a DHCP service port.
      */
     public static boolean isOfInterest(AclInterface aclInterface) {
-        return aclInterface != null && aclInterface.isPortSecurityEnabled();
+        return aclInterface != null && (aclInterface.isPortSecurityEnabled()
+                || aclInterface.getInterfaceType() == InterfaceAcl.InterfaceType.DhcpService);
     }
 
     /**
-     * Creates the id pool for ACL tag.
+     * Indicates whether the interface has port security enabled or interface is DHCP service port.
      *
-     * @param poolName the pool name
-     */
-    private void createIdPoolForAclTag(String poolName) {
-        CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
-                .setPoolName(poolName).setLow(AclConstants.ACL_TAG_POOL_START)
-                .setHigh(AclConstants.ACL_TAG_POOL_END).build();
-        try {
-            Future<RpcResult<Void>> result = this.idManager.createIdPool(createPool);
-            if (result != null && result.get().isSuccessful()) {
-                LOG.debug("Created IdPool for {}", poolName);
-            }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("Failed to create ID pool [{}] for remote ACL ids", poolName, e);
-            throw new RuntimeException("Failed to create ID pool [{}] for remote ACL ids", e);
-        }
-    }
-
-    /**
-     * Delete id pool.
-     *
-     * @param poolName the pool name
-     */
-    public void deleteIdPool(String poolName) {
-        DeleteIdPoolInput deletePool = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
-        try {
-            Future<RpcResult<Void>> result = this.idManager.deleteIdPool(deletePool);
-            if (result != null && result.get().isSuccessful()) {
-                LOG.debug("Deleted IdPool for {}", poolName);
-            }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("Failed to delete ID pool [{}]", poolName, e);
-            throw new RuntimeException("Failed to delete ID pool [" + poolName + "]", e);
-        }
-    }
-
-    /**
-     * Creates remote the acl id pools.
-     */
-    public void createRemoteAclIdPool() {
-        createIdPoolForAclTag(AclConstants.ACL_TAG_POOL_NAME);
-    }
-
-    /**
-     * Delete remote the acl id pools.
+     * @param aclInterface the interface.
+     * @return true if port is security enabled or is a DHCP service port.
      */
-    public void deleteRemoteAclIdPool() {
-        deleteIdPool(AclConstants.ACL_TAG_POOL_NAME);
+    public static boolean isOfInterest(InterfaceAcl aclInterface) {
+        return aclInterface != null && (aclInterface.isPortSecurityEnabled()
+                || aclInterface.getInterfaceType() == InterfaceAcl.InterfaceType.DhcpService);
     }
 
     public static List<? extends MatchInfoBase> buildIpAndSrcServiceMatch(Integer aclTag, AllowedAddressPairs aap) {
@@ -1096,30 +843,17 @@ public final class AclServiceUtils {
         return flowMatches;
     }
 
-    public static boolean isOfAclInterest(Acl acl) {
-        if (acl.getAccessListEntries() != null) {
-            List<Ace> aceList = acl.getAccessListEntries().getAce();
-            if (aceList != null && !aceList.isEmpty()) {
-                return aceList.get(0).getAugmentation(SecurityRuleAttr.class) != null;
-            }
-        }
-        return false;
-    }
-
-    public static void addLportTagMetadataMatch(int lportTag, List<MatchInfoBase> flowMatches,
-            Class<? extends ServiceModeBase> serviceMode) {
-        MatchInfoBase lportMatch = buildLPortTagMatch(lportTag, serviceMode);
-        InterfaceServiceUtil.mergeMetadataMatchsOrAdd(flowMatches, lportMatch);
+    public static @NonNull List<Ace> aceList(@NonNull Acl acl) {
+        final AccessListEntries ale = acl.getAccessListEntries();
+        return ale == null ? Collections.emptyList() : ale.nonnullAce();
     }
 
-    /**
-     * Returns ACL specific key for synchronization.
-     *
-     * @param key the generic key
-     * @return ACL key that can be used with synchronization
-     */
-    public static String getAclKeyForSynchronization(String key) {
-        return key + AclConstants.ACL_SYNC_KEY_EXT;
+    public static @NonNull List<Ace> getAceListFromAcl(Acl acl) {
+        List<Ace> aceList = aceList(acl);
+        if (!aceList.isEmpty() && aceList.get(0).augmentation(SecurityRuleAttr.class) != null) {
+            return aceList;
+        }
+        return Collections.emptyList();
     }
 
     /**
@@ -1143,7 +877,7 @@ public final class AclServiceUtils {
         return aceAttr != null && aceAttr.getRemoteGroupId() != null;
     }
 
-    public SortedSet<Integer> getRemoteAclTags(List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
+    public SortedSet<Integer> getRemoteAclTags(@Nullable List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
         SortedSet<Integer> remoteAclTags = new TreeSet<>();
         Set<Uuid> remoteAclIds = getRemoteAclIdsByDirection(aclIds, direction);
         for (Uuid remoteAclId : remoteAclIds) {
@@ -1155,7 +889,7 @@ public final class AclServiceUtils {
         return remoteAclTags;
     }
 
-    public Set<Uuid> getRemoteAclIdsByDirection(List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
+    public Set<Uuid> getRemoteAclIdsByDirection(@Nullable List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
         Set<Uuid> remoteAclIds = new HashSet<>();
         if (aclIds == null || aclIds.isEmpty()) {
             return remoteAclIds;
@@ -1174,13 +908,11 @@ public final class AclServiceUtils {
 
     public static Set<Uuid> getRemoteAclIdsByDirection(Acl acl, Class<? extends DirectionBase> direction) {
         Set<Uuid> remoteAclIds = new HashSet<>();
-        AccessListEntries accessListEntries = acl.getAccessListEntries();
-        if (accessListEntries != null && accessListEntries.getAce() != null) {
-            for (Ace ace : accessListEntries.getAce()) {
-                SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace);
-                if (aceAttr.getDirection().equals(direction) && doesAceHaveRemoteGroupId(aceAttr)) {
-                    remoteAclIds.add(aceAttr.getRemoteGroupId());
-                }
+        for (Ace ace : aceList(acl)) {
+            SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
+            if (aceAttr != null && Objects.equals(aceAttr.getDirection(), direction)
+                    && doesAceHaveRemoteGroupId(aceAttr)) {
+                remoteAclIds.add(aceAttr.getRemoteGroupId());
             }
         }
         return remoteAclIds;
@@ -1215,7 +947,7 @@ public final class AclServiceUtils {
             List<PortIds> portIds = new ArrayList<>(aclIpPrefixes.getPortIds());
             // Checking if there are any other ports excluding ignorePorts
             long noOfRemotePorts =
-                    portIds.stream().map(x -> x.getPortId()).filter(y -> !ignorePorts.contains(y)).count();
+                    portIds.stream().map(PortIds::getPortId).filter(y -> !ignorePorts.contains(y)).count();
             if (noOfRemotePorts > 0) {
                 skipDelete = true;
             }
@@ -1223,9 +955,31 @@ public final class AclServiceUtils {
         return skipDelete;
     }
 
-    public static void deleteAclPortsLookupEntry(String aclName, DataBroker broker)
-            throws TransactionCommitFailedException {
-        SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, aclPortsByIpPath(aclName));
+    public boolean doesRemoteAclIdExistsInAcls(List<Uuid> aclIds, Uuid remoteAclId,
+            Class<? extends DirectionBase> direction) {
+        if (aclIds == null) {
+            return false;
+        }
+        for (Uuid aclId : aclIds) {
+            Acl acl = this.aclDataUtil.getAcl(aclId.getValue());
+            if (null == acl) {
+                LOG.warn("ACL {} not found in cache.", aclId.getValue());
+                continue;
+            }
+            AccessListEntries accessListEntries = acl.getAccessListEntries();
+            if (accessListEntries != null && accessListEntries.getAce() != null) {
+                for (Ace ace : accessListEntries.getAce()) {
+                    SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
+                    if (aceAttr != null && aceAttr.getDirection().equals(direction)
+                            && doesAceHaveRemoteGroupId(aceAttr)) {
+                        if (aceAttr.getRemoteGroupId().equals(remoteAclId)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        return false;
     }
 
     public static InstanceIdentifier<AclPortsByIp> aclPortsByIpPath(String aclName) {
@@ -1245,41 +999,35 @@ public final class AclServiceUtils {
                 .build();
     }
 
-    public List<ListenableFuture<Void>> addAclPortsLookupForInterfaceUpdate(AclInterface portBefore,
-            AclInterface portAfter) {
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+    public void addAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
         LOG.debug("Processing interface additions for port {}", portAfter.getInterfaceId());
         List<AllowedAddressPairs> addedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
                 portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
-        if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
-            futures.addAll(addAclPortsLookup(portAfter, portAfter.getSecurityGroups(), addedAllowedAddressPairs));
+        if (!addedAllowedAddressPairs.isEmpty()) {
+            addAclPortsLookup(portAfter, portAfter.getSecurityGroups(), addedAllowedAddressPairs);
         }
 
         List<Uuid> addedAcls = getUpdatedAclList(portAfter.getSecurityGroups(), portBefore.getSecurityGroups());
-        if (addedAcls != null && !addedAcls.isEmpty()) {
-            futures.addAll(addAclPortsLookup(portAfter, addedAcls, portAfter.getAllowedAddressPairs()));
+        if (!addedAcls.isEmpty()) {
+            addAclPortsLookup(portAfter, addedAcls, portAfter.getAllowedAddressPairs());
         }
-        return futures;
     }
 
-    public List<ListenableFuture<Void>> deleteAclPortsLookupForInterfaceUpdate(AclInterface portBefore,
-            AclInterface portAfter) {
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+    public void deleteAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
         LOG.debug("Processing interface removals for port {}", portAfter.getInterfaceId());
         List<AllowedAddressPairs> deletedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
                 portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
-        if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
-            futures.addAll(deleteAclPortsLookup(portAfter, portAfter.getSecurityGroups(), deletedAllowedAddressPairs));
+        if (!deletedAllowedAddressPairs.isEmpty()) {
+            deleteAclPortsLookup(portAfter, portAfter.getSecurityGroups(), deletedAllowedAddressPairs);
         }
 
         List<Uuid> deletedAcls = getUpdatedAclList(portBefore.getSecurityGroups(), portAfter.getSecurityGroups());
-        if (deletedAcls != null && !deletedAcls.isEmpty()) {
-            futures.addAll(deleteAclPortsLookup(portAfter, deletedAcls, portAfter.getAllowedAddressPairs()));
+        if (!deletedAcls.isEmpty()) {
+            deleteAclPortsLookup(portAfter, deletedAcls, portAfter.getAllowedAddressPairs());
         }
-        return futures;
     }
 
-    public List<ListenableFuture<Void>> addAclPortsLookup(AclInterface port, List<Uuid> aclList,
+    public void addAclPortsLookup(AclInterface port, List<Uuid> aclList,
             List<AllowedAddressPairs> allowedAddresses) {
         String portId = port.getInterfaceId();
         LOG.trace("Adding AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
@@ -1287,28 +1035,28 @@ public final class AclServiceUtils {
         if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
             LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
                     allowedAddresses);
-            return Collections.emptyList();
+            return;
         }
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+
         for (Uuid aclId : aclList) {
             String aclName = aclId.getValue();
-            synchronized (aclName.intern()) {
-                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            jobCoordinator.enqueueJob(aclName, () -> {
+                List<ListenableFuture<Void>> futures = new ArrayList<>();
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
                     for (AllowedAddressPairs aap : allowedAddresses) {
                         PortIds portIdObj =
-                                new PortIdsBuilder().setKey(new PortIdsKey(portId)).setPortId(portId).build();
+                                new PortIdsBuilder().withKey(new PortIdsKey(portId)).setPortId(portId).build();
                         InstanceIdentifier<PortIds> path =
                                 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
-                        tx.put(LogicalDatastoreType.OPERATIONAL, path, portIdObj,
-                                WriteTransaction.CREATE_MISSING_PARENTS);
+                        tx.put(path, portIdObj, CREATE_MISSING_PARENTS);
                     }
                 }));
-            }
+                return futures;
+            });
         }
-        return futures;
     }
 
-    public List<ListenableFuture<Void>> deleteAclPortsLookup(AclInterface port, List<Uuid> aclList,
+    public void deleteAclPortsLookup(AclInterface port, List<Uuid> aclList,
             List<AllowedAddressPairs> allowedAddresses) {
         String portId = port.getInterfaceId();
         LOG.trace("Deleting AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
@@ -1316,27 +1064,28 @@ public final class AclServiceUtils {
         if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
             LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
                     allowedAddresses);
-            return Collections.emptyList();
+            return;
         }
-        List<ListenableFuture<Void>> futures = new ArrayList<>();
+
         for (Uuid aclId : aclList) {
             String aclName = aclId.getValue();
-            synchronized (aclName.intern()) {
-                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
+            jobCoordinator.enqueueJob(aclName, () -> {
+                List<ListenableFuture<Void>> futures = new ArrayList<>();
+                futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
                     for (AllowedAddressPairs aap : allowedAddresses) {
                         InstanceIdentifier<PortIds> path =
                                 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
-                        tx.delete(LogicalDatastoreType.OPERATIONAL, path);
+                        tx.delete(path);
                     }
 
                     cleanUpStaleEntriesInAclPortsLookup(aclName, tx);
                 }));
-            }
+                return futures;
+            });
         }
-        return futures;
     }
 
-    private void cleanUpStaleEntriesInAclPortsLookup(String aclName, WriteTransaction tx) {
+    private void cleanUpStaleEntriesInAclPortsLookup(String aclName, TypedWriteTransaction<Operational> tx) {
         AclPortsByIp aclPortsByIp = getAclPortsByIpFromOperDs(aclName);
         if (aclPortsByIp == null) {
             return;
@@ -1356,13 +1105,13 @@ public final class AclServiceUtils {
             deleteEntireAcl = deleteMap;
         }
         if (deleteEntireAcl) {
-            tx.delete(LogicalDatastoreType.OPERATIONAL, AclServiceUtils.aclPortsByIpPath(aclName));
+            tx.delete(AclServiceUtils.aclPortsByIpPath(aclName));
         } else {
             for (AclIpPrefixes ipPrefix : ipPrefixes) {
                 if (ipPrefix.getPortIds() == null || ipPrefix.getPortIds().isEmpty()) {
                     InstanceIdentifier<AclIpPrefixes> delPath =
                             AclServiceUtils.getAclIpPrefixesPath(aclName, ipPrefix.getIpPrefix());
-                    tx.delete(LogicalDatastoreType.OPERATIONAL, delPath);
+                    tx.delete(delPath);
                 }
             }
         }
@@ -1371,9 +1120,9 @@ public final class AclServiceUtils {
     @Nullable
     private AclPortsByIp getAclPortsByIpFromOperDs(String aclName) {
         InstanceIdentifier<AclPortsByIp> path = aclPortsByIpPath(aclName);
-        try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
-            return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
-        } catch (ReadFailedException e) {
+        try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) {
+            return tx.read(LogicalDatastoreType.OPERATIONAL, path).get().orElse(null);
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("Failed to read ACL ports {}", path, e);
             return null;
         }
@@ -1382,9 +1131,9 @@ public final class AclServiceUtils {
     @Nullable
     private AclIpPrefixes getAclIpPrefixesFromOperDs(String aclName, IpPrefixOrAddress ipPrefix) {
         InstanceIdentifier<AclIpPrefixes> path = getAclIpPrefixesPath(aclName, ipPrefix);
-        try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
-            return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
-        } catch (ReadFailedException e) {
+        try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) {
+            return tx.read(LogicalDatastoreType.OPERATIONAL, path).get().orElse(null);
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("Failed to read ACL IP prefixes {}", path, e);
             return null;
         }
@@ -1421,13 +1170,15 @@ public final class AclServiceUtils {
         int hardTimeout = AclConstants.SECURITY_GROUP_ICMP_IDLE_TIME_OUT;
         Matches matches = ace.getMatches();
         AceIp acl = (AceIp) matches.getAceType();
-        Short protocol = acl.getProtocol();
+        Short protocol = acl.getProtocol() != null ? acl.getProtocol().toJava() : null;
         if (protocol == null) {
             return hardTimeout;
-        } else if (protocol == NwConstants.IP_PROT_TCP) {
-            hardTimeout = aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout();
-        } else if (protocol == NwConstants.IP_PROT_UDP) {
-            hardTimeout = aclServiceUtils.getConfig().getSecurityGroupUdpIdleTimeout();
+        } else if (protocol == NwConstants.IP_PROT_TCP
+                && aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout() != null) {
+            hardTimeout = aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout().toJava();
+        } else if (protocol == NwConstants.IP_PROT_UDP
+                && aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout() != null) {
+            hardTimeout = aclServiceUtils.getConfig().getSecurityGroupUdpIdleTimeout().toJava();
         }
         return hardTimeout;
     }
@@ -1457,39 +1208,74 @@ public final class AclServiceUtils {
         return instructions;
     }
 
-    public static List<AllowedAddressPairs> excludeMulticastAAPs(List<AllowedAddressPairs> allowedAddresses) {
+    public static List<AllowedAddressPairs> excludeMulticastAAPs(@Nullable List<AllowedAddressPairs> allowedAddresses) {
         List<AllowedAddressPairs> filteredAAPs = new ArrayList<>();
-        for (AllowedAddressPairs allowedAddress : allowedAddresses) {
-            InetAddress inetAddr = getInetAddress(allowedAddress.getIpAddress());
-            if (inetAddr != null && !inetAddr.isMulticastAddress()) {
-                filteredAAPs.add(allowedAddress);
+        if (allowedAddresses != null) {
+            for (AllowedAddressPairs allowedAddress : allowedAddresses) {
+                InetAddress inetAddr = getInetAddress(allowedAddress.getIpAddress());
+                if (inetAddr != null && !inetAddr.isMulticastAddress()) {
+                    filteredAAPs.add(allowedAddress);
+                }
             }
         }
         return filteredAAPs;
     }
 
+    public static String getRecoverServiceRegistryKey() {
+        return NetvirtAcl.class.toString();
+    }
+
+    @Nullable
     private static InetAddress getInetAddress(IpPrefixOrAddress ipPrefixOrAddress) {
-        InetAddress inetAddress = null;
-        String addr = null;
+        String addr;
 
         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
         if (ipPrefix != null) {
-            addr = String.valueOf(ipPrefix.getValue()).split("/")[0];
+            addr = ipPrefix.stringValue().split("/")[0];
         } else {
             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
             if (ipAddress == null) {
                 LOG.error("Invalid address : {}", ipPrefixOrAddress);
                 return null;
             } else {
-                addr = String.valueOf(ipAddress.getValue());
+                addr = ipAddress.stringValue();
             }
         }
         try {
-            inetAddress = InetAddress.getByName(addr);
+            return InetAddress.getByName(addr);
         } catch (UnknownHostException e) {
             LOG.error("Invalid address : {}", addr, e);
             return null;
         }
-        return inetAddress;
+    }
+
+    public static Boolean isIpv6Subnet(List<SubnetInfo> subnetInfoList) {
+        if (subnetInfoList != null && !subnetInfoList.isEmpty()) {
+            for (SubnetInfo subnetInfo : subnetInfoList) {
+                if (subnetInfo != null && IpVersionV6.class.equals(subnetInfo.getIpVersion())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Gets the subnet difference by performing (subnetInfo1 - subnetInfo2).
+     *
+     * @param subnetInfo1 the subnet info 1
+     * @param subnetInfo2 the subnet info 2
+     * @return the subnet diff
+     */
+    public static List<SubnetInfo> getSubnetDiff(List<SubnetInfo> subnetInfo1, List<SubnetInfo> subnetInfo2) {
+        if (subnetInfo1 == null) {
+            return Collections.emptyList();
+        }
+        List<SubnetInfo> newSubnetList = new ArrayList<>(subnetInfo1);
+        if (subnetInfo2 == null) {
+            return newSubnetList;
+        }
+        newSubnetList.removeAll(subnetInfo2);
+        return newSubnetList;
     }
 }