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