Bug 8793: Null Pointer Exceptions in Carbon CSIT
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / utils / AclServiceUtils.java
1 /*
2  * Copyright © 2016, 2017 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 java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Future;
20 import javax.inject.Inject;
21 import javax.inject.Singleton;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
26 import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil;
27 import org.opendaylight.genius.mdsalutil.MDSALUtil;
28 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
29 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
30 import org.opendaylight.genius.mdsalutil.NwConstants;
31 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
32 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
33 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
34 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
35 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
36 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
37 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Destination;
38 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source;
39 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
40 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
41 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
42 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
43 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
44 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
45 import org.opendaylight.netvirt.aclservice.api.utils.AclInterfaceCacheUtil;
46 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
103 import org.opendaylight.yangtools.yang.binding.DataObject;
104 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
105 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
106 import org.opendaylight.yangtools.yang.common.RpcResult;
107 import org.slf4j.Logger;
108 import org.slf4j.LoggerFactory;
109
110 @Singleton
111 @SuppressWarnings("deprecation")
112 public final class AclServiceUtils {
113
114     private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
115     public static final AclserviceConfig.DefaultBehavior DEFAULT_DENY = AclserviceConfig.DefaultBehavior.Deny;
116     public static final AclserviceConfig.DefaultBehavior DEFAULT_ALLOW = AclserviceConfig.DefaultBehavior.Allow;
117
118     private final AclDataUtil aclDataUtil;
119     private final AclserviceConfig config;
120     private final IdManagerService idManager;
121
122     @Inject
123     public AclServiceUtils(AclDataUtil aclDataUtil, AclserviceConfig config, IdManagerService idManager) {
124         super();
125         this.aclDataUtil = aclDataUtil;
126         this.config = config;
127         this.idManager = idManager;
128     }
129
130     /**
131      * Retrieves the Interface from the datastore.
132      * @param broker the data broker
133      * @param interfaceName the interface name
134      * @return the interface.
135      */
136     public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
137         .Interface> getInterface(DataBroker broker, String interfaceName) {
138         return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
139     }
140
141     /**
142      * Builds the interface identifier.
143      * @param interfaceName the interface name.
144      * @return the interface identifier.
145      */
146     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
147         .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
148         return InstanceIdentifier.builder(Interfaces.class)
149                 .child(
150                     org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
151                     .Interface.class, new InterfaceKey(interfaceName)).build();
152     }
153
154     /**
155      * Retrieves the object from the datastore.
156      * @param broker the data broker.
157      * @param datastoreType the data store type.
158      * @param path the wild card path.
159      * @param <T> type of DataObject
160      * @return the required object.
161      */
162     public static <T extends DataObject> Optional<T> read(
163             DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
164         try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
165             return tx.read(datastoreType, path).checkedGet();
166         } catch (ReadFailedException e) {
167             LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
168             return Optional.absent();
169         }
170     }
171
172     /**
173      * Retrieves the acl matching the key from the data store.
174      *
175      * @param broker the data broker
176      * @param aclKey the acl key
177      * @return the acl
178      */
179     public static Acl getAcl(DataBroker broker, String aclKey) {
180         return read(broker, LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey)).orNull();
181     }
182
183     /** Creates the Acl instance identifier.
184      *
185      * @param aclKey the acl key
186      * @return the instance identifier
187      */
188     public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
189         return InstanceIdentifier
190                 .builder(AccessLists.class)
191                 .child(Acl.class,
192                         new AclKey(aclKey,Ipv4Acl.class))
193                 .build();
194     }
195
196     /**
197      * Get the data path number for the interface.
198      * @param interfaceManagerRpcService interfaceManagerRpcService instance.
199      * @param ifName the interface name.
200      * @return the dpn.
201      */
202     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
203         BigInteger nodeId = BigInteger.ZERO;
204         try {
205             GetDpidFromInterfaceInput dpIdInput =
206                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
207             Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
208                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
209             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
210             if (dpIdResult.isSuccessful()) {
211                 nodeId = dpIdResult.getResult().getDpid();
212             } else {
213                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
214             }
215         } catch (NullPointerException | InterruptedException | ExecutionException e) {
216             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
217         }
218         return nodeId;
219     }
220
221     /**
222      * Retrieves the interface state.
223      * @param dataBroker the data broker.
224      * @param interfaceName the interface name.
225      * @return the interface state.
226      */
227     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
228         .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
229         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
230             .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
231         return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
232     }
233
234     /**
235      * Build the interface state.
236      * @param interfaceName the interface name.
237      * @return the interface state.
238      */
239     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
240         .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
241         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
242             .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
243             .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
244             .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
245             .rev140508.interfaces.state.InterfaceKey(interfaceName));
246         return idBuilder.build();
247     }
248
249     /**
250      * Checks whether port security is enabled for the port.
251      * @param port the port.
252      * @return the port security is enabled/not.
253      */
254     public static boolean isPortSecurityEnabled(AclInterface port) {
255         return port.isPortSecurityEnabled();
256     }
257
258     /**
259      * Checks whether port security is enabled for the port.
260      * @param port the port.
261      * @return the list of security groups.
262      */
263     public static List<Uuid> getInterfaceAcls(Interface port) {
264         if (port == null) {
265             LOG.error("Port is Null");
266             return null;
267         }
268         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
269         if (aclInPort == null) {
270             LOG.error("getSecurityGroupInPortList: no security group associated}",
271                 port.getName());
272             return null;
273         }
274         return aclInPort.getSecurityGroups();
275     }
276
277     /**
278      * Retrieves the security rule attribute augmentation from the access list.
279      * @param ace the access list entry
280      * @return the security rule attributes
281      */
282     public static SecurityRuleAttr  getAccesssListAttributes(Ace ace) {
283         if (ace == null) {
284             LOG.error("Ace is Null");
285             return null;
286         }
287         SecurityRuleAttr aceAttributes = ace.getAugmentation(SecurityRuleAttr.class);
288         if (aceAttributes == null) {
289             LOG.error("Ace is null");
290             return null;
291         }
292         return aceAttributes;
293     }
294
295     /**
296      * Returns the DHCP match.
297      *
298      * @param srcPort the source port.
299      * @param dstPort the destination port.
300      * @param lportTag the lport tag
301      * @param serviceMode ingress or egress service
302      * @return list of matches.
303      */
304     public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag,
305             Class<? extends ServiceModeBase> serviceMode) {
306         List<MatchInfoBase> matches = new ArrayList<>(6);
307         matches.add(MatchEthernetType.IPV4);
308         matches.add(MatchIpProtocol.UDP);
309         matches.add(new MatchUdpDestinationPort(dstPort));
310         matches.add(new MatchUdpSourcePort(srcPort));
311         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
312         return matches;
313     }
314
315     /**
316      * Returns the DHCPv6 match.
317      *
318      * @param srcPort the source port.
319      * @param dstPort the destination port.
320      * @param lportTag the lport tag
321      * @param serviceMode ingress or egress
322      * @return list of matches.
323      */
324     public static List<MatchInfoBase> buildDhcpV6Matches(int srcPort, int dstPort, int lportTag,
325             Class<? extends ServiceModeBase> serviceMode) {
326         List<MatchInfoBase> matches = new ArrayList<>(6);
327         matches.add(MatchEthernetType.IPV6);
328         matches.add(MatchIpProtocol.UDP);
329         matches.add(new MatchUdpDestinationPort(dstPort));
330         matches.add(new MatchUdpSourcePort(srcPort));
331         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
332         return matches;
333     }
334
335     /**
336      * Returns the ICMPv6 match.
337      *
338      * @param icmpType the icmpv6-type.
339      * @param icmpCode the icmpv6-code.
340      * @param lportTag the lport tag
341      * @param serviceMode ingress or egress
342      * @return list of matches.
343      */
344     public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag,
345             Class<? extends ServiceModeBase> serviceMode) {
346         List<MatchInfoBase> matches = new ArrayList<>(6);
347         matches.add(MatchEthernetType.IPV6);
348         matches.add(MatchIpProtocol.ICMPV6);
349         if (icmpType != 0) {
350             matches.add(new MatchIcmpv6((short) icmpType, (short) icmpCode));
351         }
352         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
353         return matches;
354     }
355
356     /**
357      * Builds the service id.
358      *
359      * @param interfaceName the interface name
360      * @param serviceIndex the service index
361      * @param serviceMode the service mode
362      * @return the instance identifier
363      */
364     public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
365             Class<? extends ServiceModeBase> serviceMode) {
366         return InstanceIdentifier.builder(ServiceBindings.class)
367                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
368                 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
369     }
370
371     /**
372      * Gets the bound services.
373      *
374      * @param serviceName the service name
375      * @param servicePriority the service priority
376      * @param flowPriority the flow priority
377      * @param cookie the cookie
378      * @param instructions the instructions
379      * @return the bound services
380      */
381     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
382             BigInteger cookie, List<Instruction> instructions) {
383         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
384                 .setInstruction(instructions);
385         return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
386                 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
387                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
388     }
389
390     public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
391         if (updatedAclList == null) {
392             return null;
393         }
394         List<Uuid> newAclList = new ArrayList<>(updatedAclList);
395         if (currentAclList == null) {
396             return newAclList;
397         }
398         List<Uuid> origAclList = new ArrayList<>(currentAclList);
399         for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
400             Uuid updatedAclUuid = iterator.next();
401             for (Uuid currentAclUuid :origAclList) {
402                 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
403                     iterator.remove();
404                 }
405             }
406         }
407         return newAclList;
408     }
409
410     public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
411             List<AllowedAddressPairs> updatedAllowedAddressPairs,
412             List<AllowedAddressPairs> currentAllowedAddressPairs) {
413         if (updatedAllowedAddressPairs == null) {
414             return null;
415         }
416         List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
417         if (currentAllowedAddressPairs == null) {
418             return newAllowedAddressPairs;
419         }
420         List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
421         for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
422             AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
423             for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
424                 if (updatedAllowedAddressPair.getKey().equals(currentAllowedAddressPair.getKey())) {
425                     iterator.remove();
426                     break;
427                 }
428             }
429         }
430         return newAllowedAddressPairs;
431     }
432
433     public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
434         if (port == null) {
435             LOG.error("Port is Null");
436             return null;
437         }
438         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
439         if (aclInPort == null) {
440             LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
441             return null;
442         }
443         return aclInPort.getAllowedAddressPairs();
444     }
445
446     public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
447             .interfaces.rev140508.interfaces.state.Interface interfaceState) {
448         BigInteger dpId = null;
449         List<String> ofportIds = interfaceState.getLowerLayerIf();
450         if (ofportIds != null && !ofportIds.isEmpty()) {
451             NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
452             dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
453         }
454         return dpId;
455     }
456
457     /**
458      * Builds the ip matches.
459      *
460      * @param ipPrefixOrAddress the ip prefix or address
461      * @param matchCriteria the source_ip or destination_ip used for the match
462      * @return the list
463      */
464     public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
465                                                      MatchCriteria matchCriteria) {
466         List<MatchInfoBase> flowMatches = new ArrayList<>();
467         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
468         if (ipPrefix != null) {
469             Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
470             if (ipv4Prefix != null) {
471                 flowMatches.add(MatchEthernetType.IPV4);
472                 if (!ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
473                     flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(ipv4Prefix)
474                             : new MatchIpv4Destination(ipv4Prefix));
475                 }
476             } else {
477                 flowMatches.add(MatchEthernetType.IPV6);
478                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
479                         ipPrefix.getIpv6Prefix()) : new MatchIpv6Destination(ipPrefix.getIpv6Prefix()));
480             }
481         } else {
482             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
483             if (ipAddress.getIpv4Address() != null) {
484                 flowMatches.add(MatchEthernetType.IPV4);
485                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(
486                         ipAddress.getIpv4Address().getValue(), "32") : new MatchIpv4Destination(
487                         ipAddress.getIpv4Address().getValue(), "32"));
488             } else {
489                 flowMatches.add(MatchEthernetType.IPV6);
490                 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
491                         ipAddress.getIpv6Address().getValue() + "/128") : new MatchIpv6Destination(
492                         ipAddress.getIpv6Address().getValue() + "/128"));
493             }
494         }
495         return flowMatches;
496     }
497
498     private List<MatchInfoBase> buildAclIdMetadataMatch(Uuid remoteAclId) {
499         List<MatchInfoBase> flowMatches = new ArrayList<>();
500         BigInteger aclId = buildAclId(remoteAclId);
501         if (aclId.intValue() != AclConstants.INVALID_ACL_ID) {
502             MatchMetadata metadataMatch = new MatchMetadata(getAclIdMetadata(aclId),
503                     MetaDataUtil.METADATA_MASK_REMOTE_ACL_ID);
504             flowMatches.add(metadataMatch);
505         } else {
506             LOG.error("Failed building metadata match for Acl id match. Failed to allocate id");
507         }
508         return flowMatches;
509     }
510
511     public BigInteger buildAclId(Uuid remoteAclId) {
512         Integer aclId = allocateAclId(remoteAclId.getValue());
513         return BigInteger.valueOf(aclId);
514     }
515
516     public static BigInteger getAclIdMetadata(BigInteger aclId) {
517         return aclId.shiftLeft(1);
518     }
519
520     /**
521      * Gets the lport tag match.
522      * Ingress match is based on metadata and egress match is based on masked reg6
523      *
524      * @param lportTag the lport tag
525      * @param serviceMode ingress or egress service mode
526      * @return the lport tag match
527      */
528     public static MatchInfoBase buildLPortTagMatch(int lportTag, Class<? extends ServiceModeBase> serviceMode) {
529         if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeIngress.class)) {
530             return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
531                     MetaDataUtil.getLportTagMaskForReg6());
532         } else {
533             return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG);
534         }
535     }
536
537     public static List<Ace> getAceWithRemoteAclId(DataBroker dataBroker, AclInterface port, Uuid remoteAcl) {
538         List<Ace> remoteAclRuleList = new ArrayList<>();
539         List<Uuid> aclList = port.getSecurityGroups();
540         for (Uuid aclId : aclList) {
541             Acl acl = getAcl(dataBroker, aclId.getValue());
542             List<Ace> aceList = acl.getAccessListEntries().getAce();
543             for (Ace ace : aceList) {
544                 Uuid tempRemoteAcl = getAccesssListAttributes(ace).getRemoteGroupId();
545                 if (tempRemoteAcl != null && tempRemoteAcl.equals(remoteAcl)) {
546                     remoteAclRuleList.add(ace);
547                 }
548             }
549         }
550         return remoteAclRuleList;
551     }
552
553     public Map<String, List<MatchInfoBase>> getFlowForRemoteAcl(AclInterface aclInterface, Uuid remoteAclId,
554             String ignoreInterfaceId, Map<String, List<MatchInfoBase>> flowMatchesMap, boolean isSourceIpMacMatch) {
555         boolean singleAcl = false;
556         List<AclInterface> interfaceList = null;
557         if (aclInterface.getSecurityGroups() != null && aclInterface.getSecurityGroups().size() == 1) {
558             singleAcl = true;
559         } else {
560             interfaceList = aclDataUtil.getInterfaceList(remoteAclId);
561             if (flowMatchesMap == null || interfaceList == null || interfaceList.isEmpty()) {
562                 return null;
563             }
564         }
565         Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
566         MatchInfoBase ipv4Match = MatchEthernetType.IPV4;
567         MatchInfoBase ipv6Match = MatchEthernetType.IPV6;
568         for (String flowName : flowMatchesMap.keySet()) {
569             List<MatchInfoBase> flows = flowMatchesMap.get(flowName);
570             if (singleAcl) {
571                 LOG.debug("port {} is in only one SG. "
572                         + "Doesn't adding it's IPs {} to matches (handled in acl id match)",
573                         aclInterface.getLPortTag(), aclInterface.getAllowedAddressPairs());
574                 List<MatchInfoBase> matchInfoBaseList = addFlowMatchForAclId(remoteAclId, flows);
575                 String flowId = flowName + "_remoteACL_id_" + remoteAclId.getValue();
576                 updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
577                 continue;
578             }
579             for (AclInterface port : interfaceList) {
580                 if (port.getInterfaceId().equals(ignoreInterfaceId)) {
581                     continue;
582                 }
583
584                 // get allow address pair
585                 List<AllowedAddressPairs> allowedAddressPair = port.getAllowedAddressPairs();
586                 // iterate over allow address pair and update match type
587                 for (AllowedAddressPairs aap : allowedAddressPair) {
588                     List<MatchInfoBase> matchInfoBaseList;
589                     String flowId;
590                     if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) {
591                         matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
592                         flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap);
593                         updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
594                     } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) {
595                         matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
596                         flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap);
597                         updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
598                     }
599                 }
600             }
601         }
602         return updatedFlowMatchesMap;
603     }
604
605     public AclserviceConfig getConfig() {
606         return config;
607     }
608
609     private static boolean isIPv4Address(AllowedAddressPairs aap) {
610         IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
611         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
612         if (ipPrefix != null) {
613             if (ipPrefix.getIpv4Prefix() != null) {
614                 return true;
615             }
616         } else {
617             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
618             if (ipAddress.getIpv4Address() != null) {
619                 return true;
620             }
621         }
622         return false;
623     }
624
625     public static Map<String, List<MatchInfoBase>> getFlowForAllowedAddresses(
626             List<AllowedAddressPairs> syncAllowedAddresses, Map<String, List<MatchInfoBase>> flowMatchesMap,
627             boolean isSourceIpMacMatch) {
628         if (flowMatchesMap == null) {
629             return null;
630         }
631         Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
632         MatchInfoBase ipv4Match = MatchEthernetType.IPV4;
633         MatchInfoBase ipv6Match = MatchEthernetType.IPV6;
634         for (String flowName : flowMatchesMap.keySet()) {
635             List<MatchInfoBase> flows = flowMatchesMap.get(flowName);
636             // iterate over allow address pair and update match type
637             for (AllowedAddressPairs aap : syncAllowedAddresses) {
638                 List<MatchInfoBase> matchInfoBaseList;
639                 String flowId;
640                 if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) {
641                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
642                     flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap);
643                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
644                 } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) {
645                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
646                     flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap);
647                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
648                 }
649             }
650         }
651         return updatedFlowMatchesMap;
652     }
653
654     public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) {
655         IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
656         if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null
657                 && ipPrefix.getIpv4Prefix().getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
658             return false;
659         }
660         return true;
661     }
662
663     protected static boolean isNotIpv6AllNetwork(AllowedAddressPairs aap) {
664         IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
665         if (ipPrefix != null && ipPrefix.getIpv6Prefix() != null
666                 && ipPrefix.getIpv6Prefix().getValue().equals(AclConstants.IPV6_ALL_NETWORK)) {
667             return false;
668         }
669         return true;
670     }
671
672     private static String getAapFlowId(AllowedAddressPairs aap) {
673         return aap.getMacAddress().getValue() + "_" + String.valueOf(aap.getIpAddress().getValue());
674     }
675
676     public static Long getElanIdFromInterface(String elanInterfaceName,DataBroker broker) {
677         ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
678         if (null != elanInterface) {
679             ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
680             return elanInfo.getElanTag();
681         }
682         return null;
683     }
684
685     public static Long getElanIdFromAclInterface(String elanInterfaceName) {
686         AclInterface aclInterface = AclInterfaceCacheUtil.getAclInterfaceFromCache(elanInterfaceName);
687         if (null != aclInterface) {
688             return aclInterface.getElanId();
689         }
690         return null;
691     }
692
693     public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
694         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
695         return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
696     }
697
698     public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
699         return InstanceIdentifier.builder(ElanInterfaces.class)
700                 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
701     }
702
703     // elan-instances config container
704     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
705         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
706         return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
707     }
708
709     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
710         return InstanceIdentifier.builder(ElanInstances.class)
711                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
712     }
713
714     public static Long getVpnIdFromInterface(DataBroker broker, String vpnInterfaceName) {
715         VpnInterface vpnInterface = VpnHelper.getVpnInterface(broker, vpnInterfaceName);
716         if (vpnInterface != null) {
717             return VpnHelper.getVpnId(broker, vpnInterface.getVpnInstanceName());
718         }
719         return null;
720     }
721
722     private static List<MatchInfoBase> updateAAPMatches(boolean isSourceIpMacMatch, List<MatchInfoBase> flows,
723                                                         AllowedAddressPairs aap) {
724         List<MatchInfoBase> matchInfoBaseList;
725         if (isSourceIpMacMatch) {
726             matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_SOURCE);
727         } else {
728             matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_DESTINATION);
729         }
730         matchInfoBaseList.addAll(flows);
731         return matchInfoBaseList;
732     }
733
734     private List<MatchInfoBase> addFlowMatchForAclId(Uuid remoteAclId, List<MatchInfoBase> flows) {
735         List<MatchInfoBase> matchInfoBaseList;
736         matchInfoBaseList = buildAclIdMetadataMatch(remoteAclId);
737         matchInfoBaseList.addAll(flows);
738         return matchInfoBaseList;
739     }
740
741     public static MatchInfoBase getMatchInfoByType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
742         for (MatchInfoBase mib : flows) {
743             if (type.isAssignableFrom(mib.getClass())) {
744                 return mib;
745             }
746         }
747         return null;
748     }
749
750     public static boolean containsMatchFieldType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
751         return getMatchInfoByType(flows, type) != null;
752     }
753
754     public static boolean containsTcpMatchField(List<MatchInfoBase> flows) {
755         return flows.contains(MatchIpProtocol.TCP);
756     }
757
758     public static boolean containsUdpMatchField(List<MatchInfoBase> flows) {
759         return flows.contains(MatchIpProtocol.UDP);
760     }
761
762     public static Integer allocateId(IdManagerService idManager, String poolName, String idKey, Integer defaultId) {
763         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
764         try {
765             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
766             RpcResult<AllocateIdOutput> rpcResult = result.get();
767             if (rpcResult.isSuccessful()) {
768                 Integer allocatedId = rpcResult.getResult().getIdValue().intValue();
769                 LOG.debug("Allocated ACL ID: {} with key: {} into pool: {}", allocatedId, idKey, poolName);
770                 return allocatedId;
771             } else {
772                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
773             }
774         } catch (InterruptedException | ExecutionException e) {
775             LOG.warn("Exception when getting Unique Id", e);
776         }
777         return defaultId;
778     }
779
780     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
781         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
782         try {
783             Future<RpcResult<Void>> result = idManager.releaseId(idInput);
784             RpcResult<Void> rpcResult = result.get();
785             if (!rpcResult.isSuccessful()) {
786                 LOG.warn("RPC Call to release Id {} with Key {} returned with Errors {}", idKey, rpcResult.getErrors());
787             } else {
788                 LOG.debug("Released ACL ID with key: {} from pool: {}", idKey, poolName);
789             }
790         } catch (InterruptedException | ExecutionException e) {
791             LOG.warn("Exception when releasing Id for key {}", idKey, e);
792         }
793     }
794
795     /**
796      * Allocate and save flow priority in cache.
797      *
798      * @param key the key
799      * @return the integer
800      */
801     public Integer allocateAndSaveFlowPriorityInCache(BigInteger dpId, short tableId, String key,
802                                                       PacketHandling packetHandling) {
803         String poolName = getAclPoolName(dpId, tableId, packetHandling);
804         Integer flowPriority = AclServiceUtils.allocateId(this.idManager, poolName, key,
805                 AclConstants.PROTO_MATCH_PRIORITY);
806         this.aclDataUtil.addAclFlowPriority(key, flowPriority);
807         return flowPriority;
808     }
809
810     /**
811      * Allocate acl id.
812      *
813      * @param key the key
814      */
815     public Integer allocateAclId(String key) {
816         Integer aclId = AclServiceUtils.allocateId(this.idManager, AclConstants.ACL_ID_POOL_NAME, key,
817                 AclConstants.INVALID_ACL_ID);
818         return aclId;
819     }
820
821     /**
822     * Allocate and save flow priority in cache.
823     *
824     * @param key the key
825     */
826     public void releaseAclId(String key) {
827         AclServiceUtils.releaseId(idManager, AclConstants.ACL_ID_POOL_NAME, key);
828     }
829
830     /**
831      * Release and remove flow priority from cache.
832      *
833      * @param key the key
834      * @return the integer
835      */
836     public Integer releaseAndRemoveFlowPriorityFromCache(BigInteger dpId, short tableId, String key,
837                                                          PacketHandling packetHandling) {
838         String poolName = getAclPoolName(dpId, tableId, packetHandling);
839         AclServiceUtils.releaseId(this.idManager, poolName, key);
840         Integer flowPriority = this.aclDataUtil.removeAclFlowPriority(key);
841         if (flowPriority == null) {
842             flowPriority = AclConstants.PROTO_MATCH_PRIORITY;
843         }
844         return flowPriority;
845     }
846
847     /**
848      * Indicates whether the interface has port security enabled.
849      * @param aclInterface the interface.
850      * @return true if port is security enabled.
851      */
852     public static boolean isOfInterest(AclInterface aclInterface) {
853         return aclInterface != null && aclInterface.getPortSecurityEnabled() != null
854                 && aclInterface.isPortSecurityEnabled();
855     }
856
857     /**
858      * Creates the id pool.
859      *
860      * @param poolName the pool name
861      */
862     public void createIdPool(String poolName, AclConstants.PacketHandlingType packetHandlingType) {
863         CreateIdPoolInput createPool = null;
864
865         // If the default behavior is Deny, then ACLs with Allow packetHandling must have lower priority than
866         // ACLs with Deny packetHandling - otherwise the Deny ACLs are redundant, and vice versa
867         if ((config.getDefaultBehavior() == DEFAULT_DENY
868                 && packetHandlingType == AclConstants.PacketHandlingType.PERMIT)
869                 || (config.getDefaultBehavior() == DEFAULT_ALLOW
870                     && packetHandlingType == AclConstants.PacketHandlingType.DENY)) {
871             createPool = new CreateIdPoolInputBuilder()
872                     .setPoolName(poolName).setLow(AclConstants.ACL_FLOW_PRIORITY_LOW_POOL_START)
873                     .setHigh(AclConstants.ACL_FLOW_PRIORITY_LOW_POOL_END).build();
874         } else if ((config.getDefaultBehavior() == DEFAULT_DENY
875                 && packetHandlingType == AclConstants.PacketHandlingType.DENY)
876                 || (config.getDefaultBehavior() == DEFAULT_ALLOW
877                     && packetHandlingType == AclConstants.PacketHandlingType.PERMIT)) {
878             createPool = new CreateIdPoolInputBuilder()
879                     .setPoolName(poolName).setLow(AclConstants.ACL_FLOW_PRIORITY_HIGH_POOL_START)
880                     .setHigh(AclConstants.ACL_FLOW_PRIORITY_HIGH_POOL_END).build();
881         } else {
882             LOG.error("Got unexpected PacketHandling {} combined with default behavior {}, skipping creation"
883                     + "of pool {}", packetHandlingType, config.getDefaultBehavior(), poolName);
884             return;
885         }
886         try {
887             Future<RpcResult<Void>> result = this.idManager.createIdPool(createPool);
888             if ((result != null) && (result.get().isSuccessful())) {
889                 LOG.debug("Created IdPool for {}", poolName);
890             }
891         } catch (InterruptedException | ExecutionException e) {
892             LOG.error("Failed to create ID pool [{}] for ACL flow priority", poolName, e);
893             throw new RuntimeException("Failed to create ID pool for ACL flow priority", e);
894         }
895     }
896
897     /**
898      * Creates the id pool.
899      *
900      * @param poolName the pool name
901      */
902     private void createIdPoolForAclId(String poolName) {
903         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
904                 .setPoolName(poolName).setLow(AclConstants.ACL_ID_METADATA_POOL_START)
905                 .setHigh(AclConstants.ACL_ID_METADATA_POOL_END).build();
906         try {
907             Future<RpcResult<Void>> result = this.idManager.createIdPool(createPool);
908             if ((result != null) && (result.get().isSuccessful())) {
909                 LOG.debug("Created IdPool for {}", poolName);
910             }
911         } catch (InterruptedException | ExecutionException e) {
912             LOG.error("Failed to create ID pool [{}] for remote ACL ids", poolName, e);
913             throw new RuntimeException("Failed to create ID pool [{}] for remote ACL ids", e);
914         }
915     }
916
917     /**
918      * Delete id pool.
919      *
920      * @param poolName the pool name
921      */
922     public void deleteIdPool(String poolName) {
923         DeleteIdPoolInput deletePool = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
924         try {
925             Future<RpcResult<Void>> result = this.idManager.deleteIdPool(deletePool);
926             if ((result != null) && (result.get().isSuccessful())) {
927                 LOG.debug("Deleted IdPool for {}", poolName);
928             }
929         } catch (InterruptedException | ExecutionException e) {
930             LOG.error("Failed to delete ID pool [{}]", poolName, e);
931             throw new RuntimeException("Failed to delete ID pool [" + poolName + "]", e);
932         }
933     }
934
935     /**
936      * Gets the acl pool name.
937      *
938      * @param dpId the dp id
939      * @param tableId the table id
940      * @param packetHandlingType packet handling type
941      * @return the acl pool name
942      */
943     public static String getAclPoolName(BigInteger dpId, short tableId,
944                                         AclConstants.PacketHandlingType packetHandlingType) {
945         return AclConstants.ACL_FLOW_PRIORITY_POOL_NAME + "." + dpId + "." + tableId + "." + packetHandlingType;
946     }
947
948     /**
949      * Gets the acl pool name.
950      *
951      * @param dpId the dp id
952      * @param tableId the table id
953      * @param packetHandling packet handling type
954      * @return the acl pool name
955      */
956     public static String getAclPoolName(BigInteger dpId, short tableId, PacketHandling packetHandling) {
957         return packetHandling instanceof Permit
958                 ? getAclPoolName(dpId, tableId, AclConstants.PacketHandlingType.PERMIT)
959                 : getAclPoolName(dpId, tableId, AclConstants.PacketHandlingType.DENY);
960     }
961
962     /**
963      * Creates the acl id pools.
964      *
965      * @param dpId the dp id
966      */
967     public void createAclIdPools(BigInteger dpId) {
968         createIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
969                 AclConstants.PacketHandlingType.PERMIT), AclConstants.PacketHandlingType.PERMIT);
970         createIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
971                 AclConstants.PacketHandlingType.DENY), AclConstants.PacketHandlingType.DENY);
972         createIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
973                 AclConstants.PacketHandlingType.PERMIT), AclConstants.PacketHandlingType.PERMIT);
974         createIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
975                 AclConstants.PacketHandlingType.DENY), AclConstants.PacketHandlingType.DENY);
976     }
977
978     /**
979      * Creates remote the acl id pools.
980      */
981     public void createRemoteAclIdPool() {
982         createIdPoolForAclId(AclConstants.ACL_ID_POOL_NAME);
983     }
984
985     /**
986      * Delete remote the acl id pools.
987      */
988     public void deleteRemoteAclIdPool() {
989         deleteIdPool(AclConstants.ACL_ID_POOL_NAME);
990     }
991
992     /**
993      * Delete acl id pools.
994      *
995      * @param dpId the dp id
996      */
997     public void deleteAclIdPools(BigInteger dpId) {
998         deleteIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
999                 AclConstants.PacketHandlingType.PERMIT));
1000         deleteIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE,
1001                 AclConstants.PacketHandlingType.DENY));
1002         deleteIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
1003                 AclConstants.PacketHandlingType.PERMIT));
1004         deleteIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE,
1005                 AclConstants.PacketHandlingType.DENY));
1006     }
1007
1008     public static List<? extends MatchInfoBase> buildIpAndSrcServiceMatch(long elanTag, AllowedAddressPairs ip,
1009             DataBroker dataBroker, Long vpnId) {
1010         List<MatchInfoBase> flowMatches = new ArrayList<>();
1011         MatchMetadata metadatMatch = null;
1012         if (vpnId == null) {
1013             metadatMatch =
1014                     new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE);
1015         } else {
1016             metadatMatch =
1017                     new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID);
1018         }
1019         flowMatches.add(metadatMatch);
1020         if (ip.getIpAddress().getIpAddress() != null) {
1021             if (ip.getIpAddress().getIpAddress().getIpv4Address() != null) {
1022                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1023                 flowMatches.add(ipv4EthMatch);
1024                 MatchIpv4Source srcMatch = new MatchIpv4Source(
1025                         new Ipv4Prefix(ip.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
1026                 flowMatches.add(srcMatch);
1027             } else if (ip.getIpAddress().getIpAddress().getIpv6Address() != null) {
1028                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1029                 flowMatches.add(ipv6EthMatch);
1030                 MatchIpv6Source srcMatch = new MatchIpv6Source(
1031                         new Ipv6Prefix(ip.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
1032                 flowMatches.add(srcMatch);
1033             }
1034         } else if (ip.getIpAddress().getIpPrefix() != null) {
1035             if (ip.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
1036                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1037                 flowMatches.add(ipv4EthMatch);
1038                 MatchIpv4Source srcMatch = new MatchIpv4Source(ip.getIpAddress().getIpPrefix().getIpv4Prefix());
1039                 flowMatches.add(srcMatch);
1040             } else if (ip.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
1041                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1042                 flowMatches.add(ipv6EthMatch);
1043                 MatchIpv6Source srcMatch = new MatchIpv6Source(ip.getIpAddress().getIpPrefix().getIpv6Prefix());
1044                 flowMatches.add(srcMatch);
1045             }
1046         }
1047         return flowMatches;
1048     }
1049
1050     public static List<? extends MatchInfoBase> buildIpAndDstServiceMatch(Long elanTag, AllowedAddressPairs ip,
1051             DataBroker dataBroker, Long vpnId) {
1052         List<MatchInfoBase> flowMatches = new ArrayList<>();
1053         MatchMetadata metadatMatch = null;
1054         if (vpnId == null) {
1055             metadatMatch =
1056                     new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE);
1057         } else {
1058             metadatMatch =
1059                     new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID);
1060         }
1061         flowMatches.add(metadatMatch);
1062
1063         if (ip.getIpAddress().getIpAddress() != null) {
1064             if (ip.getIpAddress().getIpAddress().getIpv4Address() != null) {
1065                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1066                 flowMatches.add(ipv4EthMatch);
1067                 MatchIpv4Destination dstMatch = new MatchIpv4Destination(
1068                         new Ipv4Prefix(ip.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
1069                 flowMatches.add(dstMatch);
1070             } else if (ip.getIpAddress().getIpAddress().getIpv6Address() != null) {
1071                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1072                 flowMatches.add(ipv6EthMatch);
1073                 MatchIpv6Destination dstMatch = new MatchIpv6Destination(
1074                         new Ipv6Prefix(ip.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
1075                 flowMatches.add(dstMatch);
1076             }
1077         } else if (ip.getIpAddress().getIpPrefix() != null) {
1078             if (ip.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
1079                 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1080                 flowMatches.add(ipv4EthMatch);
1081                 MatchIpv4Destination dstMatch =
1082                         new MatchIpv4Destination(ip.getIpAddress().getIpPrefix().getIpv4Prefix());
1083                 flowMatches.add(dstMatch);
1084             } else if (ip.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
1085                 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1086                 flowMatches.add(ipv6EthMatch);
1087                 MatchIpv6Destination dstMatch =
1088                         new MatchIpv6Destination(ip.getIpAddress().getIpPrefix().getIpv6Prefix());
1089                 flowMatches.add(dstMatch);
1090             }
1091         }
1092         return flowMatches;
1093     }
1094
1095     public static boolean exactlyOneAcl(AclInterface port) {
1096         return (port.getSecurityGroups() != null) && (port.getSecurityGroups().size() == 1);
1097     }
1098
1099     public static boolean isOfAclInterest(Acl acl) {
1100         List<Ace> aceList = acl.getAccessListEntries().getAce();
1101         if ((aceList != null) && !aceList.isEmpty()) {
1102             return (aceList.get(0).getAugmentation(SecurityRuleAttr.class) != null);
1103         }
1104         return false;
1105     }
1106
1107     public static void addLportTagMetadataMatch(int lportTag, List<MatchInfoBase> flowMatches,
1108             Class<? extends ServiceModeBase> serviceMode) {
1109         MatchInfoBase lportMatch = buildLPortTagMatch(lportTag, serviceMode);
1110         InterfaceServiceUtil.mergeMetadataMatchsOrAdd(flowMatches, lportMatch);
1111     }
1112
1113     static AclInterface buildAclInterfaceState(String interfaceId, InterfaceAcl aclInPort) {
1114         AclInterface aclInterface = new AclInterface();
1115         aclInterface.setInterfaceId(interfaceId);
1116         aclInterface.setPortSecurityEnabled(aclInPort.isPortSecurityEnabled());
1117         aclInterface.setSecurityGroups(aclInPort.getSecurityGroups());
1118         aclInterface.setAllowedAddressPairs(aclInPort.getAllowedAddressPairs());
1119         return aclInterface;
1120     }
1121 }