Optional clean-up
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / utils / AclServiceUtils.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.aclservice.utils;
10
11 import com.google.common.base.Optional;
12 import com.googlecode.ipv6.IPv6Address;
13 import com.googlecode.ipv6.IPv6NetworkMask;
14
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.Future;
24
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchFieldType;
34 import org.opendaylight.genius.mdsalutil.MatchInfo;
35 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
36 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
37 import org.opendaylight.genius.mdsalutil.NwConstants;
38 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
39 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
40 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
41 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
42 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
88 import org.opendaylight.yangtools.yang.binding.DataObject;
89 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
90 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
91 import org.opendaylight.yangtools.yang.common.RpcResult;
92 import org.slf4j.Logger;
93 import org.slf4j.LoggerFactory;
94
95 @Singleton
96 @SuppressWarnings("deprecation")
97 public final class AclServiceUtils {
98
99     private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
100
101     private final AclDataUtil aclDataUtil;
102     private final AclserviceConfig config;
103
104     @Inject
105     public AclServiceUtils(AclDataUtil aclDataUtil, AclserviceConfig config) {
106         super();
107         this.aclDataUtil = aclDataUtil;
108         this.config = config;
109     }
110
111     /**
112      * Retrieves the Interface from the datastore.
113      * @param broker the data broker
114      * @param interfaceName the interface name
115      * @return the interface.
116      */
117     public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
118         .Interface> getInterface(DataBroker broker, String interfaceName) {
119         return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
120     }
121
122     /**
123      * Builds the interface identifier.
124      * @param interfaceName the interface name.
125      * @return the interface identifier.
126      */
127     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
128         .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
129         return InstanceIdentifier.builder(Interfaces.class)
130                 .child(
131                     org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
132                     .Interface.class, new InterfaceKey(interfaceName)).build();
133     }
134
135     /**
136      * Retrieves the object from the datastore.
137      * @param broker the data broker.
138      * @param datastoreType the data store type.
139      * @param path the wild card path.
140      * @param <T> type of DataObject
141      * @return the required object.
142      */
143     public static <T extends DataObject> Optional<T> read(
144             DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
145
146         Optional<T> result = Optional.absent();
147         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
148         try {
149             result = tx.read(datastoreType, path).checkedGet();
150         } catch (ReadFailedException e) {
151             LOG.warn("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
152         } finally {
153             tx.close();
154         }
155         return result;
156     }
157
158     /**
159      * Retrieves the acl matching the key from the data store.
160      *
161      * @param broker the data broker
162      * @param aclKey the acl key
163      * @return the acl
164      */
165     public static Acl getAcl(DataBroker broker, String aclKey) {
166         return read(broker, LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey)).orNull();
167     }
168
169     /** Creates the Acl instance identifier.
170      *
171      * @param aclKey the acl key
172      * @return the instance identifier
173      */
174     public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
175         return InstanceIdentifier
176                 .builder(AccessLists.class)
177                 .child(Acl.class,
178                         new AclKey(aclKey,Ipv4Acl.class))
179                 .build();
180     }
181
182     /**
183      * Get the data path number for the interface.
184      * @param interfaceManagerRpcService interfaceManagerRpcService instance.
185      * @param ifName the interface name.
186      * @return the dpn.
187      */
188     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
189         BigInteger nodeId = BigInteger.ZERO;
190         try {
191             GetDpidFromInterfaceInput dpIdInput =
192                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
193             Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
194                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
195             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
196             if (dpIdResult.isSuccessful()) {
197                 nodeId = dpIdResult.getResult().getDpid();
198             } else {
199                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
200             }
201         } catch (NullPointerException | InterruptedException | ExecutionException e) {
202             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
203         }
204         return nodeId;
205     }
206
207     /**
208      * Retrieves the interface state.
209      * @param dataBroker the data broker.
210      * @param interfaceName the interface name.
211      * @return the interface state.
212      */
213     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
214         .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
215         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
216             .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
217         return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
218     }
219
220     /**
221      * Build the interface state.
222      * @param interfaceName the interface name.
223      * @return the interface state.
224      */
225     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
226         .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
227         InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
228             .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
229             .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
230             .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
231             .rev140508.interfaces.state.InterfaceKey(interfaceName));
232         return idBuilder.build();
233     }
234
235     /**
236      * Checks whether port security is enabled for the port.
237      * @param port the port.
238      * @return the port security is enabled/not.
239      */
240     public static boolean isPortSecurityEnabled(AclInterface port) {
241         return port.isPortSecurityEnabled();
242     }
243
244     /**
245      * Checks whether port security is enabled for the port.
246      * @param port the port.
247      * @return the list of security groups.
248      */
249     public static List<Uuid> getInterfaceAcls(Interface port) {
250         if (port == null) {
251             LOG.error("Port is Null");
252             return null;
253         }
254         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
255         if (aclInPort == null) {
256             LOG.error("getSecurityGroupInPortList: no security group associated}",
257                 port.getName());
258             return null;
259         }
260         return aclInPort.getSecurityGroups();
261     }
262
263     /**
264      * Retrieves the security rule attribute augmentation from the access list.
265      * @param ace the access list entry
266      * @return the security rule attributes
267      */
268     public static SecurityRuleAttr  getAccesssListAttributes(Ace ace) {
269         if (ace == null) {
270             LOG.error("Ace is Null");
271             return null;
272         }
273         SecurityRuleAttr aceAttributes = ace.getAugmentation(SecurityRuleAttr.class);
274         if (aceAttributes == null) {
275             LOG.error("Ace is null");
276             return null;
277         }
278         return aceAttributes;
279     }
280
281     /**
282      * Returns the DHCP match.
283      *
284      * @param srcPort the source port.
285      * @param dstPort the destination port.
286      * @param lportTag the lport tag
287      * @return list of matches.
288      */
289     public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag) {
290         List<MatchInfoBase> matches = new ArrayList<>(6);
291         matches.add(new MatchInfo(MatchFieldType.eth_type,
292                 new long[] { NwConstants.ETHTYPE_IPV4 }));
293         matches.add(new MatchInfo(MatchFieldType.ip_proto,
294                 new long[] { IPProtocols.UDP.intValue() }));
295         matches.add(new MatchInfo(MatchFieldType.udp_dst,
296                 new long[] { dstPort }));
297         matches.add(new MatchInfo(MatchFieldType.udp_src,
298                 new long[] { srcPort}));
299         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
300         return matches;
301     }
302
303     /**
304      * Returns the DHCPv6 match.
305      *
306      * @param srcPort the source port.
307      * @param dstPort the destination port.
308      * @param lportTag the lport tag
309      * @return list of matches.
310      */
311     public static List<MatchInfoBase> buildDhcpV6Matches(int srcPort, int dstPort, int lportTag) {
312         List<MatchInfoBase> matches = new ArrayList<>(6);
313         matches.add(new MatchInfo(MatchFieldType.eth_type,
314                 new long[] { NwConstants.ETHTYPE_IPV6 }));
315         matches.add(new MatchInfo(MatchFieldType.ip_proto,
316                 new long[] { IPProtocols.UDP.intValue() }));
317         matches.add(new MatchInfo(MatchFieldType.udp_dst,
318                 new long[] { dstPort }));
319         matches.add(new MatchInfo(MatchFieldType.udp_src,
320                 new long[] { srcPort}));
321         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
322         return matches;
323     }
324
325     /**
326      * Returns the ICMPv6 match.
327      *
328      * @param icmpType the icmpv6-type.
329      * @param icmpCode the icmpv6-code.
330      * @param lportTag the lport tag
331      * @return list of matches.
332      */
333     public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag) {
334         List<MatchInfoBase> matches = new ArrayList<>(6);
335         matches.add(new MatchInfo(MatchFieldType.eth_type,
336                 new long[] { NwConstants.ETHTYPE_IPV6 }));
337         matches.add(new MatchInfo(MatchFieldType.ip_proto,
338                 new long[] { IPProtocols.IPV6ICMP.intValue() }));
339         if (icmpType != 0) {
340             matches.add(new MatchInfo(MatchFieldType.icmp_v6,
341                     new long[] { icmpType, icmpCode}));
342         }
343         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag));
344         return matches;
345     }
346
347     /**
348      * Builds the service id.
349      *
350      * @param interfaceName the interface name
351      * @param serviceIndex the service index
352      * @param serviceMode the service mode
353      * @return the instance identifier
354      */
355     public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
356             Class<? extends ServiceModeBase> serviceMode) {
357         return InstanceIdentifier.builder(ServiceBindings.class)
358                 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
359                 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
360     }
361
362     /**
363      * Gets the bound services.
364      *
365      * @param serviceName the service name
366      * @param servicePriority the service priority
367      * @param flowPriority the flow priority
368      * @param cookie the cookie
369      * @param instructions the instructions
370      * @return the bound services
371      */
372     public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
373             BigInteger cookie, List<Instruction> instructions) {
374         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
375                 .setInstruction(instructions);
376         return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
377                 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
378                 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
379     }
380
381     public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
382         if (updatedAclList == null) {
383             return null;
384         }
385         List<Uuid> newAclList = new ArrayList<>(updatedAclList);
386         if (currentAclList == null) {
387             return newAclList;
388         }
389         List<Uuid> origAclList = new ArrayList<>(currentAclList);
390         for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
391             Uuid updatedAclUuid = iterator.next();
392             for (Uuid currentAclUuid :origAclList) {
393                 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
394                     iterator.remove();
395                 }
396             }
397         }
398         return newAclList;
399     }
400
401     public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
402             List<AllowedAddressPairs> updatedAllowedAddressPairs,
403             List<AllowedAddressPairs> currentAllowedAddressPairs) {
404         if (updatedAllowedAddressPairs == null) {
405             return null;
406         }
407         List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
408         if (currentAllowedAddressPairs == null) {
409             return newAllowedAddressPairs;
410         }
411         List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
412         for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
413             AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
414             for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
415                 if (updatedAllowedAddressPair.getKey().equals(currentAllowedAddressPair.getKey())) {
416                     iterator.remove();
417                     break;
418                 }
419             }
420         }
421         return newAllowedAddressPairs;
422     }
423
424     public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
425         if (port == null) {
426             LOG.error("Port is Null");
427             return null;
428         }
429         InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
430         if (aclInPort == null) {
431             LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
432             return null;
433         }
434         return aclInPort.getAllowedAddressPairs();
435     }
436
437     public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
438             .interfaces.rev140508.interfaces.state.Interface interfaceState) {
439         BigInteger dpId = null;
440         List<String> ofportIds = interfaceState.getLowerLayerIf();
441         if (ofportIds != null && !ofportIds.isEmpty()) {
442             NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
443             dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
444         }
445         return dpId;
446     }
447
448     /**
449      * Builds the ip matches.
450      *
451      * @param ipPrefixOrAddress the ip prefix or address
452      * @param matchCriteria the source_ip or destination_ip used for the match
453      * @return the list
454      */
455     public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
456                                                      MatchCriteria matchCriteria) {
457         List<MatchInfoBase> flowMatches = new ArrayList<>();
458         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
459         MatchFieldType matchFieldType;
460         if (ipPrefix != null) {
461             if (ipPrefix.getIpv4Prefix() != null) {
462                 flowMatches.add(new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV4}));
463                 String[] ipaddressValues = ipPrefix.getIpv4Prefix().getValue().split("/");
464                 matchFieldType = matchCriteria == MatchCriteria.MATCH_SOURCE
465                         ? MatchFieldType.ipv4_source : MatchFieldType.ipv4_destination;
466                 flowMatches.add(new MatchInfo(matchFieldType, new String[] {ipaddressValues[0], ipaddressValues[1]}));
467             } else {
468                 matchFieldType = matchCriteria == MatchCriteria.MATCH_SOURCE
469                         ? MatchFieldType.ipv6_source : MatchFieldType.ipv6_destination;
470                 String[] ipv6addressValues = ipPrefix.getIpv6Prefix().getValue().split("/");
471                 IPv6Address ipv6Address = IPv6Address.fromString(ipv6addressValues[0]);
472                 IPv6Address maskedV6Address = ipv6Address.maskWithNetworkMask(
473                         IPv6NetworkMask.fromPrefixLength(Integer.parseInt(ipv6addressValues[1])));
474                 flowMatches.add(new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV6}));
475                 flowMatches.add(new MatchInfo(matchFieldType,
476                         new String[] {maskedV6Address.toString() + "/" + ipv6addressValues[1]}));
477             }
478         } else {
479             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
480             if (ipAddress.getIpv4Address() != null) {
481                 matchFieldType = matchCriteria == MatchCriteria.MATCH_SOURCE
482                         ? MatchFieldType.ipv4_source : MatchFieldType.ipv4_destination;
483                 flowMatches.add(new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV4}));
484                 flowMatches.add(new MatchInfo(matchFieldType,
485                         new String[] {ipAddress.getIpv4Address().getValue(), "32"}));
486             } else {
487                 matchFieldType = matchCriteria == MatchCriteria.MATCH_SOURCE
488                         ? MatchFieldType.ipv6_source : MatchFieldType.ipv6_destination;
489                 flowMatches.add(new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV6}));
490                 flowMatches.add(new MatchInfo(matchFieldType,
491                         new String[] {ipAddress.getIpv6Address().getValue() + "/128" }));
492             }
493         }
494         return flowMatches;
495     }
496
497     /**
498      * Gets the lport tag match.
499      *
500      * @param lportTag the lport tag
501      * @return the lport tag match
502      */
503     public static MatchInfo buildLPortTagMatch(int lportTag) {
504         return new MatchInfo(MatchFieldType.metadata,
505                 new BigInteger[] {MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG});
506     }
507
508     public static List<Ace> getAceWithRemoteAclId(DataBroker dataBroker, AclInterface port, Uuid remoteAcl) {
509         List<Ace> remoteAclRuleList = new ArrayList<>();
510         List<Uuid> aclList = port.getSecurityGroups();
511         for (Uuid aclId : aclList) {
512             Acl acl = getAcl(dataBroker, aclId.getValue());
513             List<Ace> aceList = acl.getAccessListEntries().getAce();
514             for (Ace ace : aceList) {
515                 Uuid tempRemoteAcl = getAccesssListAttributes(ace).getRemoteGroupId();
516                 if (tempRemoteAcl != null && tempRemoteAcl.equals(remoteAcl)) {
517                     remoteAclRuleList.add(ace);
518                 }
519             }
520         }
521         return remoteAclRuleList;
522     }
523
524     public Map<String, List<MatchInfoBase>> getFlowForRemoteAcl(Uuid remoteAclId, String ignoreInterfaceId,
525                                                                        Map<String, List<MatchInfoBase>>
526                                                                                flowMatchesMap, boolean
527                                                                                isSourceIpMacMatch) {
528         List<AclInterface> interfaceList = aclDataUtil.getInterfaceList(remoteAclId);
529         if (flowMatchesMap == null || interfaceList == null || interfaceList.isEmpty()) {
530             return null;
531         }
532         Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
533         MatchInfoBase ipv4Match = new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV4});
534         MatchInfoBase ipv6Match = new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV6});
535         for (String flowName : flowMatchesMap.keySet()) {
536             List<MatchInfoBase> flows = flowMatchesMap.get(flowName);
537             for (AclInterface port : interfaceList) {
538                 if (port.getInterfaceId().equals(ignoreInterfaceId)) {
539                     continue;
540                 }
541                 //get allow address pair
542                 List<AllowedAddressPairs> allowedAddressPair = port.getAllowedAddressPairs();
543                 // iterate over allow address pair and update match type
544                 for (AllowedAddressPairs aap : allowedAddressPair) {
545                     List<MatchInfoBase> matchInfoBaseList;
546                     String flowId;
547                     if (flows.contains(ipv4Match) && isIPv4Address(aap)) {
548                         matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
549                         flowId = flowName + "_ipv4_remoteACL_interface_aap_" + aap.getKey();
550                         updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
551                     } else if (flows.contains(ipv6Match) && !isIPv4Address(aap)) {
552                         matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
553                         flowId = flowName + "_ipv6_remoteACL_interface_aap_" +  aap.getKey();
554                         updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
555                     }
556                 }
557
558             }
559
560         }
561         return updatedFlowMatchesMap;
562     }
563
564     public AclserviceConfig getConfig() {
565         return config;
566     }
567
568     private static boolean isIPv4Address(AllowedAddressPairs aap) {
569         IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
570         IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
571         if (ipPrefix != null) {
572             if (ipPrefix.getIpv4Prefix() != null) {
573                 return true;
574             }
575         } else {
576             IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
577             if (ipAddress.getIpv4Address() != null) {
578                 return true;
579             }
580         }
581         return false;
582     }
583
584     public static Map<String, List<MatchInfoBase>> getFlowForAllowedAddresses(List<AllowedAddressPairs>
585                                                                                       syncAllowedAddresses,
586                                                                               Map<String, List<MatchInfoBase>>
587                                                                                       flowMatchesMap, boolean
588                                                                                       isSourceIpMacMatch) {
589         if (flowMatchesMap == null) {
590             return null;
591         }
592         Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
593         MatchInfoBase ipv4Match = new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV4});
594         MatchInfoBase ipv6Match = new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_IPV6});
595         for (String flowName : flowMatchesMap.keySet()) {
596             List<MatchInfoBase> flows = flowMatchesMap.get(flowName);
597             // iterate over allow address pair and update match type
598             for (AllowedAddressPairs aap : syncAllowedAddresses) {
599                 List<MatchInfoBase> matchInfoBaseList;
600                 String flowId;
601                 if (flows.contains(ipv4Match) && isIPv4Address(aap)) {
602                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
603                     flowId = flowName + "_ipv4_remoteACL_interface_aap_" + aap.getKey();
604                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
605                 } else if (flows.contains(ipv6Match) && !isIPv4Address(aap)) {
606                     matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
607                     flowId = flowName + "_ipv6_remoteACL_interface_aap_" + aap.getKey();
608                     updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
609                 }
610             }
611
612         }
613         return updatedFlowMatchesMap;
614     }
615
616     public static Long getElanIdFromInterface(String elanInterfaceName,DataBroker broker) {
617         ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
618         if (null != elanInterface) {
619             ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
620             return elanInfo.getElanTag();
621         }
622         return null;
623     }
624
625     public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
626         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
627         return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
628     }
629
630     public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
631         return InstanceIdentifier.builder(ElanInterfaces.class)
632                 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
633     }
634
635     // elan-instances config container
636     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
637         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
638         return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
639     }
640
641     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
642         return InstanceIdentifier.builder(ElanInstances.class)
643                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
644     }
645
646     private static List<MatchInfoBase> updateAAPMatches(boolean isSourceIpMacMatch, List<MatchInfoBase> flows,
647                                                         AllowedAddressPairs aap) {
648         List<MatchInfoBase> matchInfoBaseList;
649         if (isSourceIpMacMatch) {
650             matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_SOURCE);
651         } else {
652             matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_DESTINATION);
653         }
654         matchInfoBaseList.addAll(flows);
655         return matchInfoBaseList;
656     }
657
658     public static MatchInfoBase popMatchInfoByType(List<MatchInfoBase> flows, MatchFieldType type) {
659         MatchInfoBase mib = getMatchInfoByType(flows, type);
660         if (mib != null) {
661             flows.remove(mib);
662         }
663         return mib;
664     }
665
666     public static MatchInfo getMatchInfoByType(List<MatchInfoBase> flows, MatchFieldType type) {
667         for (MatchInfoBase mib : flows) {
668             if (mib instanceof MatchInfo) {
669                 if (((MatchInfo)mib).getMatchField() == type) {
670                     return (MatchInfo) mib;
671                 }
672             }
673         }
674         return null;
675     }
676
677     public static MatchInfoBase getMatchInfoByType(List<MatchInfoBase> flows, NxMatchFieldType type) {
678         for (MatchInfoBase mib : flows) {
679             if (mib instanceof NxMatchInfo) {
680                 if (((NxMatchInfo)mib).getMatchField() == type) {
681                     return mib;
682                 }
683             }
684         }
685         return null;
686     }
687
688     public static boolean containsMatchFieldType(List<MatchInfoBase> flows, MatchFieldType type) {
689         MatchInfoBase mib = getMatchInfoByType(flows, type);
690         if (mib != null) {
691             return true;
692         }
693         return false;
694     }
695
696     public static boolean containsMatchFieldType(List<MatchInfoBase> flows, NxMatchFieldType type) {
697         MatchInfoBase mib = getMatchInfoByType(flows, type);
698         if (mib != null) {
699             return true;
700         }
701         return false;
702     }
703
704     public static boolean containsMatchFieldTypeAndValue(List<MatchInfoBase> flows, MatchFieldType type,
705             long[] values) {
706         MatchInfo mib = getMatchInfoByType(flows, type);
707         if (mib != null && Arrays.equals(mib.getMatchValues(), values)) {
708             return true;
709         }
710
711         return false;
712     }
713
714     public static boolean containsTcpMatchField(List<MatchInfoBase> flows) {
715         return containsMatchFieldTypeAndValue(flows, MatchFieldType.ip_proto, new long[] {IPProtocols.TCP.intValue()});
716     }
717
718     public static boolean containsUdpMatchField(List<MatchInfoBase> flows) {
719         return containsMatchFieldTypeAndValue(flows, MatchFieldType.ip_proto, new long[] {IPProtocols.UDP.intValue()});
720     }
721
722     public static Integer allocateId(IdManagerService idManager, String poolName, String idKey) {
723         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
724         try {
725             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
726             RpcResult<AllocateIdOutput> rpcResult = result.get();
727             if (rpcResult.isSuccessful()) {
728                 return rpcResult.getResult().getIdValue().intValue();
729             } else {
730                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
731             }
732         } catch (InterruptedException | ExecutionException e) {
733             LOG.warn("Exception when getting Unique Id", e);
734         }
735         return AclConstants.PROTO_MATCH_PRIORITY;
736     }
737
738     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
739         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
740         try {
741             Future<RpcResult<Void>> result = idManager.releaseId(idInput);
742             RpcResult<Void> rpcResult = result.get();
743             if (!rpcResult.isSuccessful()) {
744                 LOG.warn("RPC Call to release Id {} with Key {} returned with Errors {}", idKey, rpcResult.getErrors());
745             }
746         } catch (InterruptedException | ExecutionException e) {
747             LOG.warn("Exception when releasing Id for key {}", idKey, e);
748         }
749     }
750
751     /**
752      * Indicates whether the interface has port security enabled.
753      * @param aclInterface the interface.
754      * @return true if port is security enabled.
755      */
756     public static boolean isOfInterest(AclInterface aclInterface) {
757         return aclInterface != null && aclInterface.getPortSecurityEnabled() != null
758                 && aclInterface.isPortSecurityEnabled();
759     }
760 }