More transaction clean-up in ACL
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / utils / AclServiceUtils.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.aclservice.utils;
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Lists;
13 import com.google.common.net.InetAddresses;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.Set;
26 import java.util.SortedSet;
27 import java.util.TreeSet;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.Future;
30 import javax.annotation.Nullable;
31 import javax.inject.Inject;
32 import javax.inject.Singleton;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
35 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
36 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
37 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
38 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
39 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
40 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
41 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
42 import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil;
43 import org.opendaylight.genius.mdsalutil.ActionInfo;
44 import org.opendaylight.genius.mdsalutil.InstructionInfo;
45 import org.opendaylight.genius.mdsalutil.MDSALUtil;
46 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
47 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
48 import org.opendaylight.genius.mdsalutil.NwConstants;
49 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
50 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
51 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
52 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
53 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
54 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
55 import org.opendaylight.genius.mdsalutil.matches.MatchArpSpa;
56 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
57 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
58 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
59 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
60 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
61 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
62 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Destination;
63 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source;
64 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
65 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
66 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
67 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
68 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
69 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
70 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
80 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
82 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclPortsLookup;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.PortsSubnetIpPrefixes;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIp;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIpKey;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixes;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixesKey;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIds;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsKey;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixes;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixesKey;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
140 import org.opendaylight.yangtools.yang.binding.DataObject;
141 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
142 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
143 import org.opendaylight.yangtools.yang.common.RpcResult;
144 import org.slf4j.Logger;
145 import org.slf4j.LoggerFactory;
146
147 @Singleton
148 public final class AclServiceUtils {
149
150     private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
151     public static final AclserviceConfig.DefaultBehavior DEFAULT_DENY = AclserviceConfig.DefaultBehavior.Deny;
152     public static final AclserviceConfig.DefaultBehavior DEFAULT_ALLOW = AclserviceConfig.DefaultBehavior.Allow;
153
154     private final DataBroker dataBroker;
155     private final ManagedNewTransactionRunner txRunner;
156     private final AclDataUtil aclDataUtil;
157     private final AclserviceConfig config;
158     private final IdManagerService idManager;
159
160     @Inject
161     public AclServiceUtils(DataBroker dataBroker, AclDataUtil aclDataUtil, AclserviceConfig config,
162             IdManagerService idManager) {
163         this.dataBroker = dataBroker;
164         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
165         this.aclDataUtil = aclDataUtil;
166         this.config = config;
167         this.idManager = idManager;
168     }
169
170     /**
171      * Retrieves the Interface from the datastore.
172      * @param broker the data broker
173      * @param interfaceName the interface name
174      * @return the interface.
175      */
176     public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
177         .Interface> getInterface(DataBroker broker, String interfaceName) {
178         return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
179     }
180
181     /**
182      * Builds the interface identifier.
183      * @param interfaceName the interface name.
184      * @return the interface identifier.
185      */
186     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
187         .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
188         return InstanceIdentifier.builder(Interfaces.class)
189                 .child(
190                     org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
191                     .Interface.class, new InterfaceKey(interfaceName)).build();
192     }
193
194     /**
195      * Retrieves the object from the datastore.
196      * @param broker the data broker.
197      * @param datastoreType the data store type.
198      * @param path the wild card path.
199      * @param <T> type of DataObject
200      * @return the required object.
201      */
202     public static <T extends DataObject> Optional<T> read(
203             DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
204         try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
205             return tx.read(datastoreType, path).checkedGet();
206         } catch (ReadFailedException e) {
207             LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
208             return Optional.absent();
209         }
210     }
211
212     /**
213      * Retrieves the acl matching the key from the data store.
214      *
215      * @param broker the data broker
216      * @param aclKey the acl key
217      * @return the acl
218      */
219     public static Acl getAcl(DataBroker broker, String aclKey) {
220         return read(broker, LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey)).orNull();
221     }
222
223     /** Creates the Acl instance identifier.
224      *
225      * @param aclKey the acl key
226      * @return the instance identifier
227      */
228     public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
229         return InstanceIdentifier.builder(AccessLists.class).child(Acl.class, new AclKey(aclKey, Ipv4Acl.class))
230                 .build();
231     }
232
233     /**
234      * Get the data path number for the interface.
235      * @param interfaceManagerRpcService interfaceManagerRpcService instance.
236      * @param ifName the interface name.
237      * @return the dpn.
238      */
239     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
240         BigInteger nodeId = BigInteger.ZERO;
241         try {
242             GetDpidFromInterfaceInput dpIdInput =
243                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
244             Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
245                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
246             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
247             if (dpIdResult.isSuccessful()) {
248                 nodeId = dpIdResult.getResult().getDpid();
249             } else {
250                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
251             }
252         } catch (NullPointerException | InterruptedException | ExecutionException e) {
253             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
254         }
255         return nodeId;
256     }
257
258     /**
259      * Retrieves the interface state.
260      * @param dataBroker the data broker.
261      * @param interfaceName the interface name.
262      * @return the interface state.
263      */
264     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
265         .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
266         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
267             .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
268         return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
269     }
270
271     /**
272      * Build the interface state.
273      * @param interfaceName the interface name.
274      * @return the interface state.
275      */
276     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
277         .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
278         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
279             .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
280             .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
281             .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
282             .rev140508.interfaces.state.InterfaceKey(interfaceName));
283         return idBuilder.build();
284     }
285
286     /**
287      * Checks whether port security is enabled for the port.
288      * @param port the port.
289      * @return the port security is enabled/not.
290      */
291     public static boolean isPortSecurityEnabled(AclInterface port) {
292         return port.isPortSecurityEnabled();
293     }
294
295     /**
296      * Checks whether port security is enabled for the port.
297      * @param port the port.
298      * @return the list of security groups.
299      */
300     public static List<Uuid> getInterfaceAcls(Interface port) {
301         if (port == null) {
302             LOG.error("Port is Null");
303             return null;
304         }
305         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
306         if (aclInPort == null) {
307             LOG.error("getSecurityGroupInPortList: no security group associated}",
308                 port.getName());
309             return null;
310         }
311         return aclInPort.getSecurityGroups();
312     }
313
314     /**
315      * Retrieves the security rule attribute augmentation from the access list.
316      * @param ace the access list entry
317      * @return the security rule attributes
318      */
319     public static SecurityRuleAttr  getAccesssListAttributes(Ace ace) {
320         if (ace == null) {
321             LOG.error("Ace is Null");
322             return null;
323         }
324         SecurityRuleAttr aceAttributes = ace.getAugmentation(SecurityRuleAttr.class);
325         if (aceAttributes == null) {
326             LOG.error("Ace is null");
327             return null;
328         }
329         return aceAttributes;
330     }
331
332     /**
333      * Returns the DHCP match.
334      *
335      * @param srcPort the source port.
336      * @param dstPort the destination port.
337      * @param lportTag the lport tag
338      * @param serviceMode ingress or egress service
339      * @return list of matches.
340      */
341     public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag,
342             Class<? extends ServiceModeBase> serviceMode) {
343         List<MatchInfoBase> matches = new ArrayList<>(5);
344         matches.add(MatchEthernetType.IPV4);
345         matches.add(MatchIpProtocol.UDP);
346         matches.add(new MatchUdpDestinationPort(dstPort));
347         matches.add(new MatchUdpSourcePort(srcPort));
348         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
349         return matches;
350     }
351
352     /**
353      * Returns the DHCPv6 match.
354      *
355      * @param srcPort the source port.
356      * @param dstPort the destination port.
357      * @param lportTag the lport tag
358      * @param serviceMode ingress or egress
359      * @return list of matches.
360      */
361     public static List<MatchInfoBase> buildDhcpV6Matches(int srcPort, int dstPort, int lportTag,
362             Class<? extends ServiceModeBase> serviceMode) {
363         List<MatchInfoBase> matches = new ArrayList<>(6);
364         matches.add(MatchEthernetType.IPV6);
365         matches.add(MatchIpProtocol.UDP);
366         matches.add(new MatchUdpDestinationPort(dstPort));
367         matches.add(new MatchUdpSourcePort(srcPort));
368         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
369         return matches;
370     }
371
372     /**
373      * Returns the ICMPv6 match.
374      *
375      * @param icmpType the icmpv6-type.
376      * @param icmpCode the icmpv6-code.
377      * @param lportTag the lport tag
378      * @param serviceMode ingress or egress
379      * @return list of matches.
380      */
381     public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag,
382             Class<? extends ServiceModeBase> serviceMode) {
383         List<MatchInfoBase> matches = new ArrayList<>(6);
384         matches.add(MatchEthernetType.IPV6);
385         matches.add(MatchIpProtocol.ICMPV6);
386         if (icmpType != 0) {
387             matches.add(new MatchIcmpv6((short) icmpType, (short) icmpCode));
388         }
389         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
390         return matches;
391     }
392
393     public static List<MatchInfoBase> buildBroadcastIpV4Matches(String ipAddr) {
394         List<MatchInfoBase> matches = new ArrayList<>(2);
395         matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
396         matches.addAll(AclServiceUtils.buildIpMatches(new IpPrefixOrAddress(ipAddr.toCharArray()),
397                 MatchCriteria.MATCH_DESTINATION));
398         return matches;
399     }
400
401     public static List<MatchInfoBase> buildL2BroadcastMatches() {
402         List<MatchInfoBase> matches = new ArrayList<>();
403         matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
404         return matches;
405     }
406
407     /**
408      * Builds the service id.
409      *
410      * @param interfaceName the interface name
411      * @param serviceIndex the service index
412      * @param serviceMode the service mode
413      * @return the instance identifier
414      */
415     public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
416             Class<? extends ServiceModeBase> serviceMode) {
417         return InstanceIdentifier.builder(ServiceBindings.class)
418                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
419                 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
420     }
421
422     /**
423      * Gets the bound services.
424      *
425      * @param serviceName the service name
426      * @param servicePriority the service priority
427      * @param flowPriority the flow priority
428      * @param cookie the cookie
429      * @param instructions the instructions
430      * @return the bound services
431      */
432     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
433             BigInteger cookie, List<Instruction> instructions) {
434         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
435                 .setInstruction(instructions);
436         return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
437                 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
438                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
439     }
440
441     public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
442         if (updatedAclList == null) {
443             return Collections.emptyList();
444         }
445         List<Uuid> newAclList = new ArrayList<>(updatedAclList);
446         if (currentAclList == null) {
447             return newAclList;
448         }
449         List<Uuid> origAclList = new ArrayList<>(currentAclList);
450         for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
451             Uuid updatedAclUuid = iterator.next();
452             for (Uuid currentAclUuid :origAclList) {
453                 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
454                     iterator.remove();
455                 }
456             }
457         }
458         return newAclList;
459     }
460
461     public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
462             List<AllowedAddressPairs> updatedAllowedAddressPairs,
463             List<AllowedAddressPairs> currentAllowedAddressPairs) {
464         if (updatedAllowedAddressPairs == null) {
465             return null;
466         }
467         List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
468         if (currentAllowedAddressPairs == null) {
469             return newAllowedAddressPairs;
470         }
471         List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
472         for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
473             AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
474             for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
475                 if (updatedAllowedAddressPair.getKey().equals(currentAllowedAddressPair.getKey())) {
476                     iterator.remove();
477                     break;
478                 }
479             }
480         }
481         return newAllowedAddressPairs;
482     }
483
484     public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
485         if (port == null) {
486             LOG.error("Port is Null");
487             return null;
488         }
489         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
490         if (aclInPort == null) {
491             LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
492             return null;
493         }
494         return aclInPort.getAllowedAddressPairs();
495     }
496
497     public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
498             .interfaces.rev140508.interfaces.state.Interface interfaceState) {
499         BigInteger dpId = null;
500         List<String> ofportIds = interfaceState.getLowerLayerIf();
501         if (ofportIds != null && !ofportIds.isEmpty()) {
502             NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
503             dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
504         }
505         return dpId;
506     }
507
508     public static List<String> getIpBroadcastAddresses(List<IpPrefixOrAddress> cidrs) {
509         List<String> ipBroadcastAddresses = new ArrayList<>();
510         for (IpPrefixOrAddress cidr : cidrs) {
511             IpPrefix cidrIpPrefix = cidr.getIpPrefix();
512             if (cidrIpPrefix != null) {
513                 Ipv4Prefix cidrIpv4Prefix = cidrIpPrefix.getIpv4Prefix();
514                 if (cidrIpv4Prefix != null) {
515                     ipBroadcastAddresses.add(getBroadcastAddressFromCidr(cidrIpv4Prefix.getValue()));
516                 }
517             }
518         }
519         return ipBroadcastAddresses;
520     }
521
522     public static String getBroadcastAddressFromCidr(String cidr) {
523         String[] ipaddressValues = cidr.split("/");
524         int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
525         int cidrPart = Integer.parseInt(ipaddressValues[1]);
526         int netmask = 0;
527         for (int j = 0; j < cidrPart; ++j) {
528             netmask |= 1 << 31 - j;
529         }
530         int network = address & netmask;
531         int broadcast = network | ~netmask;
532         return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
533     }
534
535     /**
536      * Builds the ip matches.
537      *
538      * @param ipPrefixOrAddress the ip prefix or address
539      * @param matchCriteria the source_ip or destination_ip used for the match
540      * @return the list
541      */
542     public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
543                                                      MatchCriteria matchCriteria) {
544         List<MatchInfoBase> flowMatches = new ArrayList<>();
545         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
546         if (ipPrefix != null) {
547             Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
548             if (ipv4Prefix != null) {
549                 flowMatches.add(MatchEthernetType.IPV4);
550                 if (!ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
551                     flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(ipv4Prefix)
552                             : new MatchIpv4Destination(ipv4Prefix));
553                 }
554             } else {
555                 flowMatches.add(MatchEthernetType.IPV6);
556                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
557                         ipPrefix.getIpv6Prefix()) : new MatchIpv6Destination(ipPrefix.getIpv6Prefix()));
558             }
559         } else {
560             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
561             if (ipAddress.getIpv4Address() != null) {
562                 flowMatches.add(MatchEthernetType.IPV4);
563                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(
564                         ipAddress.getIpv4Address().getValue(), "32") : new MatchIpv4Destination(
565                         ipAddress.getIpv4Address().getValue(), "32"));
566             } else {
567                 flowMatches.add(MatchEthernetType.IPV6);
568                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
569                         ipAddress.getIpv6Address().getValue() + "/128") : new MatchIpv6Destination(
570                         ipAddress.getIpv6Address().getValue() + "/128"));
571             }
572         }
573         return flowMatches;
574     }
575
576     /**
577      * Builds the arp ip matches.
578      * @param ipPrefixOrAddress the ip prefix or address
579      * @return the MatchInfoBase list
580      */
581     public static List<MatchInfoBase> buildArpIpMatches(IpPrefixOrAddress ipPrefixOrAddress) {
582         List<MatchInfoBase> flowMatches = new ArrayList<>();
583         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
584         if (ipPrefix != null) {
585             Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
586             if (ipv4Prefix != null && !ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
587                 flowMatches.add(new MatchArpSpa(ipv4Prefix));
588             }
589         } else {
590             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
591             if (ipAddress != null && ipAddress.getIpv4Address() != null) {
592                 flowMatches.add(new MatchArpSpa(ipAddress.getIpv4Address().getValue(), "32"));
593             }
594         }
595         return flowMatches;
596     }
597
598     public static MatchInfoBase buildRemoteAclTagMetadataMatch(Integer remoteAclTag) {
599         return new MatchMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
600                 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
601     }
602
603     public static BigInteger getRemoteAclTagMetadata(BigInteger remoteAclTag) {
604         return remoteAclTag.shiftLeft(4);
605     }
606
607     /**
608      * Does IPv4 address exists in the list of allowed address pair.
609      *
610      * @param aaps the allowed address pairs
611      * @return true, if successful
612      */
613     public static boolean doesIpv4AddressExists(List<AllowedAddressPairs> aaps) {
614         if (aaps == null) {
615             return false;
616         }
617         for (AllowedAddressPairs aap : aaps) {
618             IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
619             IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
620             if (ipPrefix != null) {
621                 if (ipPrefix.getIpv4Prefix() != null) {
622                     return true;
623                 }
624             } else {
625                 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
626                 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
627                     return true;
628                 }
629             }
630         }
631         return false;
632     }
633
634     /**
635      * Does IPv6 address exists in the list of allowed address pair.
636      *
637      * @param aaps the allowed address pairs
638      * @return true, if successful
639      */
640     public static boolean doesIpv6AddressExists(List<AllowedAddressPairs> aaps) {
641         if (aaps == null) {
642             return false;
643         }
644         for (AllowedAddressPairs aap : aaps) {
645             IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
646             IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
647             if (ipPrefix != null) {
648                 if (ipPrefix.getIpv6Prefix() != null) {
649                     return true;
650                 }
651             } else {
652                 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
653                 if (ipAddress != null && ipAddress.getIpv6Address() != null) {
654                     return true;
655                 }
656             }
657         }
658         return false;
659     }
660
661     /**
662      * Gets the lport tag match.
663      * Ingress match is based on metadata and egress match is based on masked reg6
664      *
665      * @param lportTag the lport tag
666      * @param serviceMode ingress or egress service mode
667      * @return the lport tag match
668      */
669     public static MatchInfoBase buildLPortTagMatch(int lportTag, Class<? extends ServiceModeBase> serviceMode) {
670         if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
671             return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
672                     MetaDataUtil.getLportTagMaskForReg6());
673         } else {
674             return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG);
675         }
676     }
677
678     public static List<MatchInfoBase> buildMatchesForLPortTagAndRemoteAclTag(Integer lportTag, Integer remoteAclTag,
679             Class<? extends ServiceModeBase> serviceMode) {
680         List<MatchInfoBase> matches = new ArrayList<>();
681         if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
682             matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
683             matches.add(AclServiceUtils.buildRemoteAclTagMetadataMatch(remoteAclTag));
684         } else {
685             // In case of ingress service mode, only metadata is used for
686             // matching both lportTag and aclTag. Hence performing "or"
687             // operation on both lportTag and aclTag metadata.
688             BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
689                     .or(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)));
690             BigInteger metaDataMask =
691                     MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
692             matches.add(new MatchMetadata(metaData, metaDataMask));
693         }
694         return matches;
695     }
696
697     public static Collection<? extends MatchInfoBase> buildMatchesForLPortTagAndConntrackClassifierType(int lportTag,
698             AclConntrackClassifierType conntrackClassifierType, Class<? extends ServiceModeBase> serviceMode) {
699         List<MatchInfoBase> matches = new ArrayList<>();
700         if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
701             matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
702             matches.add(AclServiceUtils.buildAclConntrackClassifierTypeMatch(conntrackClassifierType));
703         } else {
704             // In case of ingress service mode, only metadata is used for
705             // matching both lportTag and conntrackClassifierType. Hence performing "or"
706             // operation on both lportTag and conntrackClassifierType metadata.
707             BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
708                     .or(MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()));
709             BigInteger metaDataMask =
710                     MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
711             matches.add(new MatchMetadata(metaData, metaDataMask));
712         }
713         return matches;
714     }
715
716     public static InstructionWriteMetadata getWriteMetadataForAclClassifierType(
717             AclConntrackClassifierType conntrackClassifierType) {
718         return new InstructionWriteMetadata(
719                 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()),
720                 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
721     }
722
723     public static InstructionWriteMetadata getWriteMetadataForRemoteAclTag(Integer remoteAclTag) {
724         return new InstructionWriteMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
725                 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
726     }
727
728     public static MatchInfoBase buildAclConntrackClassifierTypeMatch(
729             AclConntrackClassifierType conntrackSupportedType) {
730         return new MatchMetadata(
731                 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackSupportedType.getValue()),
732                 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
733     }
734
735     public AclserviceConfig getConfig() {
736         return config;
737     }
738
739     public static boolean isIPv4Address(AllowedAddressPairs aap) {
740         IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
741         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
742         if (ipPrefix != null) {
743             if (ipPrefix.getIpv4Prefix() != null) {
744                 return true;
745             }
746         } else {
747             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
748             if (ipAddress != null && ipAddress.getIpv4Address() != null) {
749                 return true;
750             }
751         }
752         return false;
753     }
754
755     public static Map<String, List<MatchInfoBase>> getFlowForAllowedAddresses(
756             List<AllowedAddressPairs> syncAllowedAddresses, Map<String, List<MatchInfoBase>> flowMatchesMap,
757             boolean isSourceIpMacMatch) {
758         if (flowMatchesMap == null) {
759             return null;
760         }
761         Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
762         MatchInfoBase ipv4Match = MatchEthernetType.IPV4;
763         MatchInfoBase ipv6Match = MatchEthernetType.IPV6;
764         for (Entry<String, List<MatchInfoBase>> entry : flowMatchesMap.entrySet()) {
765             String flowName = entry.getKey();
766             List<MatchInfoBase> flows = entry.getValue();
767             // iterate over allow address pair and update match type
768             for (AllowedAddressPairs aap : syncAllowedAddresses) {
769                 List<MatchInfoBase> matchInfoBaseList;
770                 String flowId;
771                 if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) {
772                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
773                     flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap);
774                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
775                 } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) {
776                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
777                     flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap);
778                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
779                 }
780             }
781         }
782         return updatedFlowMatchesMap;
783     }
784
785     public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) {
786         IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
787         if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null
788                 && ipPrefix.getIpv4Prefix().getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
789             return false;
790         }
791         return true;
792     }
793
794     protected static boolean isNotIpv6AllNetwork(AllowedAddressPairs aap) {
795         IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
796         if (ipPrefix != null && ipPrefix.getIpv6Prefix() != null
797                 && ipPrefix.getIpv6Prefix().getValue().equals(AclConstants.IPV6_ALL_NETWORK)) {
798             return false;
799         }
800         return true;
801     }
802
803     public static boolean isNotIpAllNetwork(AllowedAddressPairs aap) {
804         return isNotIpv4AllNetwork(aap) && isNotIpv6AllNetwork(aap);
805     }
806
807     private static String getAapFlowId(AllowedAddressPairs aap) {
808         return aap.getMacAddress().getValue() + "_" + String.valueOf(aap.getIpAddress().getValue());
809     }
810
811     public static Long getElanIdFromInterface(String elanInterfaceName,DataBroker broker) {
812         ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
813         if (null != elanInterface) {
814             ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
815             return elanInfo.getElanTag();
816         }
817         return null;
818     }
819
820     public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
821         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
822         return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
823     }
824
825     public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
826         return InstanceIdentifier.builder(ElanInterfaces.class)
827                 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
828     }
829
830     // elan-instances config container
831     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
832         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
833         return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
834     }
835
836     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
837         return InstanceIdentifier.builder(ElanInstances.class)
838                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
839     }
840
841     public static List<IpPrefixOrAddress> getSubnetIpPrefixes(DataBroker broker, String portId) {
842         InstanceIdentifier<PortSubnetIpPrefixes> id = InstanceIdentifier.builder(PortsSubnetIpPrefixes.class)
843                 .child(PortSubnetIpPrefixes.class, new PortSubnetIpPrefixesKey(portId)).build();
844         Optional<PortSubnetIpPrefixes> portSubnetIpPrefixes = read(broker, LogicalDatastoreType.OPERATIONAL, id);
845         if (portSubnetIpPrefixes.isPresent()) {
846             return portSubnetIpPrefixes.get().getSubnetIpPrefixes();
847         }
848         return null;
849     }
850
851     public static void deleteSubnetIpPrefixes(DataBroker broker, String portId) {
852         InstanceIdentifier<PortSubnetIpPrefixes> id = InstanceIdentifier.builder(PortsSubnetIpPrefixes.class)
853                     .child(PortSubnetIpPrefixes.class, new PortSubnetIpPrefixesKey(portId)).build();
854         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
855     }
856
857     private static List<MatchInfoBase> updateAAPMatches(boolean isSourceIpMacMatch, List<MatchInfoBase> flows,
858                                                         AllowedAddressPairs aap) {
859         List<MatchInfoBase> matchInfoBaseList;
860         if (isSourceIpMacMatch) {
861             matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_SOURCE);
862         } else {
863             matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_DESTINATION);
864         }
865         matchInfoBaseList.addAll(flows);
866         return matchInfoBaseList;
867     }
868
869     public static MatchInfoBase getMatchInfoByType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
870         for (MatchInfoBase mib : flows) {
871             if (type.isAssignableFrom(mib.getClass())) {
872                 return mib;
873             }
874         }
875         return null;
876     }
877
878     public static boolean containsMatchFieldType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
879         return getMatchInfoByType(flows, type) != null;
880     }
881
882     public static boolean containsTcpMatchField(List<MatchInfoBase> flows) {
883         return flows.contains(MatchIpProtocol.TCP);
884     }
885
886     public static boolean containsUdpMatchField(List<MatchInfoBase> flows) {
887         return flows.contains(MatchIpProtocol.UDP);
888     }
889
890     public static Integer allocateId(IdManagerService idManager, String poolName, String idKey, Integer defaultId) {
891         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
892         try {
893             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
894             RpcResult<AllocateIdOutput> rpcResult = result.get();
895             if (rpcResult.isSuccessful()) {
896                 Integer allocatedId = rpcResult.getResult().getIdValue().intValue();
897                 LOG.debug("Allocated ACL ID: {} with key: {} into pool: {}", allocatedId, idKey, poolName);
898                 return allocatedId;
899             } else {
900                 LOG.error("RPC Call to Get Unique Id for key {} from pool {} returned with Errors {}",
901                         idKey, poolName, rpcResult.getErrors());
902             }
903         } catch (InterruptedException | ExecutionException e) {
904             LOG.error("Exception when getting Unique Id for key {} from pool {} ", idKey, poolName, e);
905         }
906         return defaultId;
907     }
908
909     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
910         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
911         try {
912             Future<RpcResult<Void>> result = idManager.releaseId(idInput);
913             RpcResult<Void> rpcResult = result.get();
914             if (!rpcResult.isSuccessful()) {
915                 LOG.error("RPC Call to release Id with Key {} from pool {} returned with Errors {}",
916                         idKey, poolName, rpcResult.getErrors());
917             } else {
918                 LOG.debug("Released ACL ID with key: {} from pool: {}", idKey, poolName);
919             }
920         } catch (InterruptedException | ExecutionException e) {
921             LOG.error("Exception when releasing Id for key {} from pool {} ", idKey, poolName, e);
922         }
923     }
924
925     /**
926      * Gets the ACL tag from cache. If not found in cache, tries to allocate and
927      * return the value.
928      *
929      * @param aclId the acl id
930      * @return the acl tag
931      */
932     public Integer getAclTag(final Uuid aclId) {
933         String aclName = aclId.getValue();
934         Integer aclTag = this.aclDataUtil.getAclTag(aclName);
935         if (aclTag == null) {
936             LOG.debug("ACL tag not found in cache for ACL={}, trying to allocate again.", aclName);
937             aclTag = allocateAclTag(aclName);
938             if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
939                 this.aclDataUtil.addAclTag(aclName, aclTag);
940             }
941         }
942         return aclTag;
943     }
944
945     /**
946      * Allocate ACL tag.
947      *
948      * @param aclName the ACL name
949      * @return the integer
950      */
951     public Integer allocateAclTag(String aclName) {
952         Integer aclTag = AclServiceUtils.allocateId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName,
953                 AclConstants.INVALID_ACL_TAG);
954         return aclTag;
955     }
956
957     /**
958      * Release ACL tag.
959      *
960      * @param aclName the ACL name
961      */
962     public void releaseAclTag(String aclName) {
963         AclServiceUtils.releaseId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName);
964     }
965
966     /**
967      * Indicates whether the interface has port security enabled.
968      *
969      * @param aclInterface the interface.
970      * @return true if port is security enabled.
971      */
972     public static boolean isOfInterest(AclInterface aclInterface) {
973         return aclInterface != null && aclInterface.isPortSecurityEnabled();
974     }
975
976     /**
977      * Creates the id pool for ACL tag.
978      *
979      * @param poolName the pool name
980      */
981     private void createIdPoolForAclTag(String poolName) {
982         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
983                 .setPoolName(poolName).setLow(AclConstants.ACL_TAG_POOL_START)
984                 .setHigh(AclConstants.ACL_TAG_POOL_END).build();
985         try {
986             Future<RpcResult<Void>> result = this.idManager.createIdPool(createPool);
987             if (result != null && result.get().isSuccessful()) {
988                 LOG.debug("Created IdPool for {}", poolName);
989             }
990         } catch (InterruptedException | ExecutionException e) {
991             LOG.error("Failed to create ID pool [{}] for remote ACL ids", poolName, e);
992             throw new RuntimeException("Failed to create ID pool [{}] for remote ACL ids", e);
993         }
994     }
995
996     /**
997      * Delete id pool.
998      *
999      * @param poolName the pool name
1000      */
1001     public void deleteIdPool(String poolName) {
1002         DeleteIdPoolInput deletePool = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
1003         try {
1004             Future<RpcResult<Void>> result = this.idManager.deleteIdPool(deletePool);
1005             if (result != null && result.get().isSuccessful()) {
1006                 LOG.debug("Deleted IdPool for {}", poolName);
1007             }
1008         } catch (InterruptedException | ExecutionException e) {
1009             LOG.error("Failed to delete ID pool [{}]", poolName, e);
1010             throw new RuntimeException("Failed to delete ID pool [" + poolName + "]", e);
1011         }
1012     }
1013
1014     /**
1015      * Creates remote the acl id pools.
1016      */
1017     public void createRemoteAclIdPool() {
1018         createIdPoolForAclTag(AclConstants.ACL_TAG_POOL_NAME);
1019     }
1020
1021     /**
1022      * Delete remote the acl id pools.
1023      */
1024     public void deleteRemoteAclIdPool() {
1025         deleteIdPool(AclConstants.ACL_TAG_POOL_NAME);
1026     }
1027
1028     public static List<? extends MatchInfoBase> buildIpAndSrcServiceMatch(Integer aclTag, AllowedAddressPairs aap,
1029             DataBroker dataBroker) {
1030         List<MatchInfoBase> flowMatches = new ArrayList<>();
1031         flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
1032         if (aap.getIpAddress().getIpAddress() != null) {
1033             if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
1034                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1035                 flowMatches.add(ipv4EthMatch);
1036                 MatchIpv4Source srcMatch = new MatchIpv4Source(
1037                         new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
1038                 flowMatches.add(srcMatch);
1039             } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
1040                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1041                 flowMatches.add(ipv6EthMatch);
1042                 MatchIpv6Source srcMatch = new MatchIpv6Source(
1043                         new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
1044                 flowMatches.add(srcMatch);
1045             }
1046         } else if (aap.getIpAddress().getIpPrefix() != null) {
1047             if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
1048                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1049                 flowMatches.add(ipv4EthMatch);
1050                 MatchIpv4Source srcMatch = new MatchIpv4Source(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
1051                 flowMatches.add(srcMatch);
1052             } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
1053                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1054                 flowMatches.add(ipv6EthMatch);
1055                 MatchIpv6Source srcMatch = new MatchIpv6Source(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
1056                 flowMatches.add(srcMatch);
1057             }
1058         }
1059         return flowMatches;
1060     }
1061
1062     public static List<? extends MatchInfoBase> buildIpAndDstServiceMatch(Integer aclTag, AllowedAddressPairs aap,
1063             DataBroker dataBroker) {
1064         List<MatchInfoBase> flowMatches = new ArrayList<>();
1065         flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
1066
1067         if (aap.getIpAddress().getIpAddress() != null) {
1068             if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
1069                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1070                 flowMatches.add(ipv4EthMatch);
1071                 MatchIpv4Destination dstMatch = new MatchIpv4Destination(
1072                         new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
1073                 flowMatches.add(dstMatch);
1074             } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
1075                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1076                 flowMatches.add(ipv6EthMatch);
1077                 MatchIpv6Destination dstMatch = new MatchIpv6Destination(
1078                         new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
1079                 flowMatches.add(dstMatch);
1080             }
1081         } else if (aap.getIpAddress().getIpPrefix() != null) {
1082             if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
1083                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1084                 flowMatches.add(ipv4EthMatch);
1085                 MatchIpv4Destination dstMatch =
1086                         new MatchIpv4Destination(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
1087                 flowMatches.add(dstMatch);
1088             } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
1089                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1090                 flowMatches.add(ipv6EthMatch);
1091                 MatchIpv6Destination dstMatch =
1092                         new MatchIpv6Destination(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
1093                 flowMatches.add(dstMatch);
1094             }
1095         }
1096         return flowMatches;
1097     }
1098
1099     public static boolean isOfAclInterest(Acl acl) {
1100         if (acl.getAccessListEntries() != null) {
1101             List<Ace> aceList = acl.getAccessListEntries().getAce();
1102             if (aceList != null && !aceList.isEmpty()) {
1103                 return aceList.get(0).getAugmentation(SecurityRuleAttr.class) != null;
1104             }
1105         }
1106         return false;
1107     }
1108
1109     public static void addLportTagMetadataMatch(int lportTag, List<MatchInfoBase> flowMatches,
1110             Class<? extends ServiceModeBase> serviceMode) {
1111         MatchInfoBase lportMatch = buildLPortTagMatch(lportTag, serviceMode);
1112         InterfaceServiceUtil.mergeMetadataMatchsOrAdd(flowMatches, lportMatch);
1113     }
1114
1115     /**
1116      * Returns ACL specific key for synchronization.
1117      *
1118      * @param key the generic key
1119      * @return ACL key that can be used with synchronization
1120      */
1121     public static String getAclKeyForSynchronization(String key) {
1122         return key + AclConstants.ACL_SYNC_KEY_EXT;
1123     }
1124
1125     /**
1126      * Builds the ip protocol matches.
1127      *
1128      * @param etherType the ether type
1129      * @param protocol the protocol
1130      * @return the list of matches.
1131      */
1132     public static List<MatchInfoBase> buildIpProtocolMatches(MatchEthernetType etherType, IPProtocols protocol) {
1133         return Lists.newArrayList(etherType, new MatchIpProtocol(protocol.shortValue()));
1134     }
1135
1136     /**
1137      * Does ACE have remote group id.
1138      *
1139      * @param aceAttr the ace attr
1140      * @return true, if successful
1141      */
1142     public static boolean doesAceHaveRemoteGroupId(final SecurityRuleAttr aceAttr) {
1143         return aceAttr != null && aceAttr.getRemoteGroupId() != null;
1144     }
1145
1146     public SortedSet<Integer> getRemoteAclTags(List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
1147         SortedSet<Integer> remoteAclTags = new TreeSet<>();
1148         Set<Uuid> remoteAclIds = getRemoteAclIdsByDirection(aclIds, direction);
1149         for (Uuid remoteAclId : remoteAclIds) {
1150             Integer remoteAclTag = getAclTag(remoteAclId);
1151             if (remoteAclTag != null && remoteAclTag != AclConstants.INVALID_ACL_TAG) {
1152                 remoteAclTags.add(remoteAclTag);
1153             }
1154         }
1155         return remoteAclTags;
1156     }
1157
1158     public Set<Uuid> getRemoteAclIdsByDirection(List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
1159         Set<Uuid> remoteAclIds = new HashSet<>();
1160         if (aclIds == null || aclIds.isEmpty()) {
1161             return remoteAclIds;
1162         }
1163
1164         for (Uuid aclId : aclIds) {
1165             Acl acl = this.aclDataUtil.getAcl(aclId.getValue());
1166             if (null == acl) {
1167                 LOG.warn("ACL {} not found in cache.", aclId.getValue());
1168                 continue;
1169             }
1170             remoteAclIds.addAll(getRemoteAclIdsByDirection(acl, direction));
1171         }
1172         return remoteAclIds;
1173     }
1174
1175     public static Set<Uuid> getRemoteAclIdsByDirection(Acl acl, Class<? extends DirectionBase> direction) {
1176         Set<Uuid> remoteAclIds = new HashSet<>();
1177         AccessListEntries accessListEntries = acl.getAccessListEntries();
1178         if (accessListEntries != null && accessListEntries.getAce() != null) {
1179             for (Ace ace : accessListEntries.getAce()) {
1180                 SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace);
1181                 if (aceAttr.getDirection().equals(direction) && doesAceHaveRemoteGroupId(aceAttr)) {
1182                     remoteAclIds.add(aceAttr.getRemoteGroupId());
1183                 }
1184             }
1185         }
1186         return remoteAclIds;
1187     }
1188
1189     /**
1190      * Skip delete in case of overlapping IP.
1191      *
1192      * <p>
1193      * When there are multiple ports (e.g., p1, p2, p3) having same AAP (e.g.,
1194      * 224.0.0.5) configured which are part of single SG, there would be single
1195      * flow in remote ACL table. When one of these ports (say p1) is deleted,
1196      * the single flow which is configured in remote ACL table shouldn't be
1197      * deleted. It should be deleted only when there are no more references to
1198      * it.
1199      *
1200      * @param portId the port id
1201      * @param remoteAclId the remote Acl Id
1202      * @param ipPrefix the ip prefix
1203      * @param addOrRemove the add or remove
1204      * @return true, if successful
1205      */
1206     public boolean skipDeleteInCaseOfOverlappingIP(String portId, Uuid remoteAclId, IpPrefixOrAddress ipPrefix,
1207             int addOrRemove) {
1208         boolean skipDelete = false;
1209         if (addOrRemove != NwConstants.DEL_FLOW) {
1210             return skipDelete;
1211         }
1212         AclIpPrefixes aclIpPrefixes = getAclIpPrefixesFromOperDs(remoteAclId.getValue(), ipPrefix);
1213         if (aclIpPrefixes != null && aclIpPrefixes.getPortIds() != null) {
1214             List<String> ignorePorts = Lists.newArrayList(portId);
1215             List<PortIds> portIds = new ArrayList<>(aclIpPrefixes.getPortIds());
1216             // Checking if there are any other ports excluding ignorePorts
1217             long noOfRemotePorts =
1218                     portIds.stream().map(x -> x.getPortId()).filter(y -> !ignorePorts.contains(y)).count();
1219             if (noOfRemotePorts > 0) {
1220                 skipDelete = true;
1221             }
1222         }
1223         return skipDelete;
1224     }
1225
1226     public static void deleteAclPortsLookupEntry(String aclName, DataBroker broker)
1227             throws TransactionCommitFailedException {
1228         SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, aclPortsByIpPath(aclName));
1229     }
1230
1231     public static InstanceIdentifier<AclPortsByIp> aclPortsByIpPath(String aclName) {
1232         return InstanceIdentifier.builder(AclPortsLookup.class)
1233                 .child(AclPortsByIp.class, new AclPortsByIpKey(aclName)).build();
1234     }
1235
1236     public static InstanceIdentifier<AclIpPrefixes> getAclIpPrefixesPath(String aclName, IpPrefixOrAddress ipPrefix) {
1237         return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(aclName))
1238                 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).build();
1239     }
1240
1241     public static InstanceIdentifier<PortIds> getPortIdsPathInAclPortsLookup(String ruleName,
1242             IpPrefixOrAddress ipPrefix, String portId) {
1243         return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(ruleName))
1244                 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).child(PortIds.class, new PortIdsKey(portId))
1245                 .build();
1246     }
1247
1248     public List<ListenableFuture<Void>> addAclPortsLookupForInterfaceUpdate(AclInterface portBefore,
1249             AclInterface portAfter) {
1250         List<ListenableFuture<Void>> futures = new ArrayList<>();
1251         LOG.debug("Processing interface additions for port {}", portAfter.getInterfaceId());
1252         List<AllowedAddressPairs> addedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1253                 portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
1254         if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
1255             futures.addAll(addAclPortsLookup(portAfter, portAfter.getSecurityGroups(), addedAllowedAddressPairs));
1256         }
1257
1258         List<Uuid> addedAcls = getUpdatedAclList(portAfter.getSecurityGroups(), portBefore.getSecurityGroups());
1259         if (addedAcls != null && !addedAcls.isEmpty()) {
1260             futures.addAll(addAclPortsLookup(portAfter, addedAcls, portAfter.getAllowedAddressPairs()));
1261         }
1262         return futures;
1263     }
1264
1265     public List<ListenableFuture<Void>> deleteAclPortsLookupForInterfaceUpdate(AclInterface portBefore,
1266             AclInterface portAfter) {
1267         List<ListenableFuture<Void>> futures = new ArrayList<>();
1268         LOG.debug("Processing interface removals for port {}", portAfter.getInterfaceId());
1269         List<AllowedAddressPairs> deletedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1270                 portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
1271         if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
1272             futures.addAll(deleteAclPortsLookup(portAfter, portAfter.getSecurityGroups(), deletedAllowedAddressPairs));
1273         }
1274
1275         List<Uuid> deletedAcls = getUpdatedAclList(portBefore.getSecurityGroups(), portAfter.getSecurityGroups());
1276         if (deletedAcls != null && !deletedAcls.isEmpty()) {
1277             futures.addAll(deleteAclPortsLookup(portAfter, deletedAcls, portAfter.getAllowedAddressPairs()));
1278         }
1279         return futures;
1280     }
1281
1282     public List<ListenableFuture<Void>> addAclPortsLookup(AclInterface port, List<Uuid> aclList,
1283             List<AllowedAddressPairs> allowedAddresses) {
1284         String portId = port.getInterfaceId();
1285         LOG.trace("Adding AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1286
1287         if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1288             LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1289                     allowedAddresses);
1290             return Collections.emptyList();
1291         }
1292         List<ListenableFuture<Void>> futures = new ArrayList<>();
1293         for (Uuid aclId : aclList) {
1294             String aclName = aclId.getValue();
1295             synchronized (aclName.intern()) {
1296                 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1297                     for (AllowedAddressPairs aap : allowedAddresses) {
1298                         PortIds portIdObj =
1299                                 new PortIdsBuilder().setKey(new PortIdsKey(portId)).setPortId(portId).build();
1300                         InstanceIdentifier<PortIds> path =
1301                                 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1302                         tx.put(LogicalDatastoreType.OPERATIONAL, path, portIdObj,
1303                                 WriteTransaction.CREATE_MISSING_PARENTS);
1304                     }
1305                 }));
1306             }
1307         }
1308         return futures;
1309     }
1310
1311     public List<ListenableFuture<Void>> deleteAclPortsLookup(AclInterface port, List<Uuid> aclList,
1312             List<AllowedAddressPairs> allowedAddresses) {
1313         String portId = port.getInterfaceId();
1314         LOG.trace("Deleting AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1315
1316         if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1317             LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1318                     allowedAddresses);
1319             return Collections.emptyList();
1320         }
1321         List<ListenableFuture<Void>> futures = new ArrayList<>();
1322         for (Uuid aclId : aclList) {
1323             String aclName = aclId.getValue();
1324             synchronized (aclName.intern()) {
1325                 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1326                     for (AllowedAddressPairs aap : allowedAddresses) {
1327                         InstanceIdentifier<PortIds> path =
1328                                 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1329                         tx.delete(LogicalDatastoreType.OPERATIONAL, path);
1330                     }
1331
1332                     cleanUpStaleEntriesInAclPortsLookup(aclName, tx);
1333                 }));
1334             }
1335         }
1336         return futures;
1337     }
1338
1339     private void cleanUpStaleEntriesInAclPortsLookup(String aclName, WriteTransaction tx) {
1340         AclPortsByIp aclPortsByIp = getAclPortsByIpFromOperDs(aclName);
1341         if (aclPortsByIp == null) {
1342             return;
1343         }
1344         boolean deleteEntireAcl;
1345         List<AclIpPrefixes> ipPrefixes = aclPortsByIp.getAclIpPrefixes();
1346         if (ipPrefixes == null || ipPrefixes.isEmpty()) {
1347             deleteEntireAcl = true;
1348         } else {
1349             boolean deleteMap = true;
1350             for (AclIpPrefixes ipPrefix : ipPrefixes) {
1351                 if (ipPrefix.getPortIds() != null && !ipPrefix.getPortIds().isEmpty()) {
1352                     deleteMap = false;
1353                     break;
1354                 }
1355             }
1356             deleteEntireAcl = deleteMap;
1357         }
1358         if (deleteEntireAcl) {
1359             tx.delete(LogicalDatastoreType.OPERATIONAL, AclServiceUtils.aclPortsByIpPath(aclName));
1360         } else {
1361             for (AclIpPrefixes ipPrefix : ipPrefixes) {
1362                 if (ipPrefix.getPortIds() == null || ipPrefix.getPortIds().isEmpty()) {
1363                     InstanceIdentifier<AclIpPrefixes> delPath =
1364                             AclServiceUtils.getAclIpPrefixesPath(aclName, ipPrefix.getIpPrefix());
1365                     tx.delete(LogicalDatastoreType.OPERATIONAL, delPath);
1366                 }
1367             }
1368         }
1369     }
1370
1371     @Nullable
1372     private AclPortsByIp getAclPortsByIpFromOperDs(String aclName) {
1373         InstanceIdentifier<AclPortsByIp> path = aclPortsByIpPath(aclName);
1374         try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
1375             return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
1376         } catch (ReadFailedException e) {
1377             LOG.error("Failed to read ACL ports {}", path, e);
1378             return null;
1379         }
1380     }
1381
1382     @Nullable
1383     private AclIpPrefixes getAclIpPrefixesFromOperDs(String aclName, IpPrefixOrAddress ipPrefix) {
1384         InstanceIdentifier<AclIpPrefixes> path = getAclIpPrefixesPath(aclName, ipPrefix);
1385         try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
1386             return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
1387         } catch (ReadFailedException e) {
1388             LOG.error("Failed to read ACL IP prefixes {}", path, e);
1389             return null;
1390         }
1391     }
1392
1393     /**
1394      * Gets the ace flow priority.
1395      *
1396      * @param aclName the acl name
1397      * @return the ace flow priority
1398      */
1399     public Integer getAceFlowPriority(String aclName) {
1400         Integer priority = AclConstants.ACE_DEFAULT_PRIORITY;
1401         Integer aclTag = getAclTag(new Uuid(aclName));
1402         if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
1403             // To handle overlapping rules, aclTag is added to priority
1404             priority += aclTag;
1405         } else {
1406             LOG.warn("aclTag=[] is null or invalid for aclName={}", aclTag, aclName);
1407         }
1408         return priority;
1409     }
1410
1411     /**
1412      * Returns the hard timeout based on the protocol when a ACL rule removed from the instance.
1413      * It will returns the timeout configured in the {@link AclserviceConfig} class.
1414      *
1415      * @param ace the ace
1416      * @param aclServiceUtils acl service utils
1417      * @return the hard time out
1418      */
1419     public static Integer getHardTimoutForApplyStatefulChangeOnExistingTraffic(Ace ace,
1420             AclServiceUtils aclServiceUtils) {
1421         int hardTimeout = AclConstants.SECURITY_GROUP_ICMP_IDLE_TIME_OUT;
1422         Matches matches = ace.getMatches();
1423         AceIp acl = (AceIp) matches.getAceType();
1424         Short protocol = acl.getProtocol();
1425         if (protocol == null) {
1426             return hardTimeout;
1427         } else if (protocol == NwConstants.IP_PROT_TCP) {
1428             hardTimeout = aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout();
1429         } else if (protocol == NwConstants.IP_PROT_UDP) {
1430             hardTimeout = aclServiceUtils.getConfig().getSecurityGroupUdpIdleTimeout();
1431         }
1432         return hardTimeout;
1433     }
1434
1435     /**
1436      * This method creates and returns the ct_mark instruction when a ACL rule removed from the
1437      * instance. This instruction will reset the ct_mark value and stops the existing traffics.
1438      *
1439      * @param filterTable the filterTable
1440      * @param elanId the Elan id
1441      * @return list of instruction
1442      */
1443     public static List<InstructionInfo> createCtMarkInstructionForNewState(Short filterTable, Long elanId) {
1444
1445         List<InstructionInfo> instructions = new ArrayList<>();
1446         List<ActionInfo> actionsInfos = new ArrayList<>();
1447         List<NxCtAction> ctActionsList = new ArrayList<>();
1448         NxCtAction nxCtMarkClearAction = new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_NEW_STATE);
1449         ctActionsList.add(nxCtMarkClearAction);
1450
1451         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(2, 1, 0, elanId.intValue(),
1452             (short) 255, ctActionsList);
1453         actionsInfos.add(actionNxConntrack);
1454         instructions.add(new InstructionApplyActions(actionsInfos));
1455         instructions.add(new InstructionGotoTable(filterTable));
1456
1457         return instructions;
1458     }
1459
1460 }