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