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