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