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