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