An atempt is made to reduce DS operations before fixed flows are
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / utils / AclServiceUtils.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.aclservice.utils;
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Lists;
13 import com.google.common.net.InetAddresses;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.net.InetAddress;
17 import java.net.UnknownHostException;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.Set;
28 import java.util.SortedSet;
29 import java.util.TreeSet;
30 import java.util.concurrent.ExecutionException;
31 import java.util.concurrent.Future;
32 import javax.annotation.Nullable;
33 import javax.inject.Inject;
34 import javax.inject.Singleton;
35
36 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
37 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
38 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
41 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
42 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
43 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
44 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
45 import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil;
46 import org.opendaylight.genius.mdsalutil.ActionInfo;
47 import org.opendaylight.genius.mdsalutil.InstructionInfo;
48 import org.opendaylight.genius.mdsalutil.MDSALUtil;
49 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
50 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
51 import org.opendaylight.genius.mdsalutil.NwConstants;
52 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
53 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
54 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
55 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
56 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
57 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
58 import org.opendaylight.genius.mdsalutil.matches.MatchArpSpa;
59 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
60 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
61 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
62 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
63 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
64 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
65 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Destination;
66 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source;
67 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
68 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
69 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
70 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
71 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
72 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
73 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
74 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
80 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
82 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;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
90 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
91 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
92 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolOutput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.srm.types.rev170711.NetvirtAcl;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclPortsLookup;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpVersionV6;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.PortSubnets;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIp;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIpKey;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixes;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixesKey;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIds;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsBuilder;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsKey;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.PortSubnet;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.PortSubnetKey;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.port.subnets.port.subnet.SubnetInfo;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
150 import org.opendaylight.yangtools.yang.binding.DataObject;
151 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
152 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
153 import org.opendaylight.yangtools.yang.common.RpcResult;
154 import org.slf4j.Logger;
155 import org.slf4j.LoggerFactory;
156
157 @Singleton
158 public final class AclServiceUtils {
159
160     private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
161     public static final AclserviceConfig.DefaultBehavior DEFAULT_DENY = AclserviceConfig.DefaultBehavior.Deny;
162     public static final AclserviceConfig.DefaultBehavior DEFAULT_ALLOW = AclserviceConfig.DefaultBehavior.Allow;
163
164     private final DataBroker dataBroker;
165     private final ManagedNewTransactionRunner txRunner;
166     private final AclDataUtil aclDataUtil;
167     private final AclserviceConfig config;
168     private final IdManagerService idManager;
169     private final JobCoordinator jobCoordinator;
170
171     @Inject
172     public AclServiceUtils(DataBroker dataBroker, AclDataUtil aclDataUtil, AclserviceConfig config,
173             IdManagerService idManager, JobCoordinator jobCoordinator) {
174         this.dataBroker = dataBroker;
175         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
176         this.aclDataUtil = aclDataUtil;
177         this.config = config;
178         this.idManager = idManager;
179         this.jobCoordinator = jobCoordinator;
180     }
181
182     /**
183      * Retrieves the Interface from the datastore.
184      * @param broker the data broker
185      * @param interfaceName the interface name
186      * @return the interface.
187      */
188     public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
189         .Interface> getInterface(DataBroker broker, String interfaceName) {
190         return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
191     }
192
193     /**
194      * Builds the interface identifier.
195      * @param interfaceName the interface name.
196      * @return the interface identifier.
197      */
198     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
199         .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
200         return InstanceIdentifier.builder(Interfaces.class)
201                 .child(
202                     org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
203                     .Interface.class, new InterfaceKey(interfaceName)).build();
204     }
205
206     /**
207      * Retrieves the object from the datastore.
208      * @param broker the data broker.
209      * @param datastoreType the data store type.
210      * @param path the wild card path.
211      * @param <T> type of DataObject
212      * @return the required object.
213      */
214     public static <T extends DataObject> Optional<T> read(
215             DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
216         try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
217             return tx.read(datastoreType, path).checkedGet();
218         } catch (ReadFailedException e) {
219             LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
220             return Optional.absent();
221         }
222     }
223
224     /**
225      * Retrieves the acl matching the key from the data store.
226      *
227      * @param broker the data broker
228      * @param aclKey the acl key
229      * @return the acl
230      */
231     public static Acl getAcl(DataBroker broker, String aclKey) {
232         return read(broker, LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey)).orNull();
233     }
234
235     /** Creates the Acl instance identifier.
236      *
237      * @param aclKey the acl key
238      * @return the instance identifier
239      */
240     public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
241         return InstanceIdentifier.builder(AccessLists.class).child(Acl.class, new AclKey(aclKey, Ipv4Acl.class))
242                 .build();
243     }
244
245     /**
246      * Get the data path number for the interface.
247      * @param interfaceManagerRpcService interfaceManagerRpcService instance.
248      * @param ifName the interface name.
249      * @return the dpn.
250      */
251     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
252         BigInteger nodeId = BigInteger.ZERO;
253         try {
254             GetDpidFromInterfaceInput dpIdInput =
255                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
256             Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
257                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
258             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
259             if (dpIdResult.isSuccessful()) {
260                 nodeId = dpIdResult.getResult().getDpid();
261             } else {
262                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
263             }
264         } catch (NullPointerException | InterruptedException | ExecutionException e) {
265             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
266         }
267         return nodeId;
268     }
269
270     /**
271      * Retrieves the interface state.
272      * @param dataBroker the data broker.
273      * @param interfaceName the interface name.
274      * @return the interface state.
275      */
276     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
277         .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
278         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
279             .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
280         return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
281     }
282
283     /**
284      * Build the interface state.
285      * @param interfaceName the interface name.
286      * @return the interface state.
287      */
288     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
289         .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
290         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
291             .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
292             .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
293             .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
294             .rev140508.interfaces.state.InterfaceKey(interfaceName));
295         return idBuilder.build();
296     }
297
298     /**
299      * Checks whether port security is enabled for the port.
300      * @param port the port.
301      * @return the port security is enabled/not.
302      */
303     public static boolean isPortSecurityEnabled(AclInterface port) {
304         return port.isPortSecurityEnabled();
305     }
306
307     /**
308      * Checks whether port security is enabled for the port.
309      * @param port the port.
310      * @return the list of security groups.
311      */
312     public static List<Uuid> getInterfaceAcls(Interface port) {
313         if (port == null) {
314             LOG.error("Port is Null");
315             return null;
316         }
317         InterfaceAcl aclInPort = port.augmentation(InterfaceAcl.class);
318         if (aclInPort == null) {
319             LOG.error("getSecurityGroupInPortList: no security group associated with port {}",
320                 port.getName());
321             return null;
322         }
323         return aclInPort.getSecurityGroups();
324     }
325
326     /**
327      * Retrieves the security rule attribute augmentation from the access list.
328      * @param ace the access list entry
329      * @return the security rule attributes
330      */
331     public static SecurityRuleAttr  getAccesssListAttributes(Ace ace) {
332         if (ace == null) {
333             LOG.error("Ace is Null");
334             return null;
335         }
336         SecurityRuleAttr aceAttributes = ace.augmentation(SecurityRuleAttr.class);
337         if (aceAttributes == null) {
338             LOG.error("Ace is null");
339             return null;
340         }
341         return aceAttributes;
342     }
343
344     /**
345      * Returns the DHCP match.
346      *
347      * @param srcPort the source port.
348      * @param dstPort the destination port.
349      * @param lportTag the lport tag
350      * @param serviceMode ingress or egress service
351      * @return list of matches.
352      */
353     public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag,
354             Class<? extends ServiceModeBase> serviceMode) {
355         List<MatchInfoBase> matches = new ArrayList<>(5);
356         matches.add(MatchEthernetType.IPV4);
357         matches.add(MatchIpProtocol.UDP);
358         matches.add(new MatchUdpDestinationPort(dstPort));
359         matches.add(new MatchUdpSourcePort(srcPort));
360         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
361         return matches;
362     }
363
364     /**
365      * Returns the DHCPv6 match.
366      *
367      * @param srcPort the source port.
368      * @param dstPort the destination port.
369      * @param lportTag the lport tag
370      * @param serviceMode ingress or egress
371      * @return list of matches.
372      */
373     public static List<MatchInfoBase> buildDhcpV6Matches(int srcPort, int dstPort, int lportTag,
374             Class<? extends ServiceModeBase> serviceMode) {
375         List<MatchInfoBase> matches = new ArrayList<>(6);
376         matches.add(MatchEthernetType.IPV6);
377         matches.add(MatchIpProtocol.UDP);
378         matches.add(new MatchUdpDestinationPort(dstPort));
379         matches.add(new MatchUdpSourcePort(srcPort));
380         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
381         return matches;
382     }
383
384     /**
385      * Returns the ICMPv6 match.
386      *
387      * @param icmpType the icmpv6-type.
388      * @param icmpCode the icmpv6-code.
389      * @param lportTag the lport tag
390      * @param serviceMode ingress or egress
391      * @return list of matches.
392      */
393     public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag,
394             Class<? extends ServiceModeBase> serviceMode) {
395         List<MatchInfoBase> matches = new ArrayList<>();
396         matches.add(MatchEthernetType.IPV6);
397         matches.add(MatchIpProtocol.ICMPV6);
398         if (icmpType != 0) {
399             matches.add(new MatchIcmpv6((short) icmpType, (short) icmpCode));
400         }
401         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
402         return matches;
403     }
404
405     public static List<MatchInfoBase> buildBroadcastIpV4Matches(String ipAddr) {
406         List<MatchInfoBase> matches = new ArrayList<>(2);
407         matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
408         matches.addAll(AclServiceUtils.buildIpMatches(new IpPrefixOrAddress(ipAddr.toCharArray()),
409                 MatchCriteria.MATCH_DESTINATION));
410         return matches;
411     }
412
413     public static List<MatchInfoBase> buildL2BroadcastMatches() {
414         List<MatchInfoBase> matches = new ArrayList<>();
415         matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
416         return matches;
417     }
418
419     /**
420      * Builds the service id.
421      *
422      * @param interfaceName the interface name
423      * @param serviceIndex the service index
424      * @param serviceMode the service mode
425      * @return the instance identifier
426      */
427     public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
428             Class<? extends ServiceModeBase> serviceMode) {
429         return InstanceIdentifier.builder(ServiceBindings.class)
430                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
431                 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
432     }
433
434     /**
435      * Gets the bound services.
436      *
437      * @param serviceName the service name
438      * @param servicePriority the service priority
439      * @param flowPriority the flow priority
440      * @param cookie the cookie
441      * @param instructions the instructions
442      * @return the bound services
443      */
444     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
445             BigInteger cookie, List<Instruction> instructions) {
446         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
447                 .setInstruction(instructions);
448         return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
449                 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
450                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
451     }
452
453     public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
454         if (updatedAclList == null) {
455             return Collections.emptyList();
456         }
457         List<Uuid> newAclList = new ArrayList<>(updatedAclList);
458         if (currentAclList == null) {
459             return newAclList;
460         }
461         List<Uuid> origAclList = new ArrayList<>(currentAclList);
462         for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
463             Uuid updatedAclUuid = iterator.next();
464             for (Uuid currentAclUuid :origAclList) {
465                 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
466                     iterator.remove();
467                 }
468             }
469         }
470         return newAclList;
471     }
472
473     public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
474             List<AllowedAddressPairs> updatedAllowedAddressPairs,
475             List<AllowedAddressPairs> currentAllowedAddressPairs) {
476         if (updatedAllowedAddressPairs == null) {
477             return null;
478         }
479         List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
480         if (currentAllowedAddressPairs == null) {
481             return newAllowedAddressPairs;
482         }
483         List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
484         for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
485             AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
486             for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
487                 if (updatedAllowedAddressPair.key().equals(currentAllowedAddressPair.key())) {
488                     iterator.remove();
489                     break;
490                 }
491             }
492         }
493         return newAllowedAddressPairs;
494     }
495
496     public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
497         if (port == null) {
498             LOG.error("Port is Null");
499             return null;
500         }
501         InterfaceAcl aclInPort = port.augmentation(InterfaceAcl.class);
502         if (aclInPort == null) {
503             LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
504             return null;
505         }
506         return aclInPort.getAllowedAddressPairs();
507     }
508
509     public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
510             .interfaces.rev140508.interfaces.state.Interface interfaceState) {
511         BigInteger dpId = null;
512         List<String> ofportIds = interfaceState.getLowerLayerIf();
513         if (ofportIds != null && !ofportIds.isEmpty()) {
514             NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
515             dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
516         }
517         return dpId;
518     }
519
520     public static List<String> getIpBroadcastAddresses(List<SubnetInfo> subnetInfoList) {
521         List<String> ipBroadcastAddresses = new ArrayList<>();
522         for (SubnetInfo subnetInfo : subnetInfoList) {
523             IpPrefix cidrIpPrefix = subnetInfo.getIpPrefix().getIpPrefix();
524             if (cidrIpPrefix != null) {
525                 Ipv4Prefix cidrIpv4Prefix = cidrIpPrefix.getIpv4Prefix();
526                 if (cidrIpv4Prefix != null) {
527                     ipBroadcastAddresses.add(getBroadcastAddressFromCidr(cidrIpv4Prefix.getValue()));
528                 }
529             }
530         }
531         return ipBroadcastAddresses;
532     }
533
534     public static String getBroadcastAddressFromCidr(String cidr) {
535         String[] ipaddressValues = cidr.split("/");
536         int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
537         int cidrPart = Integer.parseInt(ipaddressValues[1]);
538         int netmask = 0;
539         for (int j = 0; j < cidrPart; ++j) {
540             netmask |= 1 << 31 - j;
541         }
542         int network = address & netmask;
543         int broadcast = network | ~netmask;
544         return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
545     }
546
547     /**
548      * Builds the ip matches.
549      *
550      * @param ipPrefixOrAddress the ip prefix or address
551      * @param matchCriteria the source_ip or destination_ip used for the match
552      * @return the list
553      */
554     public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
555                                                      MatchCriteria matchCriteria) {
556         List<MatchInfoBase> flowMatches = new ArrayList<>();
557         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
558         if (ipPrefix != null) {
559             Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
560             if (ipv4Prefix != null) {
561                 flowMatches.add(MatchEthernetType.IPV4);
562                 if (!ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
563                     flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(ipv4Prefix)
564                             : new MatchIpv4Destination(ipv4Prefix));
565                 }
566             } else {
567                 flowMatches.add(MatchEthernetType.IPV6);
568                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
569                         ipPrefix.getIpv6Prefix()) : new MatchIpv6Destination(ipPrefix.getIpv6Prefix()));
570             }
571         } else {
572             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
573             if (ipAddress.getIpv4Address() != null) {
574                 flowMatches.add(MatchEthernetType.IPV4);
575                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(
576                         ipAddress.getIpv4Address().getValue(), "32") : new MatchIpv4Destination(
577                         ipAddress.getIpv4Address().getValue(), "32"));
578             } else {
579                 flowMatches.add(MatchEthernetType.IPV6);
580                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
581                         ipAddress.getIpv6Address().getValue() + "/128") : new MatchIpv6Destination(
582                         ipAddress.getIpv6Address().getValue() + "/128"));
583             }
584         }
585         return flowMatches;
586     }
587
588     /**
589      * Builds the arp ip matches.
590      * @param ipPrefixOrAddress the ip prefix or address
591      * @return the MatchInfoBase list
592      */
593     public static List<MatchInfoBase> buildArpIpMatches(IpPrefixOrAddress ipPrefixOrAddress) {
594         List<MatchInfoBase> flowMatches = new ArrayList<>();
595         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
596         if (ipPrefix != null) {
597             Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
598             if (ipv4Prefix != null && !ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
599                 flowMatches.add(new MatchArpSpa(ipv4Prefix));
600             }
601         } else {
602             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
603             if (ipAddress != null && ipAddress.getIpv4Address() != null) {
604                 flowMatches.add(new MatchArpSpa(ipAddress.getIpv4Address().getValue(), "32"));
605             }
606         }
607         return flowMatches;
608     }
609
610     public static MatchInfoBase buildRemoteAclTagMetadataMatch(Integer remoteAclTag) {
611         return new MatchMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
612                 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
613     }
614
615     public static BigInteger getRemoteAclTagMetadata(BigInteger remoteAclTag) {
616         return remoteAclTag.shiftLeft(4);
617     }
618
619     public static BigInteger getDropFlowCookie(int lport) {
620         return MetaDataUtil.getLportTagMetaData(lport).or(AclConstants.COOKIE_ACL_DROP_FLOW);
621     }
622
623     /**
624      * Does IPv4 address exists in the list of allowed address pair.
625      *
626      * @param aaps the allowed address pairs
627      * @return true, if successful
628      */
629     public static boolean doesIpv4AddressExists(List<AllowedAddressPairs> aaps) {
630         if (aaps == null) {
631             return false;
632         }
633         for (AllowedAddressPairs aap : aaps) {
634             IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
635             IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
636             if (ipPrefix != null) {
637                 if (ipPrefix.getIpv4Prefix() != null) {
638                     return true;
639                 }
640             } else {
641                 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
642                 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
643                     return true;
644                 }
645             }
646         }
647         return false;
648     }
649
650     /**
651      * Does IPv6 address exists in the list of allowed address pair.
652      *
653      * @param aaps the allowed address pairs
654      * @return true, if successful
655      */
656     public static boolean doesIpv6AddressExists(List<AllowedAddressPairs> aaps) {
657         if (aaps == null) {
658             return false;
659         }
660         for (AllowedAddressPairs aap : aaps) {
661             IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
662             IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
663             if (ipPrefix != null) {
664                 if (ipPrefix.getIpv6Prefix() != null) {
665                     return true;
666                 }
667             } else {
668                 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
669                 if (ipAddress != null && ipAddress.getIpv6Address() != null) {
670                     return true;
671                 }
672             }
673         }
674         return false;
675     }
676
677     /**
678      * Gets the lport tag match.
679      * Ingress match is based on metadata and egress match is based on masked reg6
680      *
681      * @param lportTag the lport tag
682      * @param serviceMode ingress or egress service mode
683      * @return the lport tag match
684      */
685     public static MatchInfoBase buildLPortTagMatch(int lportTag, Class<? extends ServiceModeBase> serviceMode) {
686         if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
687             return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
688                     MetaDataUtil.getLportTagMaskForReg6());
689         } else {
690             return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG);
691         }
692     }
693
694     public static List<MatchInfoBase> buildMatchesForLPortTagAndRemoteAclTag(Integer lportTag, Integer remoteAclTag,
695             Class<? extends ServiceModeBase> serviceMode) {
696         List<MatchInfoBase> matches = new ArrayList<>();
697         if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
698             matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
699             matches.add(AclServiceUtils.buildRemoteAclTagMetadataMatch(remoteAclTag));
700         } else {
701             // In case of ingress service mode, only metadata is used for
702             // matching both lportTag and aclTag. Hence performing "or"
703             // operation on both lportTag and aclTag metadata.
704             BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
705                     .or(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)));
706             BigInteger metaDataMask =
707                     MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
708             matches.add(new MatchMetadata(metaData, metaDataMask));
709         }
710         return matches;
711     }
712
713     public static Collection<? extends MatchInfoBase> buildMatchesForLPortTagAndConntrackClassifierType(int lportTag,
714             AclConntrackClassifierType conntrackClassifierType, Class<? extends ServiceModeBase> serviceMode) {
715         List<MatchInfoBase> matches = new ArrayList<>();
716         if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
717             matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
718             matches.add(AclServiceUtils.buildAclConntrackClassifierTypeMatch(conntrackClassifierType));
719         } else {
720             // In case of ingress service mode, only metadata is used for
721             // matching both lportTag and conntrackClassifierType. Hence performing "or"
722             // operation on both lportTag and conntrackClassifierType metadata.
723             BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
724                     .or(MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()));
725             BigInteger metaDataMask =
726                     MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
727             matches.add(new MatchMetadata(metaData, metaDataMask));
728         }
729         return matches;
730     }
731
732     public static InstructionWriteMetadata getWriteMetadataForAclClassifierType(
733             AclConntrackClassifierType conntrackClassifierType) {
734         return new InstructionWriteMetadata(
735                 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()),
736                 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
737     }
738
739     public static InstructionWriteMetadata getWriteMetadataForDropFlag() {
740         return new InstructionWriteMetadata(MetaDataUtil.getAclDropMetaData(AclConstants.METADATA_DROP_FLAG),
741                 MetaDataUtil.METADATA_MASK_ACL_DROP);
742     }
743
744     public static InstructionWriteMetadata getWriteMetadataForRemoteAclTag(Integer remoteAclTag) {
745         return new InstructionWriteMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
746                 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
747     }
748
749     public static MatchInfoBase buildAclConntrackClassifierTypeMatch(
750             AclConntrackClassifierType conntrackSupportedType) {
751         return new MatchMetadata(
752                 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackSupportedType.getValue()),
753                 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
754     }
755
756     public AclserviceConfig getConfig() {
757         return config;
758     }
759
760     public static boolean isIPv4Address(AllowedAddressPairs aap) {
761         IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
762         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
763         if (ipPrefix != null) {
764             if (ipPrefix.getIpv4Prefix() != null) {
765                 return true;
766             }
767         } else {
768             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
769             if (ipAddress != null && ipAddress.getIpv4Address() != null) {
770                 return true;
771             }
772         }
773         return false;
774     }
775
776     public static Map<String, List<MatchInfoBase>> getFlowForAllowedAddresses(
777             List<AllowedAddressPairs> syncAllowedAddresses, Map<String, List<MatchInfoBase>> flowMatchesMap,
778             boolean isSourceIpMacMatch) {
779         if (flowMatchesMap == null) {
780             return null;
781         }
782         Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
783         MatchInfoBase ipv4Match = MatchEthernetType.IPV4;
784         MatchInfoBase ipv6Match = MatchEthernetType.IPV6;
785         for (Entry<String, List<MatchInfoBase>> entry : flowMatchesMap.entrySet()) {
786             String flowName = entry.getKey();
787             List<MatchInfoBase> flows = entry.getValue();
788             // iterate over allow address pair and update match type
789             for (AllowedAddressPairs aap : syncAllowedAddresses) {
790                 List<MatchInfoBase> matchInfoBaseList;
791                 String flowId;
792                 if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) {
793                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
794                     flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap);
795                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
796                 } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) {
797                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
798                     flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap);
799                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
800                 }
801             }
802         }
803         return updatedFlowMatchesMap;
804     }
805
806     public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) {
807         IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
808         if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null
809                 && ipPrefix.getIpv4Prefix().getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
810             return false;
811         }
812         return true;
813     }
814
815     protected static boolean isNotIpv6AllNetwork(AllowedAddressPairs aap) {
816         IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
817         if (ipPrefix != null && ipPrefix.getIpv6Prefix() != null
818                 && ipPrefix.getIpv6Prefix().getValue().equals(AclConstants.IPV6_ALL_NETWORK)) {
819             return false;
820         }
821         return true;
822     }
823
824     public static boolean isNotIpAllNetwork(AllowedAddressPairs aap) {
825         return isNotIpv4AllNetwork(aap) && isNotIpv6AllNetwork(aap);
826     }
827
828     private static String getAapFlowId(AllowedAddressPairs aap) {
829         return aap.getMacAddress().getValue() + "_" + String.valueOf(aap.getIpAddress().getValue());
830     }
831
832     public static Long getElanIdFromInterface(String elanInterfaceName,DataBroker broker) {
833         ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
834         if (null != elanInterface) {
835             ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
836             return elanInfo.getElanTag();
837         }
838         return null;
839     }
840
841     public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
842         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
843         return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
844     }
845
846     public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
847         return InstanceIdentifier.builder(ElanInterfaces.class)
848                 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
849     }
850
851     // elan-instances config container
852     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
853         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
854         return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
855     }
856
857     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
858         return InstanceIdentifier.builder(ElanInstances.class)
859                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
860     }
861
862     public List<SubnetInfo> getSubnetInfo(String portId) {
863         InstanceIdentifier<PortSubnet> id = InstanceIdentifier.builder(PortSubnets.class)
864                 .child(PortSubnet.class, new PortSubnetKey(portId)).build();
865
866         Optional<PortSubnet> portSubnet = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
867         if (portSubnet.isPresent()) {
868             return portSubnet.get().getSubnetInfo();
869         }
870         return null;
871     }
872
873     public void deleteSubnetInfo(String portId) {
874         InstanceIdentifier<PortSubnet> id = InstanceIdentifier.builder(PortSubnets.class)
875                 .child(PortSubnet.class, new PortSubnetKey(portId)).build();
876         try {
877             SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
878         } catch (TransactionCommitFailedException e) {
879             LOG.error("Failed to delete subnet info for port={}", portId, e);
880         }
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 void deleteAclPortsLookupEntry(String aclName, DataBroker broker)
1249             throws TransactionCommitFailedException {
1250         SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, aclPortsByIpPath(aclName));
1251     }
1252
1253     public static InstanceIdentifier<AclPortsByIp> aclPortsByIpPath(String aclName) {
1254         return InstanceIdentifier.builder(AclPortsLookup.class)
1255                 .child(AclPortsByIp.class, new AclPortsByIpKey(aclName)).build();
1256     }
1257
1258     public static InstanceIdentifier<AclIpPrefixes> getAclIpPrefixesPath(String aclName, IpPrefixOrAddress ipPrefix) {
1259         return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(aclName))
1260                 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).build();
1261     }
1262
1263     public static InstanceIdentifier<PortIds> getPortIdsPathInAclPortsLookup(String ruleName,
1264             IpPrefixOrAddress ipPrefix, String portId) {
1265         return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(ruleName))
1266                 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).child(PortIds.class, new PortIdsKey(portId))
1267                 .build();
1268     }
1269
1270     public void addAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
1271         LOG.debug("Processing interface additions for port {}", portAfter.getInterfaceId());
1272         List<AllowedAddressPairs> addedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1273                 portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
1274         if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
1275             addAclPortsLookup(portAfter, portAfter.getSecurityGroups(), addedAllowedAddressPairs);
1276         }
1277
1278         List<Uuid> addedAcls = getUpdatedAclList(portAfter.getSecurityGroups(), portBefore.getSecurityGroups());
1279         if (addedAcls != null && !addedAcls.isEmpty()) {
1280             addAclPortsLookup(portAfter, addedAcls, portAfter.getAllowedAddressPairs());
1281         }
1282     }
1283
1284     public void deleteAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
1285         LOG.debug("Processing interface removals for port {}", portAfter.getInterfaceId());
1286         List<AllowedAddressPairs> deletedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1287                 portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
1288         if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
1289             deleteAclPortsLookup(portAfter, portAfter.getSecurityGroups(), deletedAllowedAddressPairs);
1290         }
1291
1292         List<Uuid> deletedAcls = getUpdatedAclList(portBefore.getSecurityGroups(), portAfter.getSecurityGroups());
1293         if (deletedAcls != null && !deletedAcls.isEmpty()) {
1294             deleteAclPortsLookup(portAfter, deletedAcls, portAfter.getAllowedAddressPairs());
1295         }
1296     }
1297
1298     public void addAclPortsLookup(AclInterface port, List<Uuid> aclList,
1299             List<AllowedAddressPairs> allowedAddresses) {
1300         String portId = port.getInterfaceId();
1301         LOG.trace("Adding AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1302
1303         if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1304             LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1305                     allowedAddresses);
1306             return;
1307         }
1308
1309         for (Uuid aclId : aclList) {
1310             String aclName = aclId.getValue();
1311             jobCoordinator.enqueueJob(aclName.intern(), () -> {
1312                 List<ListenableFuture<Void>> futures = new ArrayList<>();
1313                 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1314                     for (AllowedAddressPairs aap : allowedAddresses) {
1315                         PortIds portIdObj =
1316                                 new PortIdsBuilder().withKey(new PortIdsKey(portId)).setPortId(portId).build();
1317                         InstanceIdentifier<PortIds> path =
1318                                 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1319                         tx.put(LogicalDatastoreType.OPERATIONAL, path, portIdObj,
1320                                 WriteTransaction.CREATE_MISSING_PARENTS);
1321                     }
1322                 }));
1323                 return futures;
1324             });
1325         }
1326     }
1327
1328     public void deleteAclPortsLookup(AclInterface port, List<Uuid> aclList,
1329             List<AllowedAddressPairs> allowedAddresses) {
1330         String portId = port.getInterfaceId();
1331         LOG.trace("Deleting AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1332
1333         if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1334             LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1335                     allowedAddresses);
1336             return;
1337         }
1338
1339         for (Uuid aclId : aclList) {
1340             String aclName = aclId.getValue();
1341             jobCoordinator.enqueueJob(aclName.intern(), () -> {
1342                 List<ListenableFuture<Void>> futures = new ArrayList<>();
1343                 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1344                     for (AllowedAddressPairs aap : allowedAddresses) {
1345                         InstanceIdentifier<PortIds> path =
1346                                 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1347                         tx.delete(LogicalDatastoreType.OPERATIONAL, path);
1348                     }
1349
1350                     cleanUpStaleEntriesInAclPortsLookup(aclName, tx);
1351                 }));
1352                 return futures;
1353             });
1354         }
1355     }
1356
1357     private void cleanUpStaleEntriesInAclPortsLookup(String aclName, WriteTransaction tx) {
1358         AclPortsByIp aclPortsByIp = getAclPortsByIpFromOperDs(aclName);
1359         if (aclPortsByIp == null) {
1360             return;
1361         }
1362         boolean deleteEntireAcl;
1363         List<AclIpPrefixes> ipPrefixes = aclPortsByIp.getAclIpPrefixes();
1364         if (ipPrefixes == null || ipPrefixes.isEmpty()) {
1365             deleteEntireAcl = true;
1366         } else {
1367             boolean deleteMap = true;
1368             for (AclIpPrefixes ipPrefix : ipPrefixes) {
1369                 if (ipPrefix.getPortIds() != null && !ipPrefix.getPortIds().isEmpty()) {
1370                     deleteMap = false;
1371                     break;
1372                 }
1373             }
1374             deleteEntireAcl = deleteMap;
1375         }
1376         if (deleteEntireAcl) {
1377             tx.delete(LogicalDatastoreType.OPERATIONAL, AclServiceUtils.aclPortsByIpPath(aclName));
1378         } else {
1379             for (AclIpPrefixes ipPrefix : ipPrefixes) {
1380                 if (ipPrefix.getPortIds() == null || ipPrefix.getPortIds().isEmpty()) {
1381                     InstanceIdentifier<AclIpPrefixes> delPath =
1382                             AclServiceUtils.getAclIpPrefixesPath(aclName, ipPrefix.getIpPrefix());
1383                     tx.delete(LogicalDatastoreType.OPERATIONAL, delPath);
1384                 }
1385             }
1386         }
1387     }
1388
1389     @Nullable
1390     private AclPortsByIp getAclPortsByIpFromOperDs(String aclName) {
1391         InstanceIdentifier<AclPortsByIp> path = aclPortsByIpPath(aclName);
1392         try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
1393             return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
1394         } catch (ReadFailedException e) {
1395             LOG.error("Failed to read ACL ports {}", path, e);
1396             return null;
1397         }
1398     }
1399
1400     @Nullable
1401     private AclIpPrefixes getAclIpPrefixesFromOperDs(String aclName, IpPrefixOrAddress ipPrefix) {
1402         InstanceIdentifier<AclIpPrefixes> path = getAclIpPrefixesPath(aclName, ipPrefix);
1403         try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
1404             return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
1405         } catch (ReadFailedException e) {
1406             LOG.error("Failed to read ACL IP prefixes {}", path, e);
1407             return null;
1408         }
1409     }
1410
1411     /**
1412      * Gets the ace flow priority.
1413      *
1414      * @param aclName the acl name
1415      * @return the ace flow priority
1416      */
1417     public Integer getAceFlowPriority(String aclName) {
1418         Integer priority = AclConstants.ACE_DEFAULT_PRIORITY;
1419         Integer aclTag = getAclTag(new Uuid(aclName));
1420         if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
1421             // To handle overlapping rules, aclTag is added to priority
1422             priority += aclTag;
1423         } else {
1424             LOG.warn("aclTag={} is null or invalid for aclName={}", aclTag, aclName);
1425         }
1426         return priority;
1427     }
1428
1429     /**
1430      * Returns the hard timeout based on the protocol when a ACL rule removed from the instance.
1431      * It will returns the timeout configured in the {@link AclserviceConfig} class.
1432      *
1433      * @param ace the ace
1434      * @param aclServiceUtils acl service utils
1435      * @return the hard time out
1436      */
1437     public static Integer getHardTimoutForApplyStatefulChangeOnExistingTraffic(Ace ace,
1438             AclServiceUtils aclServiceUtils) {
1439         int hardTimeout = AclConstants.SECURITY_GROUP_ICMP_IDLE_TIME_OUT;
1440         Matches matches = ace.getMatches();
1441         AceIp acl = (AceIp) matches.getAceType();
1442         Short protocol = acl.getProtocol();
1443         if (protocol == null) {
1444             return hardTimeout;
1445         } else if (protocol == NwConstants.IP_PROT_TCP) {
1446             hardTimeout = aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout();
1447         } else if (protocol == NwConstants.IP_PROT_UDP) {
1448             hardTimeout = aclServiceUtils.getConfig().getSecurityGroupUdpIdleTimeout();
1449         }
1450         return hardTimeout;
1451     }
1452
1453     /**
1454      * This method creates and returns the ct_mark instruction when a ACL rule removed from the
1455      * instance. This instruction will reset the ct_mark value and stops the existing traffics.
1456      *
1457      * @param filterTable the filterTable
1458      * @param elanId the Elan id
1459      * @return list of instruction
1460      */
1461     public static List<InstructionInfo> createCtMarkInstructionForNewState(Short filterTable, Long elanId) {
1462
1463         List<InstructionInfo> instructions = new ArrayList<>();
1464         List<ActionInfo> actionsInfos = new ArrayList<>();
1465         List<NxCtAction> ctActionsList = new ArrayList<>();
1466         NxCtAction nxCtMarkClearAction = new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_NEW_STATE);
1467         ctActionsList.add(nxCtMarkClearAction);
1468
1469         ActionNxConntrack actionNxConntrack = new ActionNxConntrack(2, 1, 0, elanId.intValue(),
1470             (short) 255, ctActionsList);
1471         actionsInfos.add(actionNxConntrack);
1472         instructions.add(new InstructionApplyActions(actionsInfos));
1473         instructions.add(new InstructionGotoTable(filterTable));
1474
1475         return instructions;
1476     }
1477
1478     public static List<AllowedAddressPairs> excludeMulticastAAPs(List<AllowedAddressPairs> allowedAddresses) {
1479         List<AllowedAddressPairs> filteredAAPs = new ArrayList<>();
1480         for (AllowedAddressPairs allowedAddress : allowedAddresses) {
1481             InetAddress inetAddr = getInetAddress(allowedAddress.getIpAddress());
1482             if (inetAddr != null && !inetAddr.isMulticastAddress()) {
1483                 filteredAAPs.add(allowedAddress);
1484             }
1485         }
1486         return filteredAAPs;
1487     }
1488
1489     public static String getRecoverServiceRegistryKey() {
1490         return NetvirtAcl.class.toString();
1491     }
1492
1493     private static InetAddress getInetAddress(IpPrefixOrAddress ipPrefixOrAddress) {
1494         InetAddress inetAddress = null;
1495         String addr = null;
1496
1497         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
1498         if (ipPrefix != null) {
1499             addr = String.valueOf(ipPrefix.getValue()).split("/")[0];
1500         } else {
1501             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
1502             if (ipAddress == null) {
1503                 LOG.error("Invalid address : {}", ipPrefixOrAddress);
1504                 return null;
1505             } else {
1506                 addr = String.valueOf(ipAddress.getValue());
1507             }
1508         }
1509         try {
1510             inetAddress = InetAddress.getByName(addr);
1511         } catch (UnknownHostException e) {
1512             LOG.error("Invalid address : {}", addr, e);
1513             return null;
1514         }
1515         return inetAddress;
1516     }
1517
1518     public static Boolean isIpv6Subnet(List<SubnetInfo> subnetInfoList) {
1519         if (subnetInfoList != null && !subnetInfoList.isEmpty()) {
1520             for (SubnetInfo subnetInfo : subnetInfoList) {
1521                 if (subnetInfo != null && IpVersionV6.class.equals(subnetInfo.getIpVersion())) {
1522                     return true;
1523                 }
1524             }
1525         }
1526         return false;
1527     }
1528
1529     /**
1530      * Gets the subnet difference by performing (subnetInfo1 - subnetInfo2).
1531      *
1532      * @param subnetInfo1 the subnet info 1
1533      * @param subnetInfo2 the subnet info 2
1534      * @return the subnet diff
1535      */
1536     public static List<SubnetInfo> getSubnetDiff(List<SubnetInfo> subnetInfo1, List<SubnetInfo> subnetInfo2) {
1537         if (subnetInfo1 == null) {
1538             return Collections.emptyList();
1539         }
1540         List<SubnetInfo> newSubnetList = new ArrayList<>(subnetInfo1);
1541         if (subnetInfo2 == null) {
1542             return newSubnetList;
1543         }
1544         newSubnetList.removeAll(subnetInfo2);
1545         return newSubnetList;
1546     }
1547 }