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