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