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