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