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