2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.aclservice.utils;
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Lists;
13 import com.google.common.net.InetAddresses;
14 import com.google.common.util.concurrent.CheckedFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.List;
24 import java.util.Map.Entry;
26 import java.util.SortedSet;
27 import java.util.TreeSet;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.Future;
30 import javax.inject.Inject;
31 import javax.inject.Singleton;
32 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
33 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
34 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
36 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
37 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
38 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
39 import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil;
40 import org.opendaylight.genius.mdsalutil.ActionInfo;
41 import org.opendaylight.genius.mdsalutil.InstructionInfo;
42 import org.opendaylight.genius.mdsalutil.MDSALUtil;
43 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
44 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
45 import org.opendaylight.genius.mdsalutil.NwConstants;
46 import org.opendaylight.genius.mdsalutil.NxMatchInfo;
47 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
48 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
49 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
50 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
51 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
52 import org.opendaylight.genius.mdsalutil.matches.MatchArpSpa;
53 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
54 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
55 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
56 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
57 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
58 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
59 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Destination;
60 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source;
61 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
62 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
63 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
64 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
65 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
66 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
67 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
68 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
74 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;
75 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;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
80 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
82 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclPortsLookup;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.PortsSubnetIpPrefixes;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIp;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIpKey;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixes;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixesKey;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIds;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsKey;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixes;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.ports.subnet.ip.prefixes.PortSubnetIpPrefixesKey;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
137 import org.opendaylight.yangtools.yang.binding.DataObject;
138 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
139 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
140 import org.opendaylight.yangtools.yang.common.RpcResult;
141 import org.slf4j.Logger;
142 import org.slf4j.LoggerFactory;
145 public final class AclServiceUtils {
147 private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
148 public static final AclserviceConfig.DefaultBehavior DEFAULT_DENY = AclserviceConfig.DefaultBehavior.Deny;
149 public static final AclserviceConfig.DefaultBehavior DEFAULT_ALLOW = AclserviceConfig.DefaultBehavior.Allow;
151 private final AclDataUtil aclDataUtil;
152 private final AclserviceConfig config;
153 private final IdManagerService idManager;
156 public AclServiceUtils(AclDataUtil aclDataUtil, AclserviceConfig config, IdManagerService idManager) {
157 this.aclDataUtil = aclDataUtil;
158 this.config = config;
159 this.idManager = idManager;
163 * Retrieves the Interface from the datastore.
164 * @param broker the data broker
165 * @param interfaceName the interface name
166 * @return the interface.
168 public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
169 .Interface> getInterface(DataBroker broker, String interfaceName) {
170 return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
174 * Builds the interface identifier.
175 * @param interfaceName the interface name.
176 * @return the interface identifier.
178 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
179 .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
180 return InstanceIdentifier.builder(Interfaces.class)
182 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
183 .Interface.class, new InterfaceKey(interfaceName)).build();
187 * Retrieves the object from the datastore.
188 * @param broker the data broker.
189 * @param datastoreType the data store type.
190 * @param path the wild card path.
191 * @param <T> type of DataObject
192 * @return the required object.
194 public static <T extends DataObject> Optional<T> read(
195 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
196 try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
197 return tx.read(datastoreType, path).checkedGet();
198 } catch (ReadFailedException e) {
199 LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
200 return Optional.absent();
205 * Retrieves the acl matching the key from the data store.
207 * @param broker the data broker
208 * @param aclKey the acl key
211 public static Acl getAcl(DataBroker broker, String aclKey) {
212 return read(broker, LogicalDatastoreType.CONFIGURATION, getAclInstanceIdentifier(aclKey)).orNull();
215 /** Creates the Acl instance identifier.
217 * @param aclKey the acl key
218 * @return the instance identifier
220 public static InstanceIdentifier<Acl> getAclInstanceIdentifier(String aclKey) {
221 return InstanceIdentifier.builder(AccessLists.class).child(Acl.class, new AclKey(aclKey, Ipv4Acl.class))
226 * Get the data path number for the interface.
227 * @param interfaceManagerRpcService interfaceManagerRpcService instance.
228 * @param ifName the interface name.
231 public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
232 BigInteger nodeId = BigInteger.ZERO;
234 GetDpidFromInterfaceInput dpIdInput =
235 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
236 Future<RpcResult<GetDpidFromInterfaceOutput>> dpIdOutput =
237 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
238 RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
239 if (dpIdResult.isSuccessful()) {
240 nodeId = dpIdResult.getResult().getDpid();
242 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
244 } catch (NullPointerException | InterruptedException | ExecutionException e) {
245 LOG.error("Exception when getting dpn for interface {}", ifName, e);
251 * Retrieves the interface state.
252 * @param dataBroker the data broker.
253 * @param interfaceName the interface name.
254 * @return the interface state.
256 public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
257 .Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
258 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
259 .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
260 return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
264 * Build the interface state.
265 * @param interfaceName the interface name.
266 * @return the interface state.
268 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
269 .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
270 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
271 .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
272 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
273 .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
274 .rev140508.interfaces.state.InterfaceKey(interfaceName));
275 return idBuilder.build();
279 * Checks whether port security is enabled for the port.
280 * @param port the port.
281 * @return the port security is enabled/not.
283 public static boolean isPortSecurityEnabled(AclInterface port) {
284 return port.isPortSecurityEnabled();
288 * Checks whether port security is enabled for the port.
289 * @param port the port.
290 * @return the list of security groups.
292 public static List<Uuid> getInterfaceAcls(Interface port) {
294 LOG.error("Port is Null");
297 InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
298 if (aclInPort == null) {
299 LOG.error("getSecurityGroupInPortList: no security group associated}",
303 return aclInPort.getSecurityGroups();
307 * Retrieves the security rule attribute augmentation from the access list.
308 * @param ace the access list entry
309 * @return the security rule attributes
311 public static SecurityRuleAttr getAccesssListAttributes(Ace ace) {
313 LOG.error("Ace is Null");
316 SecurityRuleAttr aceAttributes = ace.getAugmentation(SecurityRuleAttr.class);
317 if (aceAttributes == null) {
318 LOG.error("Ace is null");
321 return aceAttributes;
325 * Returns the DHCP match.
327 * @param srcPort the source port.
328 * @param dstPort the destination port.
329 * @param lportTag the lport tag
330 * @param serviceMode ingress or egress service
331 * @return list of matches.
333 public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag,
334 Class<? extends ServiceModeBase> serviceMode) {
335 List<MatchInfoBase> matches = new ArrayList<>(5);
336 matches.add(MatchEthernetType.IPV4);
337 matches.add(MatchIpProtocol.UDP);
338 matches.add(new MatchUdpDestinationPort(dstPort));
339 matches.add(new MatchUdpSourcePort(srcPort));
340 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
345 * Returns the DHCPv6 match.
347 * @param srcPort the source port.
348 * @param dstPort the destination port.
349 * @param lportTag the lport tag
350 * @param serviceMode ingress or egress
351 * @return list of matches.
353 public static List<MatchInfoBase> buildDhcpV6Matches(int srcPort, int dstPort, int lportTag,
354 Class<? extends ServiceModeBase> serviceMode) {
355 List<MatchInfoBase> matches = new ArrayList<>(6);
356 matches.add(MatchEthernetType.IPV6);
357 matches.add(MatchIpProtocol.UDP);
358 matches.add(new MatchUdpDestinationPort(dstPort));
359 matches.add(new MatchUdpSourcePort(srcPort));
360 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
365 * Returns the ICMPv6 match.
367 * @param icmpType the icmpv6-type.
368 * @param icmpCode the icmpv6-code.
369 * @param lportTag the lport tag
370 * @param serviceMode ingress or egress
371 * @return list of matches.
373 public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag,
374 Class<? extends ServiceModeBase> serviceMode) {
375 List<MatchInfoBase> matches = new ArrayList<>(6);
376 matches.add(MatchEthernetType.IPV6);
377 matches.add(MatchIpProtocol.ICMPV6);
379 matches.add(new MatchIcmpv6((short) icmpType, (short) icmpCode));
381 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
385 public static List<MatchInfoBase> buildBroadcastIpV4Matches(String ipAddr) {
386 List<MatchInfoBase> matches = new ArrayList<>(2);
387 matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
388 matches.addAll(AclServiceUtils.buildIpMatches(new IpPrefixOrAddress(ipAddr.toCharArray()),
389 MatchCriteria.MATCH_DESTINATION));
393 public static List<MatchInfoBase> buildL2BroadcastMatches() {
394 List<MatchInfoBase> matches = new ArrayList<>();
395 matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
400 * Builds the service id.
402 * @param interfaceName the interface name
403 * @param serviceIndex the service index
404 * @param serviceMode the service mode
405 * @return the instance identifier
407 public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
408 Class<? extends ServiceModeBase> serviceMode) {
409 return InstanceIdentifier.builder(ServiceBindings.class)
410 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
411 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
415 * Gets the bound services.
417 * @param serviceName the service name
418 * @param servicePriority the service priority
419 * @param flowPriority the flow priority
420 * @param cookie the cookie
421 * @param instructions the instructions
422 * @return the bound services
424 public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
425 BigInteger cookie, List<Instruction> instructions) {
426 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
427 .setInstruction(instructions);
428 return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
429 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
430 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
433 public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
434 if (updatedAclList == null) {
435 return Collections.emptyList();
437 List<Uuid> newAclList = new ArrayList<>(updatedAclList);
438 if (currentAclList == null) {
441 List<Uuid> origAclList = new ArrayList<>(currentAclList);
442 for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
443 Uuid updatedAclUuid = iterator.next();
444 for (Uuid currentAclUuid :origAclList) {
445 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
453 public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
454 List<AllowedAddressPairs> updatedAllowedAddressPairs,
455 List<AllowedAddressPairs> currentAllowedAddressPairs) {
456 if (updatedAllowedAddressPairs == null) {
459 List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
460 if (currentAllowedAddressPairs == null) {
461 return newAllowedAddressPairs;
463 List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
464 for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
465 AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
466 for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
467 if (updatedAllowedAddressPair.getKey().equals(currentAllowedAddressPair.getKey())) {
473 return newAllowedAddressPairs;
476 public static List<AllowedAddressPairs> getPortAllowedAddresses(Interface port) {
478 LOG.error("Port is Null");
481 InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
482 if (aclInPort == null) {
483 LOG.error("getSecurityGroupInPortList: no security group associated to Interface port: {}", port.getName());
486 return aclInPort.getAllowedAddressPairs();
489 public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
490 .interfaces.rev140508.interfaces.state.Interface interfaceState) {
491 BigInteger dpId = null;
492 List<String> ofportIds = interfaceState.getLowerLayerIf();
493 if (ofportIds != null && !ofportIds.isEmpty()) {
494 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
495 dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
500 public static List<String> getIpBroadcastAddresses(List<IpPrefixOrAddress> cidrs) {
501 List<String> ipBroadcastAddresses = new ArrayList<>();
502 for (IpPrefixOrAddress cidr : cidrs) {
503 IpPrefix cidrIpPrefix = cidr.getIpPrefix();
504 if (cidrIpPrefix != null) {
505 Ipv4Prefix cidrIpv4Prefix = cidrIpPrefix.getIpv4Prefix();
506 if (cidrIpv4Prefix != null) {
507 ipBroadcastAddresses.add(getBroadcastAddressFromCidr(cidrIpv4Prefix.getValue()));
511 return ipBroadcastAddresses;
514 public static String getBroadcastAddressFromCidr(String cidr) {
515 String[] ipaddressValues = cidr.split("/");
516 int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
517 int cidrPart = Integer.parseInt(ipaddressValues[1]);
519 for (int j = 0; j < cidrPart; ++j) {
520 netmask |= 1 << 31 - j;
522 int network = address & netmask;
523 int broadcast = network | ~netmask;
524 return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
528 * Builds the ip matches.
530 * @param ipPrefixOrAddress the ip prefix or address
531 * @param matchCriteria the source_ip or destination_ip used for the match
534 public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
535 MatchCriteria matchCriteria) {
536 List<MatchInfoBase> flowMatches = new ArrayList<>();
537 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
538 if (ipPrefix != null) {
539 Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
540 if (ipv4Prefix != null) {
541 flowMatches.add(MatchEthernetType.IPV4);
542 if (!ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
543 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(ipv4Prefix)
544 : new MatchIpv4Destination(ipv4Prefix));
547 flowMatches.add(MatchEthernetType.IPV6);
548 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
549 ipPrefix.getIpv6Prefix()) : new MatchIpv6Destination(ipPrefix.getIpv6Prefix()));
552 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
553 if (ipAddress.getIpv4Address() != null) {
554 flowMatches.add(MatchEthernetType.IPV4);
555 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(
556 ipAddress.getIpv4Address().getValue(), "32") : new MatchIpv4Destination(
557 ipAddress.getIpv4Address().getValue(), "32"));
559 flowMatches.add(MatchEthernetType.IPV6);
560 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
561 ipAddress.getIpv6Address().getValue() + "/128") : new MatchIpv6Destination(
562 ipAddress.getIpv6Address().getValue() + "/128"));
569 * Builds the arp ip matches.
570 * @param ipPrefixOrAddress the ip prefix or address
571 * @return the MatchInfoBase list
573 public static List<MatchInfoBase> buildArpIpMatches(IpPrefixOrAddress ipPrefixOrAddress) {
574 List<MatchInfoBase> flowMatches = new ArrayList<>();
575 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
576 if (ipPrefix != null) {
577 Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
578 if (ipv4Prefix != null && !ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
579 flowMatches.add(new MatchArpSpa(ipv4Prefix));
582 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
583 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
584 flowMatches.add(new MatchArpSpa(ipAddress.getIpv4Address().getValue(), "32"));
590 public static MatchInfoBase buildRemoteAclTagMetadataMatch(Integer remoteAclTag) {
591 return new MatchMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
592 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
595 public static BigInteger getRemoteAclTagMetadata(BigInteger remoteAclTag) {
596 return remoteAclTag.shiftLeft(4);
600 * Does IPv4 address exists in the list of allowed address pair.
602 * @param aaps the allowed address pairs
603 * @return true, if successful
605 public static boolean doesIpv4AddressExists(List<AllowedAddressPairs> aaps) {
609 for (AllowedAddressPairs aap : aaps) {
610 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
611 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
612 if (ipPrefix != null) {
613 if (ipPrefix.getIpv4Prefix() != null) {
617 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
618 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
627 * Does IPv6 address exists in the list of allowed address pair.
629 * @param aaps the allowed address pairs
630 * @return true, if successful
632 public static boolean doesIpv6AddressExists(List<AllowedAddressPairs> aaps) {
636 for (AllowedAddressPairs aap : aaps) {
637 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
638 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
639 if (ipPrefix != null) {
640 if (ipPrefix.getIpv6Prefix() != null) {
644 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
645 if (ipAddress != null && ipAddress.getIpv6Address() != null) {
654 * Gets the lport tag match.
655 * Ingress match is based on metadata and egress match is based on masked reg6
657 * @param lportTag the lport tag
658 * @param serviceMode ingress or egress service mode
659 * @return the lport tag match
661 public static MatchInfoBase buildLPortTagMatch(int lportTag, Class<? extends ServiceModeBase> serviceMode) {
662 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
663 return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
664 MetaDataUtil.getLportTagMaskForReg6());
666 return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG);
670 public static List<MatchInfoBase> buildMatchesForLPortTagAndRemoteAclTag(Integer lportTag, Integer remoteAclTag,
671 Class<? extends ServiceModeBase> serviceMode) {
672 List<MatchInfoBase> matches = new ArrayList<>();
673 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
674 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
675 matches.add(AclServiceUtils.buildRemoteAclTagMetadataMatch(remoteAclTag));
677 // In case of ingress service mode, only metadata is used for
678 // matching both lportTag and aclTag. Hence performing "or"
679 // operation on both lportTag and aclTag metadata.
680 BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
681 .or(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)));
682 BigInteger metaDataMask =
683 MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
684 matches.add(new MatchMetadata(metaData, metaDataMask));
689 public static Collection<? extends MatchInfoBase> buildMatchesForLPortTagAndConntrackClassifierType(int lportTag,
690 AclConntrackClassifierType conntrackClassifierType, Class<? extends ServiceModeBase> serviceMode) {
691 List<MatchInfoBase> matches = new ArrayList<>();
692 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
693 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
694 matches.add(AclServiceUtils.buildAclConntrackClassifierTypeMatch(conntrackClassifierType));
696 // In case of ingress service mode, only metadata is used for
697 // matching both lportTag and conntrackClassifierType. Hence performing "or"
698 // operation on both lportTag and conntrackClassifierType metadata.
699 BigInteger metaData = MetaDataUtil.getLportTagMetaData(lportTag)
700 .or(MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()));
701 BigInteger metaDataMask =
702 MetaDataUtil.METADATA_MASK_LPORT_TAG.or(MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
703 matches.add(new MatchMetadata(metaData, metaDataMask));
708 public static InstructionWriteMetadata getWriteMetadataForAclClassifierType(
709 AclConntrackClassifierType conntrackClassifierType) {
710 return new InstructionWriteMetadata(
711 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackClassifierType.getValue()),
712 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
715 public static InstructionWriteMetadata getWriteMetadataForRemoteAclTag(Integer remoteAclTag) {
716 return new InstructionWriteMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
717 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
720 public static MatchInfoBase buildAclConntrackClassifierTypeMatch(
721 AclConntrackClassifierType conntrackSupportedType) {
722 return new MatchMetadata(
723 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(conntrackSupportedType.getValue()),
724 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
727 public AclserviceConfig getConfig() {
731 public static boolean isIPv4Address(AllowedAddressPairs aap) {
732 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
733 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
734 if (ipPrefix != null) {
735 if (ipPrefix.getIpv4Prefix() != null) {
739 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
740 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
747 public static Map<String, List<MatchInfoBase>> getFlowForAllowedAddresses(
748 List<AllowedAddressPairs> syncAllowedAddresses, Map<String, List<MatchInfoBase>> flowMatchesMap,
749 boolean isSourceIpMacMatch) {
750 if (flowMatchesMap == null) {
753 Map<String, List<MatchInfoBase>> updatedFlowMatchesMap = new HashMap<>();
754 MatchInfoBase ipv4Match = MatchEthernetType.IPV4;
755 MatchInfoBase ipv6Match = MatchEthernetType.IPV6;
756 for (Entry<String, List<MatchInfoBase>> entry : flowMatchesMap.entrySet()) {
757 String flowName = entry.getKey();
758 List<MatchInfoBase> flows = entry.getValue();
759 // iterate over allow address pair and update match type
760 for (AllowedAddressPairs aap : syncAllowedAddresses) {
761 List<MatchInfoBase> matchInfoBaseList;
763 if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) {
764 matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
765 flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap);
766 updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
767 } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) {
768 matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap);
769 flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap);
770 updatedFlowMatchesMap.put(flowId, matchInfoBaseList);
774 return updatedFlowMatchesMap;
777 public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) {
778 IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
779 if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null
780 && ipPrefix.getIpv4Prefix().getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
786 protected static boolean isNotIpv6AllNetwork(AllowedAddressPairs aap) {
787 IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
788 if (ipPrefix != null && ipPrefix.getIpv6Prefix() != null
789 && ipPrefix.getIpv6Prefix().getValue().equals(AclConstants.IPV6_ALL_NETWORK)) {
795 public static boolean isNotIpAllNetwork(AllowedAddressPairs aap) {
796 return isNotIpv4AllNetwork(aap) && isNotIpv6AllNetwork(aap);
799 private static String getAapFlowId(AllowedAddressPairs aap) {
800 return aap.getMacAddress().getValue() + "_" + String.valueOf(aap.getIpAddress().getValue());
803 public static Long getElanIdFromInterface(String elanInterfaceName,DataBroker broker) {
804 ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
805 if (null != elanInterface) {
806 ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
807 return elanInfo.getElanTag();
812 public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
813 InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
814 return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
817 public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
818 return InstanceIdentifier.builder(ElanInterfaces.class)
819 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
822 // elan-instances config container
823 public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
824 InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
825 return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
828 public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
829 return InstanceIdentifier.builder(ElanInstances.class)
830 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
833 public static List<IpPrefixOrAddress> getSubnetIpPrefixes(DataBroker broker, String portId) {
834 InstanceIdentifier<PortSubnetIpPrefixes> id = InstanceIdentifier.builder(PortsSubnetIpPrefixes.class)
835 .child(PortSubnetIpPrefixes.class, new PortSubnetIpPrefixesKey(portId)).build();
836 Optional<PortSubnetIpPrefixes> portSubnetIpPrefixes = read(broker, LogicalDatastoreType.OPERATIONAL, id);
837 if (portSubnetIpPrefixes.isPresent()) {
838 return portSubnetIpPrefixes.get().getSubnetIpPrefixes();
843 public static void deleteSubnetIpPrefixes(DataBroker broker, String portId) {
844 InstanceIdentifier<PortSubnetIpPrefixes> id = InstanceIdentifier.builder(PortsSubnetIpPrefixes.class)
845 .child(PortSubnetIpPrefixes.class, new PortSubnetIpPrefixesKey(portId)).build();
846 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
849 private static List<MatchInfoBase> updateAAPMatches(boolean isSourceIpMacMatch, List<MatchInfoBase> flows,
850 AllowedAddressPairs aap) {
851 List<MatchInfoBase> matchInfoBaseList;
852 if (isSourceIpMacMatch) {
853 matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_SOURCE);
855 matchInfoBaseList = AclServiceUtils.buildIpMatches(aap.getIpAddress(), MatchCriteria.MATCH_DESTINATION);
857 matchInfoBaseList.addAll(flows);
858 return matchInfoBaseList;
861 public static MatchInfoBase getMatchInfoByType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
862 for (MatchInfoBase mib : flows) {
863 if (type.isAssignableFrom(mib.getClass())) {
870 public static boolean containsMatchFieldType(List<MatchInfoBase> flows, Class<? extends NxMatchInfo> type) {
871 return getMatchInfoByType(flows, type) != null;
874 public static boolean containsTcpMatchField(List<MatchInfoBase> flows) {
875 return flows.contains(MatchIpProtocol.TCP);
878 public static boolean containsUdpMatchField(List<MatchInfoBase> flows) {
879 return flows.contains(MatchIpProtocol.UDP);
882 public static Integer allocateId(IdManagerService idManager, String poolName, String idKey, Integer defaultId) {
883 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
885 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
886 RpcResult<AllocateIdOutput> rpcResult = result.get();
887 if (rpcResult.isSuccessful()) {
888 Integer allocatedId = rpcResult.getResult().getIdValue().intValue();
889 LOG.debug("Allocated ACL ID: {} with key: {} into pool: {}", allocatedId, idKey, poolName);
892 LOG.error("RPC Call to Get Unique Id for key {} from pool {} returned with Errors {}",
893 idKey, poolName, rpcResult.getErrors());
895 } catch (InterruptedException | ExecutionException e) {
896 LOG.error("Exception when getting Unique Id for key {} from pool {} ", idKey, poolName, e);
901 public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
902 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
904 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
905 RpcResult<Void> rpcResult = result.get();
906 if (!rpcResult.isSuccessful()) {
907 LOG.error("RPC Call to release Id with Key {} from pool {} returned with Errors {}",
908 idKey, poolName, rpcResult.getErrors());
910 LOG.debug("Released ACL ID with key: {} from pool: {}", idKey, poolName);
912 } catch (InterruptedException | ExecutionException e) {
913 LOG.error("Exception when releasing Id for key {} from pool {} ", idKey, poolName, e);
918 * Gets the ACL tag from cache. If not found in cache, tries to allocate and
921 * @param aclId the acl id
922 * @return the acl tag
924 public Integer getAclTag(final Uuid aclId) {
925 String aclName = aclId.getValue();
926 Integer aclTag = this.aclDataUtil.getAclTag(aclName);
927 if (aclTag == null) {
928 LOG.debug("ACL tag not found in cache for ACL={}, trying to allocate again.", aclName);
929 aclTag = allocateAclTag(aclName);
930 if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
931 this.aclDataUtil.addAclTag(aclName, aclTag);
940 * @param aclName the ACL name
941 * @return the integer
943 public Integer allocateAclTag(String aclName) {
944 Integer aclTag = AclServiceUtils.allocateId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName,
945 AclConstants.INVALID_ACL_TAG);
952 * @param aclName the ACL name
954 public void releaseAclTag(String aclName) {
955 AclServiceUtils.releaseId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName);
959 * Indicates whether the interface has port security enabled.
961 * @param aclInterface the interface.
962 * @return true if port is security enabled.
964 public static boolean isOfInterest(AclInterface aclInterface) {
965 return aclInterface != null && aclInterface.isPortSecurityEnabled();
969 * Creates the id pool for ACL tag.
971 * @param poolName the pool name
973 private void createIdPoolForAclTag(String poolName) {
974 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
975 .setPoolName(poolName).setLow(AclConstants.ACL_TAG_POOL_START)
976 .setHigh(AclConstants.ACL_TAG_POOL_END).build();
978 Future<RpcResult<Void>> result = this.idManager.createIdPool(createPool);
979 if (result != null && result.get().isSuccessful()) {
980 LOG.debug("Created IdPool for {}", poolName);
982 } catch (InterruptedException | ExecutionException e) {
983 LOG.error("Failed to create ID pool [{}] for remote ACL ids", poolName, e);
984 throw new RuntimeException("Failed to create ID pool [{}] for remote ACL ids", e);
991 * @param poolName the pool name
993 public void deleteIdPool(String poolName) {
994 DeleteIdPoolInput deletePool = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
996 Future<RpcResult<Void>> result = this.idManager.deleteIdPool(deletePool);
997 if (result != null && result.get().isSuccessful()) {
998 LOG.debug("Deleted IdPool for {}", poolName);
1000 } catch (InterruptedException | ExecutionException e) {
1001 LOG.error("Failed to delete ID pool [{}]", poolName, e);
1002 throw new RuntimeException("Failed to delete ID pool [" + poolName + "]", e);
1007 * Creates remote the acl id pools.
1009 public void createRemoteAclIdPool() {
1010 createIdPoolForAclTag(AclConstants.ACL_TAG_POOL_NAME);
1014 * Delete remote the acl id pools.
1016 public void deleteRemoteAclIdPool() {
1017 deleteIdPool(AclConstants.ACL_TAG_POOL_NAME);
1020 public static List<? extends MatchInfoBase> buildIpAndSrcServiceMatch(Integer aclTag, AllowedAddressPairs aap,
1021 DataBroker dataBroker) {
1022 List<MatchInfoBase> flowMatches = new ArrayList<>();
1023 flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
1024 if (aap.getIpAddress().getIpAddress() != null) {
1025 if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
1026 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1027 flowMatches.add(ipv4EthMatch);
1028 MatchIpv4Source srcMatch = new MatchIpv4Source(
1029 new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
1030 flowMatches.add(srcMatch);
1031 } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
1032 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1033 flowMatches.add(ipv6EthMatch);
1034 MatchIpv6Source srcMatch = new MatchIpv6Source(
1035 new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
1036 flowMatches.add(srcMatch);
1038 } else if (aap.getIpAddress().getIpPrefix() != null) {
1039 if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
1040 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1041 flowMatches.add(ipv4EthMatch);
1042 MatchIpv4Source srcMatch = new MatchIpv4Source(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
1043 flowMatches.add(srcMatch);
1044 } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
1045 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1046 flowMatches.add(ipv6EthMatch);
1047 MatchIpv6Source srcMatch = new MatchIpv6Source(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
1048 flowMatches.add(srcMatch);
1054 public static List<? extends MatchInfoBase> buildIpAndDstServiceMatch(Integer aclTag, AllowedAddressPairs aap,
1055 DataBroker dataBroker) {
1056 List<MatchInfoBase> flowMatches = new ArrayList<>();
1057 flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
1059 if (aap.getIpAddress().getIpAddress() != null) {
1060 if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
1061 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1062 flowMatches.add(ipv4EthMatch);
1063 MatchIpv4Destination dstMatch = new MatchIpv4Destination(
1064 new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
1065 flowMatches.add(dstMatch);
1066 } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
1067 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1068 flowMatches.add(ipv6EthMatch);
1069 MatchIpv6Destination dstMatch = new MatchIpv6Destination(
1070 new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
1071 flowMatches.add(dstMatch);
1073 } else if (aap.getIpAddress().getIpPrefix() != null) {
1074 if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
1075 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
1076 flowMatches.add(ipv4EthMatch);
1077 MatchIpv4Destination dstMatch =
1078 new MatchIpv4Destination(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
1079 flowMatches.add(dstMatch);
1080 } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
1081 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
1082 flowMatches.add(ipv6EthMatch);
1083 MatchIpv6Destination dstMatch =
1084 new MatchIpv6Destination(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
1085 flowMatches.add(dstMatch);
1091 public static boolean isOfAclInterest(Acl acl) {
1092 if (acl.getAccessListEntries() != null) {
1093 List<Ace> aceList = acl.getAccessListEntries().getAce();
1094 if (aceList != null && !aceList.isEmpty()) {
1095 return aceList.get(0).getAugmentation(SecurityRuleAttr.class) != null;
1101 public static void addLportTagMetadataMatch(int lportTag, List<MatchInfoBase> flowMatches,
1102 Class<? extends ServiceModeBase> serviceMode) {
1103 MatchInfoBase lportMatch = buildLPortTagMatch(lportTag, serviceMode);
1104 InterfaceServiceUtil.mergeMetadataMatchsOrAdd(flowMatches, lportMatch);
1108 * Returns ACL specific key for synchronization.
1110 * @param key the generic key
1111 * @return ACL key that can be used with synchronization
1113 public static String getAclKeyForSynchronization(String key) {
1114 return key + AclConstants.ACL_SYNC_KEY_EXT;
1118 * Builds the ip protocol matches.
1120 * @param etherType the ether type
1121 * @param protocol the protocol
1122 * @return the list of matches.
1124 public static List<MatchInfoBase> buildIpProtocolMatches(MatchEthernetType etherType, IPProtocols protocol) {
1125 return Lists.newArrayList(etherType, new MatchIpProtocol(protocol.shortValue()));
1129 * Does ACE have remote group id.
1131 * @param aceAttr the ace attr
1132 * @return true, if successful
1134 public static boolean doesAceHaveRemoteGroupId(final SecurityRuleAttr aceAttr) {
1135 return aceAttr != null && aceAttr.getRemoteGroupId() != null;
1138 public SortedSet<Integer> getRemoteAclTags(List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
1139 SortedSet<Integer> remoteAclTags = new TreeSet<>();
1140 Set<Uuid> remoteAclIds = getRemoteAclIdsByDirection(aclIds, direction);
1141 for (Uuid remoteAclId : remoteAclIds) {
1142 Integer remoteAclTag = getAclTag(remoteAclId);
1143 if (remoteAclTag != null && remoteAclTag != AclConstants.INVALID_ACL_TAG) {
1144 remoteAclTags.add(remoteAclTag);
1147 return remoteAclTags;
1150 public Set<Uuid> getRemoteAclIdsByDirection(List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
1151 Set<Uuid> remoteAclIds = new HashSet<>();
1152 if (aclIds == null || aclIds.isEmpty()) {
1153 return remoteAclIds;
1156 for (Uuid aclId : aclIds) {
1157 Acl acl = this.aclDataUtil.getAcl(aclId.getValue());
1159 LOG.warn("ACL {} not found in cache.", aclId.getValue());
1162 remoteAclIds.addAll(getRemoteAclIdsByDirection(acl, direction));
1164 return remoteAclIds;
1167 public static Set<Uuid> getRemoteAclIdsByDirection(Acl acl, Class<? extends DirectionBase> direction) {
1168 Set<Uuid> remoteAclIds = new HashSet<>();
1169 AccessListEntries accessListEntries = acl.getAccessListEntries();
1170 if (accessListEntries != null && accessListEntries.getAce() != null) {
1171 for (Ace ace : accessListEntries.getAce()) {
1172 SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace);
1173 if (aceAttr.getDirection().equals(direction) && doesAceHaveRemoteGroupId(aceAttr)) {
1174 remoteAclIds.add(aceAttr.getRemoteGroupId());
1178 return remoteAclIds;
1182 * Skip delete in case of overlapping IP.
1185 * When there are multiple ports (e.g., p1, p2, p3) having same AAP (e.g.,
1186 * 224.0.0.5) configured which are part of single SG, there would be single
1187 * flow in remote ACL table. When one of these ports (say p1) is deleted,
1188 * the single flow which is configured in remote ACL table shouldn't be
1189 * deleted. It should be deleted only when there are no more references to
1192 * @param portId the port id
1193 * @param remoteAclId the remote Acl Id
1194 * @param ipPrefix the ip prefix
1195 * @param broker the broker
1196 * @param addOrRemove the add or remove
1197 * @return true, if successful
1199 public static boolean skipDeleteInCaseOfOverlappingIP(String portId, Uuid remoteAclId, IpPrefixOrAddress ipPrefix,
1200 DataBroker broker, int addOrRemove) {
1201 boolean skipDelete = false;
1202 if (addOrRemove != NwConstants.DEL_FLOW) {
1205 AclIpPrefixes aclIpPrefixes =
1206 AclServiceUtils.getAclIpPrefixesFromOperDs(broker, remoteAclId.getValue(), ipPrefix);
1207 if (aclIpPrefixes != null && aclIpPrefixes.getPortIds() != null) {
1208 List<String> ignorePorts = Lists.newArrayList(portId);
1209 List<PortIds> portIds = new ArrayList<>(aclIpPrefixes.getPortIds());
1210 // Checking if there are any other ports excluding ignorePorts
1211 long noOfRemotePorts =
1212 portIds.stream().map(x -> x.getPortId()).filter(y -> !ignorePorts.contains(y)).count();
1213 if (noOfRemotePorts > 0) {
1220 public static void deleteAclPortsLookupEntry(String aclName, DataBroker broker)
1221 throws TransactionCommitFailedException {
1222 SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, aclPortsByIpPath(aclName));
1225 public static InstanceIdentifier<AclPortsByIp> aclPortsByIpPath(String aclName) {
1226 InstanceIdentifier<AclPortsByIp> path = InstanceIdentifier.builder(AclPortsLookup.class)
1227 .child(AclPortsByIp.class, new AclPortsByIpKey(aclName)).build();
1231 public static InstanceIdentifier<AclIpPrefixes> getAclIpPrefixesPath(String aclName, IpPrefixOrAddress ipPrefix) {
1232 return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(aclName))
1233 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).build();
1236 public static InstanceIdentifier<PortIds> getPortIdsPathInAclPortsLookup(String ruleName,
1237 IpPrefixOrAddress ipPrefix, String portId) {
1238 return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(ruleName))
1239 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).child(PortIds.class, new PortIdsKey(portId))
1243 public static void updateAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter,
1244 DataBroker broker, int addOrRemove) {
1245 LOG.debug("Processing interface update for port {}, addOrRemove={}", portAfter.getInterfaceId(), addOrRemove);
1246 if (addOrRemove == NwConstants.ADD_FLOW) {
1247 List<AllowedAddressPairs> addedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1248 portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
1249 if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
1250 updateAclPortsLookup(portAfter, portAfter.getSecurityGroups(), addedAllowedAddressPairs,
1251 NwConstants.ADD_FLOW, broker);
1254 List<Uuid> addedAcls = getUpdatedAclList(portAfter.getSecurityGroups(), portBefore.getSecurityGroups());
1255 if (addedAcls != null && !addedAcls.isEmpty()) {
1256 updateAclPortsLookup(portAfter, addedAcls, portAfter.getAllowedAddressPairs(), NwConstants.ADD_FLOW,
1260 List<AllowedAddressPairs> deletedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1261 portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
1262 if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
1263 updateAclPortsLookup(portAfter, portAfter.getSecurityGroups(), deletedAllowedAddressPairs,
1264 NwConstants.DEL_FLOW, broker);
1267 List<Uuid> deletedAcls = getUpdatedAclList(portBefore.getSecurityGroups(), portAfter.getSecurityGroups());
1268 if (deletedAcls != null && !deletedAcls.isEmpty()) {
1269 updateAclPortsLookup(portAfter, deletedAcls, portAfter.getAllowedAddressPairs(), NwConstants.DEL_FLOW,
1275 public static void updateAclPortsLookup(AclInterface port, List<Uuid> aclList,
1276 List<AllowedAddressPairs> allowedAddresses, int addOrRemove, DataBroker broker) {
1277 String portId = port.getInterfaceId();
1278 LOG.trace("Updating AclPortsLookup for port={}, acls={}, AAPs={}, addOrRemove={}", portId, aclList,
1279 allowedAddresses, addOrRemove);
1281 if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1282 LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}, addOrRemove={}", portId, aclList,
1283 allowedAddresses, addOrRemove);
1286 for (Uuid aclId : aclList) {
1287 String aclName = aclId.getValue();
1288 synchronized (aclName.intern()) {
1289 WriteTransaction tx = broker.newWriteOnlyTransaction();
1290 for (AllowedAddressPairs aap : allowedAddresses) {
1291 PortIds portIdObj = new PortIdsBuilder().setKey(new PortIdsKey(portId)).setPortId(portId).build();
1292 InstanceIdentifier<PortIds> path =
1293 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1294 if (addOrRemove == NwConstants.ADD_FLOW) {
1295 tx.put(LogicalDatastoreType.OPERATIONAL, path, portIdObj, true);
1297 tx.delete(LogicalDatastoreType.OPERATIONAL, path);
1300 AclServiceUtils.waitForTransactionToComplete(tx);
1302 if (addOrRemove == NwConstants.DEL_FLOW) {
1303 cleanUpStaleEntriesInAclPortsLookup(aclName, broker);
1309 public static void cleanUpStaleEntriesInAclPortsLookup(String aclName, DataBroker broker) {
1310 AclPortsByIp aclPortsByIp = AclServiceUtils.getAclPortsByIpFromOperDs(broker, aclName);
1311 if (aclPortsByIp == null) {
1314 boolean deleteEntireAcl = false;
1315 List<AclIpPrefixes> ipPrefixes = aclPortsByIp.getAclIpPrefixes();
1316 if (ipPrefixes == null || ipPrefixes.isEmpty()) {
1317 deleteEntireAcl = true;
1319 boolean deleteMap = true;
1320 for (AclIpPrefixes ipPrefix : ipPrefixes) {
1321 if (ipPrefix.getPortIds() != null && !ipPrefix.getPortIds().isEmpty()) {
1326 deleteEntireAcl = deleteMap;
1328 WriteTransaction txDeleteMap = broker.newWriteOnlyTransaction();
1329 boolean wrTxPresent = false;
1330 if (deleteEntireAcl) {
1331 txDeleteMap.delete(LogicalDatastoreType.OPERATIONAL, AclServiceUtils.aclPortsByIpPath(aclName));
1334 for (AclIpPrefixes ipPrefix : ipPrefixes) {
1335 if (ipPrefix.getPortIds() == null || ipPrefix.getPortIds().isEmpty()) {
1336 InstanceIdentifier<AclIpPrefixes> delPath =
1337 AclServiceUtils.getAclIpPrefixesPath(aclName, ipPrefix.getIpPrefix());
1338 txDeleteMap.delete(LogicalDatastoreType.OPERATIONAL, delPath);
1344 AclServiceUtils.waitForTransactionToComplete(txDeleteMap);
1346 txDeleteMap.cancel();
1348 LOG.trace("Clean up of stale entries in AclPortsLookup is done for Acl={}, deleteEntireAcl={}", aclName,
1352 public static AclPortsByIp getAclPortsByIpFromOperDs(DataBroker broker, String aclName) {
1353 InstanceIdentifier<AclPortsByIp> path = aclPortsByIpPath(aclName);
1354 Optional<AclPortsByIp> optAclPortsByIp = read(broker, LogicalDatastoreType.OPERATIONAL, path);
1355 if (optAclPortsByIp.isPresent()) {
1356 return optAclPortsByIp.get();
1361 public static AclIpPrefixes getAclIpPrefixesFromOperDs(DataBroker broker, String aclName,
1362 IpPrefixOrAddress ipPrefix) {
1363 InstanceIdentifier<AclIpPrefixes> path = getAclIpPrefixesPath(aclName, ipPrefix);
1364 Optional<AclIpPrefixes> optAclPortsByIp = read(broker, LogicalDatastoreType.OPERATIONAL, path);
1365 if (optAclPortsByIp.isPresent()) {
1366 return optAclPortsByIp.get();
1371 public static CheckedFuture<Void, TransactionCommitFailedException> waitForTransactionToComplete(
1372 WriteTransaction tx) {
1373 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
1376 } catch (InterruptedException | ExecutionException e) {
1377 LOG.error("Error writing to datastore", e);
1383 * Gets the ace flow priority.
1385 * @param aclName the acl name
1386 * @return the ace flow priority
1388 public Integer getAceFlowPriority(String aclName) {
1389 Integer priority = AclConstants.ACE_DEFAULT_PRIORITY;
1390 Integer aclTag = getAclTag(new Uuid(aclName));
1391 if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
1392 // To handle overlapping rules, aclTag is added to priority
1395 LOG.warn("aclTag=[] is null or invalid for aclName={}", aclTag, aclName);
1401 * Returns the hard timeout based on the protocol when a ACL rule removed from the instance.
1402 * It will returns the timeout configured in the {@link AclserviceConfig} class.
1404 * @param ace the ace
1405 * @param aclServiceUtils acl service utils
1406 * @return the hard time out
1408 public static Integer getHardTimoutForApplyStatefulChangeOnExistingTraffic(Ace ace,
1409 AclServiceUtils aclServiceUtils) {
1410 int hardTimeout = AclConstants.SECURITY_GROUP_ICMP_IDLE_TIME_OUT;
1411 Matches matches = ace.getMatches();
1412 AceIp acl = (AceIp) matches.getAceType();
1413 Short protocol = acl.getProtocol();
1414 if (protocol == null) {
1416 } else if (protocol == NwConstants.IP_PROT_TCP) {
1417 hardTimeout = aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout();
1418 } else if (protocol == NwConstants.IP_PROT_UDP) {
1419 hardTimeout = aclServiceUtils.getConfig().getSecurityGroupUdpIdleTimeout();
1425 * This method creates and returns the ct_mark instruction when a ACL rule removed from the
1426 * instance. This instruction will reset the ct_mark value and stops the existing traffics.
1428 * @param filterTable the filterTable
1429 * @param elanId the Elan id
1430 * @return list of instruction
1432 public static List<InstructionInfo> createCtMarkInstructionForNewState(Short filterTable, Long elanId) {
1434 List<InstructionInfo> instructions = new ArrayList<>();
1435 List<ActionInfo> actionsInfos = new ArrayList<>();
1436 List<NxCtAction> ctActionsList = new ArrayList<>();
1437 NxCtAction nxCtMarkClearAction = new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_NEW_STATE);
1438 ctActionsList.add(nxCtMarkClearAction);
1440 ActionNxConntrack actionNxConntrack = new ActionNxConntrack(2, 1, 0, elanId.intValue(),
1441 (short) 255, ctActionsList);
1442 actionsInfos.add(actionNxConntrack);
1443 instructions.add(new InstructionApplyActions(actionsInfos));
1444 instructions.add(new InstructionGotoTable(filterTable));
1446 return instructions;