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