2 * Copyright (c) 2016, 2018 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 static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
14 import com.google.common.collect.Lists;
15 import com.google.common.net.InetAddresses;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import java.math.BigInteger;
18 import java.net.InetAddress;
19 import java.net.UnknownHostException;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
27 import java.util.Objects;
28 import java.util.Optional;
30 import java.util.SortedSet;
31 import java.util.TreeSet;
32 import java.util.concurrent.ExecutionException;
33 import javax.inject.Inject;
34 import javax.inject.Singleton;
35 import org.eclipse.jdt.annotation.NonNull;
36 import org.eclipse.jdt.annotation.Nullable;
37 import org.opendaylight.genius.infra.Datastore.Operational;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
39 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
40 import org.opendaylight.genius.infra.TypedWriteTransaction;
41 import org.opendaylight.genius.mdsalutil.ActionInfo;
42 import org.opendaylight.genius.mdsalutil.InstructionInfo;
43 import org.opendaylight.genius.mdsalutil.MDSALUtil;
44 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
45 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
46 import org.opendaylight.genius.mdsalutil.NwConstants;
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.infrautils.jobcoordinator.JobCoordinator;
67 import org.opendaylight.mdsal.binding.api.DataBroker;
68 import org.opendaylight.mdsal.binding.api.ReadTransaction;
69 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
70 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
71 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
80 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
82 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclPortsLookup;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclserviceAugmentation;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddressBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpVersionV6;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIp;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIpKey;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixes;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixesKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIds;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsKey;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.NetvirtAcl;
128 import org.opendaylight.yangtools.yang.binding.DataObject;
129 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
130 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
131 import org.opendaylight.yangtools.yang.common.Uint64;
132 import org.slf4j.Logger;
133 import org.slf4j.LoggerFactory;
136 public final class AclServiceUtils {
138 private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
140 private final DataBroker dataBroker;
141 private final ManagedNewTransactionRunner txRunner;
142 private final AclDataUtil aclDataUtil;
143 private final AclserviceConfig config;
144 private final JobCoordinator jobCoordinator;
147 public AclServiceUtils(DataBroker dataBroker, AclDataUtil aclDataUtil, AclserviceConfig config,
148 JobCoordinator jobCoordinator) {
149 this.dataBroker = dataBroker;
150 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
151 this.aclDataUtil = aclDataUtil;
152 this.config = config;
153 this.jobCoordinator = jobCoordinator;
157 * Retrieves the Interface from the datastore.
158 * @param broker the data broker
159 * @param interfaceName the interface name
160 * @return the interface.
162 public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
163 .Interface> getInterface(DataBroker broker, String interfaceName) {
164 return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
168 * Builds the interface identifier.
169 * @param interfaceName the interface name.
170 * @return the interface identifier.
172 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
173 .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
174 return InstanceIdentifier.builder(Interfaces.class)
176 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
177 .Interface.class, new InterfaceKey(interfaceName)).build();
181 * Retrieves the object from the datastore.
182 * @param broker the data broker.
183 * @param datastoreType the data store type.
184 * @param path the wild card path.
185 * @param <T> type of DataObject
186 * @return the required object.
188 public static <T extends DataObject> Optional<T> read(
189 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
190 try (ReadTransaction tx = broker.newReadOnlyTransaction()) {
191 return tx.read(datastoreType, path).get();
192 } catch (InterruptedException | ExecutionException e) {
193 LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
194 return Optional.empty();
199 * Retrieves the interface state.
200 * @param dataBroker the data broker.
201 * @param interfaceName the interface name.
202 * @return the interface state.
204 public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
205 .@Nullable Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
206 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
207 .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
208 return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orElse(null);
212 * Build the interface state.
213 * @param interfaceName the interface name.
214 * @return the interface state.
216 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
217 .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
218 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
219 .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
220 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
221 .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
222 .rev140508.interfaces.state.InterfaceKey(interfaceName));
223 return idBuilder.build();
227 * Retrieves the security rule attribute augmentation from the access list.
228 * @param ace the access list entry
229 * @return the security rule attributes
232 public static SecurityRuleAttr getAccessListAttributes(Ace ace) {
236 SecurityRuleAttr aceAttributes = ace.augmentation(SecurityRuleAttr.class);
237 if (aceAttributes == null) {
240 return aceAttributes;
244 * Returns the DHCP match.
246 * @param srcPort the source port.
247 * @param dstPort the destination port.
248 * @param lportTag the lport tag
249 * @param serviceMode ingress or egress service
250 * @return list of matches.
252 public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag,
253 Class<? extends ServiceModeBase> serviceMode) {
254 List<MatchInfoBase> matches = new ArrayList<>(5);
255 matches.add(MatchEthernetType.IPV4);
256 matches.add(MatchIpProtocol.UDP);
257 matches.add(new MatchUdpDestinationPort(dstPort));
258 matches.add(new MatchUdpSourcePort(srcPort));
259 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
264 * Returns the DHCPv6 match.
266 * @param srcPort the source port.
267 * @param dstPort the destination port.
268 * @param lportTag the lport tag
269 * @param serviceMode ingress or egress
270 * @return list of matches.
272 public static List<MatchInfoBase> buildDhcpV6Matches(int srcPort, int dstPort, int lportTag,
273 Class<? extends ServiceModeBase> serviceMode) {
274 List<MatchInfoBase> matches = new ArrayList<>(6);
275 matches.add(MatchEthernetType.IPV6);
276 matches.add(MatchIpProtocol.UDP);
277 matches.add(new MatchUdpDestinationPort(dstPort));
278 matches.add(new MatchUdpSourcePort(srcPort));
279 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
284 * Returns the ICMPv6 match.
286 * @param icmpType the icmpv6-type.
287 * @param icmpCode the icmpv6-code.
288 * @param lportTag the lport tag
289 * @param serviceMode ingress or egress
290 * @return list of matches.
292 public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag,
293 Class<? extends ServiceModeBase> serviceMode) {
294 List<MatchInfoBase> matches = new ArrayList<>();
295 matches.add(MatchEthernetType.IPV6);
296 matches.add(MatchIpProtocol.ICMPV6);
298 matches.add(new MatchIcmpv6((short) icmpType, (short) icmpCode));
300 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
304 public static List<MatchInfoBase> buildBroadcastIpV4Matches(String ipAddr) {
305 List<MatchInfoBase> matches = new ArrayList<>(2);
306 matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
307 matches.addAll(AclServiceUtils.buildIpMatches(IpPrefixOrAddressBuilder.getDefaultInstance(ipAddr),
308 MatchCriteria.MATCH_DESTINATION));
312 public static List<MatchInfoBase> buildL2BroadcastMatches() {
313 List<MatchInfoBase> matches = new ArrayList<>();
314 matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
319 * Builds the service id.
321 * @param interfaceName the interface name
322 * @param serviceIndex the service index
323 * @param serviceMode the service mode
324 * @return the instance identifier
326 public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
327 Class<? extends ServiceModeBase> serviceMode) {
328 return InstanceIdentifier.builder(ServiceBindings.class)
329 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
330 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
334 * Gets the bound services.
336 * @param serviceName the service name
337 * @param servicePriority the service priority
338 * @param flowPriority the flow priority
339 * @param cookie the cookie
340 * @param instructions the instructions
341 * @return the bound services
343 public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
344 Uint64 cookie, List<Instruction> instructions) {
345 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
346 .setInstruction(instructions);
347 return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
348 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
349 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
352 public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
353 if (updatedAclList == null) {
354 return Collections.emptyList();
356 List<Uuid> newAclList = new ArrayList<>(updatedAclList);
357 if (currentAclList == null) {
360 List<Uuid> origAclList = new ArrayList<>(currentAclList);
361 newAclList.removeAll(origAclList);
365 public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
366 @Nullable List<AllowedAddressPairs> updatedAllowedAddressPairs,
367 @Nullable List<AllowedAddressPairs> currentAllowedAddressPairs) {
368 if (updatedAllowedAddressPairs == null) {
369 return Collections.emptyList();
371 List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
372 if (currentAllowedAddressPairs == null) {
373 return newAllowedAddressPairs;
375 List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
376 for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
377 AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
378 for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
379 if (updatedAllowedAddressPair.key().equals(currentAllowedAddressPair.key())) {
385 return newAllowedAddressPairs;
389 public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
390 .interfaces.rev140508.interfaces.state.Interface interfaceState) {
391 BigInteger dpId = null;
392 List<String> ofportIds = interfaceState.getLowerLayerIf();
393 if (ofportIds != null && !ofportIds.isEmpty()) {
394 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
395 dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
400 public static List<String> getIpBroadcastAddresses(List<SubnetInfo> subnetInfoList) {
401 List<String> ipBroadcastAddresses = new ArrayList<>();
402 for (SubnetInfo subnetInfo : subnetInfoList) {
403 IpPrefix cidrIpPrefix = subnetInfo.getIpPrefix().getIpPrefix();
404 if (cidrIpPrefix != null) {
405 Ipv4Prefix cidrIpv4Prefix = cidrIpPrefix.getIpv4Prefix();
406 if (cidrIpv4Prefix != null) {
407 ipBroadcastAddresses.add(getBroadcastAddressFromCidr(cidrIpv4Prefix.getValue()));
411 return ipBroadcastAddresses;
414 public static String getBroadcastAddressFromCidr(String cidr) {
415 String[] ipaddressValues = cidr.split("/");
416 int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
417 int cidrPart = Integer.parseInt(ipaddressValues[1]);
419 for (int j = 0; j < cidrPart; ++j) {
420 netmask |= 1 << 31 - j;
422 int network = address & netmask;
423 int broadcast = network | ~netmask;
424 return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
428 * Builds the ip matches.
430 * @param ipPrefixOrAddress the ip prefix or address
431 * @param matchCriteria the source_ip or destination_ip used for the match
434 public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
435 MatchCriteria matchCriteria) {
436 List<MatchInfoBase> flowMatches = new ArrayList<>();
437 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
438 if (ipPrefix != null) {
439 Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
440 if (ipv4Prefix != null) {
441 flowMatches.add(MatchEthernetType.IPV4);
442 if (!ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
443 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(ipv4Prefix)
444 : new MatchIpv4Destination(ipv4Prefix));
447 flowMatches.add(MatchEthernetType.IPV6);
448 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
449 ipPrefix.getIpv6Prefix()) : new MatchIpv6Destination(ipPrefix.getIpv6Prefix()));
452 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
453 if (ipAddress.getIpv4Address() != null) {
454 flowMatches.add(MatchEthernetType.IPV4);
455 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(
456 ipAddress.getIpv4Address().getValue(), "32") : new MatchIpv4Destination(
457 ipAddress.getIpv4Address().getValue(), "32"));
459 flowMatches.add(MatchEthernetType.IPV6);
460 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
461 ipAddress.getIpv6Address().getValue() + "/128") : new MatchIpv6Destination(
462 ipAddress.getIpv6Address().getValue() + "/128"));
469 * Builds the arp ip matches.
470 * @param ipPrefixOrAddress the ip prefix or address
471 * @return the MatchInfoBase list
473 public static List<MatchInfoBase> buildArpIpMatches(IpPrefixOrAddress ipPrefixOrAddress) {
474 List<MatchInfoBase> flowMatches = new ArrayList<>();
475 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
476 if (ipPrefix != null) {
477 Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
478 if (ipv4Prefix != null && !ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
479 flowMatches.add(new MatchArpSpa(ipv4Prefix));
482 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
483 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
484 flowMatches.add(new MatchArpSpa(ipAddress.getIpv4Address().getValue(), "32"));
490 public static MatchInfoBase buildRemoteAclTagMetadataMatch(Integer remoteAclTag) {
491 return new MatchMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
492 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
495 public static Uint64 getRemoteAclTagMetadata(BigInteger remoteAclTag) {
496 return Uint64.valueOf(remoteAclTag.shiftLeft(4));
499 public static Uint64 getDropFlowCookie(int lport) {
500 return Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lport).longValue()
501 | AclConstants.COOKIE_ACL_DROP_FLOW.longValue());
505 * Does IPv4 address exists in the list of allowed address pair.
507 * @param aaps the allowed address pairs
508 * @return true, if successful
510 public static boolean doesIpv4AddressExists(List<AllowedAddressPairs> aaps) {
514 for (AllowedAddressPairs aap : aaps) {
515 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
516 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
517 if (ipPrefix != null) {
518 if (ipPrefix.getIpv4Prefix() != null) {
522 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
523 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
532 * Does IPv6 address exists in the list of allowed address pair.
534 * @param aaps the allowed address pairs
535 * @return true, if successful
537 public static boolean doesIpv6AddressExists(List<AllowedAddressPairs> aaps) {
541 for (AllowedAddressPairs aap : aaps) {
542 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
543 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
544 if (ipPrefix != null) {
545 if (ipPrefix.getIpv6Prefix() != null) {
549 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
550 if (ipAddress != null && ipAddress.getIpv6Address() != null) {
559 * Gets the lport tag match.
560 * Ingress match is based on metadata and egress match is based on masked reg6
562 * @param lportTag the lport tag
563 * @param serviceMode ingress or egress service mode
564 * @return the lport tag match
566 public static MatchInfoBase buildLPortTagMatch(int lportTag, Class<? extends ServiceModeBase> serviceMode) {
567 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
568 return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
569 MetaDataUtil.getLportTagMaskForReg6());
571 return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG);
575 public static List<MatchInfoBase> buildMatchesForLPortTagAndRemoteAclTag(Integer lportTag, Integer remoteAclTag,
576 Class<? extends ServiceModeBase> serviceMode) {
577 List<MatchInfoBase> matches = new ArrayList<>();
578 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
579 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
580 matches.add(AclServiceUtils.buildRemoteAclTagMetadataMatch(remoteAclTag));
582 // In case of ingress service mode, only metadata is used for
583 // matching both lportTag and aclTag. Hence performing "or"
584 // operation on both lportTag and aclTag metadata.
585 Uint64 metaData = Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lportTag).longValue()
586 | (getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)).longValue()));
587 Uint64 metaDataMask = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_LPORT_TAG.longValue()
588 | MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG.longValue());
589 matches.add(new MatchMetadata(metaData, metaDataMask));
594 public static Collection<? extends MatchInfoBase> buildMatchesForLPortTagAndConntrackClassifierType(int lportTag,
595 AclConntrackClassifierType conntrackClassifierType, Class<? extends ServiceModeBase> serviceMode) {
596 List<MatchInfoBase> matches = new ArrayList<>();
597 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
598 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
599 matches.add(AclServiceUtils.buildAclConntrackClassifierTypeMatch(conntrackClassifierType));
601 // In case of ingress service mode, only metadata is used for
602 // matching both lportTag and conntrackClassifierType. Hence performing "or"
603 // operation on both lportTag and conntrackClassifierType metadata.
604 Uint64 metaData = Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lportTag).longValue()
605 | (MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
606 Uint64.valueOf(conntrackClassifierType.getValue()))).longValue());
607 Uint64 metaDataMask = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_LPORT_TAG.longValue()
608 | MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE.longValue());
609 matches.add(new MatchMetadata(metaData, metaDataMask));
614 public static InstructionWriteMetadata getWriteMetadataForAclClassifierType(
615 AclConntrackClassifierType conntrackClassifierType) {
616 return new InstructionWriteMetadata(MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
617 Uint64.valueOf(conntrackClassifierType.getValue())),
618 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
621 public static InstructionWriteMetadata getWriteMetadataForDropFlag() {
622 return new InstructionWriteMetadata(MetaDataUtil.getAclDropMetaData(AclConstants.METADATA_DROP_FLAG),
623 MetaDataUtil.METADATA_MASK_ACL_DROP);
626 public static InstructionWriteMetadata getWriteMetadataForRemoteAclTag(Integer remoteAclTag) {
627 return new InstructionWriteMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
628 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
631 public static MatchInfoBase buildAclConntrackClassifierTypeMatch(
632 AclConntrackClassifierType conntrackSupportedType) {
633 return new MatchMetadata(
634 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
635 Uint64.valueOf(conntrackSupportedType.getValue())),
636 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
639 public AclserviceConfig getConfig() {
643 public static boolean isIPv4Address(AllowedAddressPairs aap) {
644 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
645 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
646 if (ipPrefix != null) {
647 if (ipPrefix.getIpv4Prefix() != null) {
651 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
652 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
659 public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) {
660 IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
661 if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null
662 && ipPrefix.getIpv4Prefix().getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
668 protected static boolean isNotIpv6AllNetwork(AllowedAddressPairs aap) {
669 IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
670 if (ipPrefix != null && ipPrefix.getIpv6Prefix() != null
671 && ipPrefix.getIpv6Prefix().getValue().equals(AclConstants.IPV6_ALL_NETWORK)) {
677 public static boolean isNotIpAllNetwork(AllowedAddressPairs aap) {
678 return isNotIpv4AllNetwork(aap) && isNotIpv6AllNetwork(aap);
682 public static Long getElanIdFromInterface(String elanInterfaceName, DataBroker broker) {
683 ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
684 if (null != elanInterface) {
685 ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
686 return elanInfo != null ? elanInfo.getElanTag().toJava() : null;
692 public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
693 InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
694 return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orElse(null);
697 public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
698 return InstanceIdentifier.builder(ElanInterfaces.class)
699 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
702 // elan-instances config container
704 public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
705 InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
706 return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orElse(null);
709 public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
710 return InstanceIdentifier.builder(ElanInstances.class)
711 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
714 public void deleteAcesFromConfigDS(String aclName, List<Ace> deletedAceRules) {
715 List<List<Ace>> acesParts = Lists.partition(deletedAceRules, AclConstants.ACES_PER_TRANSACTION);
716 for (List<Ace> acePart : acesParts) {
717 jobCoordinator.enqueueJob(aclName,
718 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
720 for (Ace ace: acePart) {
721 InstanceIdentifier<Ace> id = InstanceIdentifier.builder(AccessLists.class)
722 .child(Acl.class, new AclKey(aclName, Ipv4Acl.class)).child(AccessListEntries.class)
723 .child(Ace.class, ace.key()).build();
726 })), AclConstants.ACEDELETE_MAX_RETRIES);
731 * Gets ACL tag from Acl.
732 * @param acl Acl object
733 * @return the acl tag
735 public static Integer getAclTag(Acl acl) {
736 Integer aclTag = null;
737 AclserviceAugmentation aclserviceAugmentation = acl.augmentation(AclserviceAugmentation.class);
738 if (aclserviceAugmentation != null) {
739 aclTag = aclserviceAugmentation.getAclTag().intValue();
745 * Gets the ACL tag from cache.
747 * @param aclId the acl id
748 * @return the acl tag
750 public Integer getAclTag(final Uuid aclId) {
751 String aclName = aclId.getValue();
752 return this.aclDataUtil.getAclTag(aclName);
756 * Indicates whether the interface has port security enabled or interface is DHCP service port.
758 * @param aclInterface the interface.
759 * @return true if port is security enabled or is a DHCP service port.
761 public static boolean isOfInterest(AclInterface aclInterface) {
762 return aclInterface != null && (aclInterface.isPortSecurityEnabled()
763 || aclInterface.getInterfaceType() == InterfaceAcl.InterfaceType.DhcpService);
767 * Indicates whether the interface has port security enabled or interface is DHCP service port.
769 * @param aclInterface the interface.
770 * @return true if port is security enabled or is a DHCP service port.
772 public static boolean isOfInterest(InterfaceAcl aclInterface) {
773 return aclInterface != null && (aclInterface.isPortSecurityEnabled()
774 || aclInterface.getInterfaceType() == InterfaceAcl.InterfaceType.DhcpService);
777 public static List<? extends MatchInfoBase> buildIpAndSrcServiceMatch(Integer aclTag, AllowedAddressPairs aap) {
778 List<MatchInfoBase> flowMatches = new ArrayList<>();
779 flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
780 if (aap.getIpAddress().getIpAddress() != null) {
781 if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
782 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
783 flowMatches.add(ipv4EthMatch);
784 MatchIpv4Source srcMatch = new MatchIpv4Source(
785 new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
786 flowMatches.add(srcMatch);
787 } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
788 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
789 flowMatches.add(ipv6EthMatch);
790 MatchIpv6Source srcMatch = new MatchIpv6Source(
791 new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
792 flowMatches.add(srcMatch);
794 } else if (aap.getIpAddress().getIpPrefix() != null) {
795 if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
796 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
797 flowMatches.add(ipv4EthMatch);
798 MatchIpv4Source srcMatch = new MatchIpv4Source(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
799 flowMatches.add(srcMatch);
800 } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
801 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
802 flowMatches.add(ipv6EthMatch);
803 MatchIpv6Source srcMatch = new MatchIpv6Source(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
804 flowMatches.add(srcMatch);
810 public static List<? extends MatchInfoBase> buildIpAndDstServiceMatch(Integer aclTag, AllowedAddressPairs aap) {
811 List<MatchInfoBase> flowMatches = new ArrayList<>();
812 flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
814 if (aap.getIpAddress().getIpAddress() != null) {
815 if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
816 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
817 flowMatches.add(ipv4EthMatch);
818 MatchIpv4Destination dstMatch = new MatchIpv4Destination(
819 new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
820 flowMatches.add(dstMatch);
821 } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
822 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
823 flowMatches.add(ipv6EthMatch);
824 MatchIpv6Destination dstMatch = new MatchIpv6Destination(
825 new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
826 flowMatches.add(dstMatch);
828 } else if (aap.getIpAddress().getIpPrefix() != null) {
829 if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
830 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
831 flowMatches.add(ipv4EthMatch);
832 MatchIpv4Destination dstMatch =
833 new MatchIpv4Destination(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
834 flowMatches.add(dstMatch);
835 } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
836 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
837 flowMatches.add(ipv6EthMatch);
838 MatchIpv6Destination dstMatch =
839 new MatchIpv6Destination(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
840 flowMatches.add(dstMatch);
846 public static @NonNull List<Ace> aceList(@NonNull Acl acl) {
847 final AccessListEntries ale = acl.getAccessListEntries();
848 return ale == null ? Collections.emptyList() : ale.nonnullAce();
851 public static @NonNull List<Ace> getAceListFromAcl(Acl acl) {
852 List<Ace> aceList = aceList(acl);
853 if (!aceList.isEmpty() && aceList.get(0).augmentation(SecurityRuleAttr.class) != null) {
856 return Collections.emptyList();
860 * Builds the ip protocol matches.
862 * @param etherType the ether type
863 * @param protocol the protocol
864 * @return the list of matches.
866 public static List<MatchInfoBase> buildIpProtocolMatches(MatchEthernetType etherType, IPProtocols protocol) {
867 return Lists.newArrayList(etherType, new MatchIpProtocol(protocol.shortValue()));
871 * Does ACE have remote group id.
873 * @param aceAttr the ace attr
874 * @return true, if successful
876 public static boolean doesAceHaveRemoteGroupId(final SecurityRuleAttr aceAttr) {
877 return aceAttr != null && aceAttr.getRemoteGroupId() != null;
880 public SortedSet<Integer> getRemoteAclTags(@Nullable List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
881 SortedSet<Integer> remoteAclTags = new TreeSet<>();
882 Set<Uuid> remoteAclIds = getRemoteAclIdsByDirection(aclIds, direction);
883 for (Uuid remoteAclId : remoteAclIds) {
884 Integer remoteAclTag = getAclTag(remoteAclId);
885 if (remoteAclTag != null && remoteAclTag != AclConstants.INVALID_ACL_TAG) {
886 remoteAclTags.add(remoteAclTag);
889 return remoteAclTags;
892 public Set<Uuid> getRemoteAclIdsByDirection(@Nullable List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
893 Set<Uuid> remoteAclIds = new HashSet<>();
894 if (aclIds == null || aclIds.isEmpty()) {
898 for (Uuid aclId : aclIds) {
899 Acl acl = this.aclDataUtil.getAcl(aclId.getValue());
901 LOG.warn("ACL {} not found in cache.", aclId.getValue());
904 remoteAclIds.addAll(getRemoteAclIdsByDirection(acl, direction));
909 public static Set<Uuid> getRemoteAclIdsByDirection(Acl acl, Class<? extends DirectionBase> direction) {
910 Set<Uuid> remoteAclIds = new HashSet<>();
911 for (Ace ace : aceList(acl)) {
912 SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
913 if (aceAttr != null && Objects.equals(aceAttr.getDirection(), direction)
914 && doesAceHaveRemoteGroupId(aceAttr)) {
915 remoteAclIds.add(aceAttr.getRemoteGroupId());
922 * Skip delete in case of overlapping IP.
925 * When there are multiple ports (e.g., p1, p2, p3) having same AAP (e.g.,
926 * 224.0.0.5) configured which are part of single SG, there would be single
927 * flow in remote ACL table. When one of these ports (say p1) is deleted,
928 * the single flow which is configured in remote ACL table shouldn't be
929 * deleted. It should be deleted only when there are no more references to
932 * @param portId the port id
933 * @param remoteAclId the remote Acl Id
934 * @param ipPrefix the ip prefix
935 * @param addOrRemove the add or remove
936 * @return true, if successful
938 public boolean skipDeleteInCaseOfOverlappingIP(String portId, Uuid remoteAclId, IpPrefixOrAddress ipPrefix,
940 boolean skipDelete = false;
941 if (addOrRemove != NwConstants.DEL_FLOW) {
944 AclIpPrefixes aclIpPrefixes = getAclIpPrefixesFromOperDs(remoteAclId.getValue(), ipPrefix);
945 if (aclIpPrefixes != null && aclIpPrefixes.getPortIds() != null) {
946 List<String> ignorePorts = Lists.newArrayList(portId);
947 List<PortIds> portIds = new ArrayList<>(aclIpPrefixes.getPortIds().values());
948 // Checking if there are any other ports excluding ignorePorts
949 long noOfRemotePorts =
950 portIds.stream().map(PortIds::getPortId).filter(y -> !ignorePorts.contains(y)).count();
951 if (noOfRemotePorts > 0) {
958 public boolean doesRemoteAclIdExistsInAcls(List<Uuid> aclIds, Uuid remoteAclId,
959 Class<? extends DirectionBase> direction) {
960 if (aclIds == null) {
963 for (Uuid aclId : aclIds) {
964 Acl acl = this.aclDataUtil.getAcl(aclId.getValue());
966 LOG.warn("ACL {} not found in cache.", aclId.getValue());
969 AccessListEntries accessListEntries = acl.getAccessListEntries();
970 if (accessListEntries != null && accessListEntries.getAce() != null) {
971 for (Ace ace : accessListEntries.getAce()) {
972 SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
973 if (aceAttr != null && aceAttr.getDirection().equals(direction)
974 && doesAceHaveRemoteGroupId(aceAttr)) {
975 if (aceAttr.getRemoteGroupId().equals(remoteAclId)) {
985 public static InstanceIdentifier<AclPortsByIp> aclPortsByIpPath(String aclName) {
986 return InstanceIdentifier.builder(AclPortsLookup.class)
987 .child(AclPortsByIp.class, new AclPortsByIpKey(aclName)).build();
990 public static InstanceIdentifier<AclIpPrefixes> getAclIpPrefixesPath(String aclName, IpPrefixOrAddress ipPrefix) {
991 return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(aclName))
992 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).build();
995 public static InstanceIdentifier<PortIds> getPortIdsPathInAclPortsLookup(String ruleName,
996 IpPrefixOrAddress ipPrefix, String portId) {
997 return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(ruleName))
998 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).child(PortIds.class, new PortIdsKey(portId))
1002 public void addAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
1003 LOG.debug("Processing interface additions for port {}", portAfter.getInterfaceId());
1004 List<AllowedAddressPairs> addedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1005 portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
1006 if (!addedAllowedAddressPairs.isEmpty()) {
1007 addAclPortsLookup(portAfter, portAfter.getSecurityGroups(), addedAllowedAddressPairs);
1010 List<Uuid> addedAcls = getUpdatedAclList(portAfter.getSecurityGroups(), portBefore.getSecurityGroups());
1011 if (!addedAcls.isEmpty()) {
1012 addAclPortsLookup(portAfter, addedAcls, portAfter.getAllowedAddressPairs());
1016 public void deleteAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
1017 LOG.debug("Processing interface removals for port {}", portAfter.getInterfaceId());
1018 List<AllowedAddressPairs> deletedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1019 portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
1020 if (!deletedAllowedAddressPairs.isEmpty()) {
1021 deleteAclPortsLookup(portAfter, portAfter.getSecurityGroups(), deletedAllowedAddressPairs);
1024 List<Uuid> deletedAcls = getUpdatedAclList(portBefore.getSecurityGroups(), portAfter.getSecurityGroups());
1025 if (!deletedAcls.isEmpty()) {
1026 deleteAclPortsLookup(portAfter, deletedAcls, portAfter.getAllowedAddressPairs());
1030 public void addAclPortsLookup(AclInterface port, List<Uuid> aclList,
1031 List<AllowedAddressPairs> allowedAddresses) {
1032 String portId = port.getInterfaceId();
1033 LOG.trace("Adding AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1035 if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1036 LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1041 for (Uuid aclId : aclList) {
1042 String aclName = aclId.getValue();
1043 jobCoordinator.enqueueJob(aclName, () -> {
1044 List<ListenableFuture<Void>> futures = new ArrayList<>();
1045 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
1046 for (AllowedAddressPairs aap : allowedAddresses) {
1048 new PortIdsBuilder().withKey(new PortIdsKey(portId)).setPortId(portId).build();
1049 InstanceIdentifier<PortIds> path =
1050 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1051 tx.mergeParentStructurePut(path, portIdObj);
1059 public void deleteAclPortsLookup(AclInterface port, List<Uuid> aclList,
1060 List<AllowedAddressPairs> allowedAddresses) {
1061 String portId = port.getInterfaceId();
1062 LOG.trace("Deleting AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1064 if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1065 LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1070 for (Uuid aclId : aclList) {
1071 String aclName = aclId.getValue();
1072 jobCoordinator.enqueueJob(aclName, () -> {
1073 List<ListenableFuture<Void>> futures = new ArrayList<>();
1074 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
1075 for (AllowedAddressPairs aap : allowedAddresses) {
1076 InstanceIdentifier<PortIds> path =
1077 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1081 cleanUpStaleEntriesInAclPortsLookup(aclName, tx);
1088 private void cleanUpStaleEntriesInAclPortsLookup(String aclName, TypedWriteTransaction<Operational> tx) {
1089 AclPortsByIp aclPortsByIp = getAclPortsByIpFromOperDs(aclName);
1090 if (aclPortsByIp == null) {
1093 boolean deleteEntireAcl;
1094 @NonNull Map<AclIpPrefixesKey, AclIpPrefixes> aclIpPrefixesKeyAclIpPrefixesMap
1095 = aclPortsByIp.getAclIpPrefixes();
1096 if (aclIpPrefixesKeyAclIpPrefixesMap == null || aclIpPrefixesKeyAclIpPrefixesMap.isEmpty()) {
1097 deleteEntireAcl = true;
1099 boolean deleteMap = true;
1100 for (AclIpPrefixes ipPrefix : aclIpPrefixesKeyAclIpPrefixesMap.values()) {
1101 if (ipPrefix.getPortIds() != null && !ipPrefix.getPortIds().isEmpty()) {
1106 deleteEntireAcl = deleteMap;
1108 if (deleteEntireAcl) {
1109 tx.delete(AclServiceUtils.aclPortsByIpPath(aclName));
1111 for (AclIpPrefixes ipPrefix : aclIpPrefixesKeyAclIpPrefixesMap.values()) {
1112 if (ipPrefix.getPortIds() == null || ipPrefix.getPortIds().isEmpty()) {
1113 InstanceIdentifier<AclIpPrefixes> delPath =
1114 AclServiceUtils.getAclIpPrefixesPath(aclName, ipPrefix.getIpPrefix());
1122 private AclPortsByIp getAclPortsByIpFromOperDs(String aclName) {
1123 InstanceIdentifier<AclPortsByIp> path = aclPortsByIpPath(aclName);
1124 try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) {
1125 return tx.read(LogicalDatastoreType.OPERATIONAL, path).get().orElse(null);
1126 } catch (InterruptedException | ExecutionException e) {
1127 LOG.error("Failed to read ACL ports {}", path, e);
1133 private AclIpPrefixes getAclIpPrefixesFromOperDs(String aclName, IpPrefixOrAddress ipPrefix) {
1134 InstanceIdentifier<AclIpPrefixes> path = getAclIpPrefixesPath(aclName, ipPrefix);
1135 try (ReadTransaction tx = dataBroker.newReadOnlyTransaction()) {
1136 return tx.read(LogicalDatastoreType.OPERATIONAL, path).get().orElse(null);
1137 } catch (InterruptedException | ExecutionException e) {
1138 LOG.error("Failed to read ACL IP prefixes {}", path, e);
1144 * Gets the ace flow priority.
1146 * @param aclName the acl name
1147 * @return the ace flow priority
1149 public Integer getAceFlowPriority(String aclName) {
1150 Integer priority = AclConstants.ACE_DEFAULT_PRIORITY;
1151 Integer aclTag = getAclTag(new Uuid(aclName));
1152 if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
1153 // To handle overlapping rules, aclTag is added to priority
1156 LOG.warn("aclTag={} is null or invalid for aclName={}", aclTag, aclName);
1162 * Returns the hard timeout based on the protocol when a ACL rule removed from the instance.
1163 * It will returns the timeout configured in the {@link AclserviceConfig} class.
1165 * @param ace the ace
1166 * @param aclServiceUtils acl service utils
1167 * @return the hard time out
1169 public static Integer getHardTimoutForApplyStatefulChangeOnExistingTraffic(Ace ace,
1170 AclServiceUtils aclServiceUtils) {
1171 int hardTimeout = AclConstants.SECURITY_GROUP_ICMP_IDLE_TIME_OUT;
1172 Matches matches = ace.getMatches();
1173 AceIp acl = (AceIp) matches.getAceType();
1174 Short protocol = acl.getProtocol() != null ? acl.getProtocol().toJava() : null;
1175 if (protocol == null) {
1177 } else if (protocol == NwConstants.IP_PROT_TCP
1178 && aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout() != null) {
1179 hardTimeout = aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout().toJava();
1180 } else if (protocol == NwConstants.IP_PROT_UDP
1181 && aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout() != null) {
1182 hardTimeout = aclServiceUtils.getConfig().getSecurityGroupUdpIdleTimeout().toJava();
1188 * This method creates and returns the ct_mark instruction when a ACL rule removed from the
1189 * instance. This instruction will reset the ct_mark value and stops the existing traffics.
1191 * @param filterTable the filterTable
1192 * @param elanId the Elan id
1193 * @return list of instruction
1195 public static List<InstructionInfo> createCtMarkInstructionForNewState(Short filterTable, Long elanId) {
1197 List<InstructionInfo> instructions = new ArrayList<>();
1198 List<ActionInfo> actionsInfos = new ArrayList<>();
1199 List<NxCtAction> ctActionsList = new ArrayList<>();
1200 NxCtAction nxCtMarkClearAction = new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_NEW_STATE);
1201 ctActionsList.add(nxCtMarkClearAction);
1203 ActionNxConntrack actionNxConntrack = new ActionNxConntrack(2, 1, 0, elanId.intValue(),
1204 (short) 255, ctActionsList);
1205 actionsInfos.add(actionNxConntrack);
1206 instructions.add(new InstructionApplyActions(actionsInfos));
1207 instructions.add(new InstructionGotoTable(filterTable));
1209 return instructions;
1212 public static List<AllowedAddressPairs> excludeMulticastAAPs(@Nullable List<AllowedAddressPairs> allowedAddresses) {
1213 List<AllowedAddressPairs> filteredAAPs = new ArrayList<>();
1214 if (allowedAddresses != null) {
1215 for (AllowedAddressPairs allowedAddress : allowedAddresses) {
1216 InetAddress inetAddr = getInetAddress(allowedAddress.getIpAddress());
1217 if (inetAddr != null && !inetAddr.isMulticastAddress()) {
1218 filteredAAPs.add(allowedAddress);
1222 return filteredAAPs;
1225 public static String getRecoverServiceRegistryKey() {
1226 return NetvirtAcl.class.toString();
1230 private static InetAddress getInetAddress(IpPrefixOrAddress ipPrefixOrAddress) {
1233 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
1234 if (ipPrefix != null) {
1235 addr = ipPrefix.stringValue().split("/")[0];
1237 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
1238 if (ipAddress == null) {
1239 LOG.error("Invalid address : {}", ipPrefixOrAddress);
1242 addr = ipAddress.stringValue();
1246 return InetAddress.getByName(addr);
1247 } catch (UnknownHostException e) {
1248 LOG.error("Invalid address : {}", addr, e);
1253 public static Boolean isIpv6Subnet(List<SubnetInfo> subnetInfoList) {
1254 if (subnetInfoList != null && !subnetInfoList.isEmpty()) {
1255 for (SubnetInfo subnetInfo : subnetInfoList) {
1256 if (subnetInfo != null && IpVersionV6.class.equals(subnetInfo.getIpVersion())) {
1265 * Gets the subnet difference by performing (subnetInfo1 - subnetInfo2).
1267 * @param subnetInfo1 the subnet info 1
1268 * @param subnetInfo2 the subnet info 2
1269 * @return the subnet diff
1271 public static List<SubnetInfo> getSubnetDiff(List<SubnetInfo> subnetInfo1, List<SubnetInfo> subnetInfo2) {
1272 if (subnetInfo1 == null) {
1273 return Collections.emptyList();
1275 List<SubnetInfo> newSubnetList = new ArrayList<>(subnetInfo1);
1276 if (subnetInfo2 == null) {
1277 return newSubnetList;
1279 newSubnetList.removeAll(subnetInfo2);
1280 return newSubnetList;