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.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
15 import com.google.common.base.Optional;
16 import com.google.common.collect.Lists;
17 import com.google.common.net.InetAddresses;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import java.math.BigInteger;
20 import java.net.InetAddress;
21 import java.net.UnknownHostException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Objects;
30 import java.util.SortedSet;
31 import java.util.TreeSet;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Future;
34 import javax.inject.Inject;
35 import javax.inject.Singleton;
36 import org.eclipse.jdt.annotation.Nullable;
37 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
38 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
41 import org.opendaylight.genius.infra.Datastore.Operational;
42 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
43 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
44 import org.opendaylight.genius.infra.TypedWriteTransaction;
45 import org.opendaylight.genius.mdsalutil.ActionInfo;
46 import org.opendaylight.genius.mdsalutil.InstructionInfo;
47 import org.opendaylight.genius.mdsalutil.MDSALUtil;
48 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
49 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
50 import org.opendaylight.genius.mdsalutil.NwConstants;
51 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
52 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
53 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
54 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
55 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
56 import org.opendaylight.genius.mdsalutil.matches.MatchArpSpa;
57 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
58 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
59 import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6;
60 import org.opendaylight.genius.mdsalutil.matches.MatchIpProtocol;
61 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Destination;
62 import org.opendaylight.genius.mdsalutil.matches.MatchIpv4Source;
63 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Destination;
64 import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source;
65 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
66 import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort;
67 import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort;
68 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
69 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
70 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
71 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria;
72 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
80 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
82 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolOutput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.AclPortsLookup;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddressBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpVersionV6;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIp;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.AclPortsByIpKey;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixes;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.AclIpPrefixesKey;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIds;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.acl.ports.lookup.acl.ports.by.ip.acl.ip.prefixes.PortIdsKey;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.serviceutils.srm.types.rev180626.NetvirtAcl;
141 import org.opendaylight.yangtools.yang.binding.DataObject;
142 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
143 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
144 import org.opendaylight.yangtools.yang.common.RpcResult;
145 import org.opendaylight.yangtools.yang.common.Uint64;
146 import org.slf4j.Logger;
147 import org.slf4j.LoggerFactory;
150 public final class AclServiceUtils {
152 private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class);
154 private final DataBroker dataBroker;
155 private final ManagedNewTransactionRunner txRunner;
156 private final AclDataUtil aclDataUtil;
157 private final AclserviceConfig config;
158 private final IdManagerService idManager;
159 private final JobCoordinator jobCoordinator;
162 public AclServiceUtils(DataBroker dataBroker, AclDataUtil aclDataUtil, AclserviceConfig config,
163 IdManagerService idManager, JobCoordinator jobCoordinator) {
164 this.dataBroker = dataBroker;
165 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
166 this.aclDataUtil = aclDataUtil;
167 this.config = config;
168 this.idManager = idManager;
169 this.jobCoordinator = jobCoordinator;
173 * Retrieves the Interface from the datastore.
174 * @param broker the data broker
175 * @param interfaceName the interface name
176 * @return the interface.
178 public static Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
179 .Interface> getInterface(DataBroker broker, String interfaceName) {
180 return read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
184 * Builds the interface identifier.
185 * @param interfaceName the interface name.
186 * @return the interface identifier.
188 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
189 .interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
190 return InstanceIdentifier.builder(Interfaces.class)
192 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
193 .Interface.class, new InterfaceKey(interfaceName)).build();
197 * Retrieves the object from the datastore.
198 * @param broker the data broker.
199 * @param datastoreType the data store type.
200 * @param path the wild card path.
201 * @param <T> type of DataObject
202 * @return the required object.
204 public static <T extends DataObject> Optional<T> read(
205 DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
206 try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
207 return tx.read(datastoreType, path).checkedGet();
208 } catch (ReadFailedException e) {
209 LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e);
210 return Optional.absent();
215 * Retrieves the interface state.
216 * @param dataBroker the data broker.
217 * @param interfaceName the interface name.
218 * @return the interface state.
220 public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
221 .@Nullable Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
222 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
223 .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
224 return MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker).orNull();
228 * Build the interface state.
229 * @param interfaceName the interface name.
230 * @return the interface state.
232 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
233 .interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
234 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
235 .interfaces.state.Interface> idBuilder = InstanceIdentifier.builder(InterfacesState.class)
236 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
237 .state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
238 .rev140508.interfaces.state.InterfaceKey(interfaceName));
239 return idBuilder.build();
243 * Retrieves the security rule attribute augmentation from the access list.
244 * @param ace the access list entry
245 * @return the security rule attributes
248 public static SecurityRuleAttr getAccessListAttributes(Ace ace) {
252 SecurityRuleAttr aceAttributes = ace.augmentation(SecurityRuleAttr.class);
253 if (aceAttributes == null) {
256 return aceAttributes;
260 * Returns the DHCP match.
262 * @param srcPort the source port.
263 * @param dstPort the destination port.
264 * @param lportTag the lport tag
265 * @param serviceMode ingress or egress service
266 * @return list of matches.
268 public static List<MatchInfoBase> buildDhcpMatches(int srcPort, int dstPort, int lportTag,
269 Class<? extends ServiceModeBase> serviceMode) {
270 List<MatchInfoBase> matches = new ArrayList<>(5);
271 matches.add(MatchEthernetType.IPV4);
272 matches.add(MatchIpProtocol.UDP);
273 matches.add(new MatchUdpDestinationPort(dstPort));
274 matches.add(new MatchUdpSourcePort(srcPort));
275 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
280 * Returns the DHCPv6 match.
282 * @param srcPort the source port.
283 * @param dstPort the destination port.
284 * @param lportTag the lport tag
285 * @param serviceMode ingress or egress
286 * @return list of matches.
288 public static List<MatchInfoBase> buildDhcpV6Matches(int srcPort, int dstPort, int lportTag,
289 Class<? extends ServiceModeBase> serviceMode) {
290 List<MatchInfoBase> matches = new ArrayList<>(6);
291 matches.add(MatchEthernetType.IPV6);
292 matches.add(MatchIpProtocol.UDP);
293 matches.add(new MatchUdpDestinationPort(dstPort));
294 matches.add(new MatchUdpSourcePort(srcPort));
295 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
300 * Returns the ICMPv6 match.
302 * @param icmpType the icmpv6-type.
303 * @param icmpCode the icmpv6-code.
304 * @param lportTag the lport tag
305 * @param serviceMode ingress or egress
306 * @return list of matches.
308 public static List<MatchInfoBase> buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag,
309 Class<? extends ServiceModeBase> serviceMode) {
310 List<MatchInfoBase> matches = new ArrayList<>();
311 matches.add(MatchEthernetType.IPV6);
312 matches.add(MatchIpProtocol.ICMPV6);
314 matches.add(new MatchIcmpv6((short) icmpType, (short) icmpCode));
316 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
320 public static List<MatchInfoBase> buildBroadcastIpV4Matches(String ipAddr) {
321 List<MatchInfoBase> matches = new ArrayList<>(2);
322 matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
323 matches.addAll(AclServiceUtils.buildIpMatches(IpPrefixOrAddressBuilder.getDefaultInstance(ipAddr),
324 MatchCriteria.MATCH_DESTINATION));
328 public static List<MatchInfoBase> buildL2BroadcastMatches() {
329 List<MatchInfoBase> matches = new ArrayList<>();
330 matches.add(new MatchEthernetDestination(new MacAddress(AclConstants.BROADCAST_MAC)));
335 * Builds the service id.
337 * @param interfaceName the interface name
338 * @param serviceIndex the service index
339 * @param serviceMode the service mode
340 * @return the instance identifier
342 public static InstanceIdentifier<BoundServices> buildServiceId(String interfaceName, short serviceIndex,
343 Class<? extends ServiceModeBase> serviceMode) {
344 return InstanceIdentifier.builder(ServiceBindings.class)
345 .child(ServicesInfo.class, new ServicesInfoKey(interfaceName, serviceMode))
346 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
350 * Gets the bound services.
352 * @param serviceName the service name
353 * @param servicePriority the service priority
354 * @param flowPriority the flow priority
355 * @param cookie the cookie
356 * @param instructions the instructions
357 * @return the bound services
359 public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
360 Uint64 cookie, List<Instruction> instructions) {
361 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
362 .setInstruction(instructions);
363 return new BoundServicesBuilder().withKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
364 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
365 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
368 public static List<Uuid> getUpdatedAclList(List<Uuid> updatedAclList, List<Uuid> currentAclList) {
369 if (updatedAclList == null) {
370 return Collections.emptyList();
372 List<Uuid> newAclList = new ArrayList<>(updatedAclList);
373 if (currentAclList == null) {
376 List<Uuid> origAclList = new ArrayList<>(currentAclList);
377 for (Iterator<Uuid> iterator = newAclList.iterator(); iterator.hasNext();) {
378 Uuid updatedAclUuid = iterator.next();
379 for (Uuid currentAclUuid :origAclList) {
380 if (updatedAclUuid.getValue().equals(currentAclUuid.getValue())) {
389 public static List<AllowedAddressPairs> getUpdatedAllowedAddressPairs(
390 @Nullable List<AllowedAddressPairs> updatedAllowedAddressPairs,
391 @Nullable List<AllowedAddressPairs> currentAllowedAddressPairs) {
392 if (updatedAllowedAddressPairs == null) {
395 List<AllowedAddressPairs> newAllowedAddressPairs = new ArrayList<>(updatedAllowedAddressPairs);
396 if (currentAllowedAddressPairs == null) {
397 return newAllowedAddressPairs;
399 List<AllowedAddressPairs> origAllowedAddressPairs = new ArrayList<>(currentAllowedAddressPairs);
400 for (Iterator<AllowedAddressPairs> iterator = newAllowedAddressPairs.iterator(); iterator.hasNext();) {
401 AllowedAddressPairs updatedAllowedAddressPair = iterator.next();
402 for (AllowedAddressPairs currentAllowedAddressPair : origAllowedAddressPairs) {
403 if (updatedAllowedAddressPair.key().equals(currentAllowedAddressPair.key())) {
409 return newAllowedAddressPairs;
413 public static BigInteger getDpIdFromIterfaceState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
414 .interfaces.rev140508.interfaces.state.Interface interfaceState) {
415 BigInteger dpId = null;
416 List<String> ofportIds = interfaceState.getLowerLayerIf();
417 if (ofportIds != null && !ofportIds.isEmpty()) {
418 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
419 dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
424 public static List<String> getIpBroadcastAddresses(List<SubnetInfo> subnetInfoList) {
425 List<String> ipBroadcastAddresses = new ArrayList<>();
426 for (SubnetInfo subnetInfo : subnetInfoList) {
427 IpPrefix cidrIpPrefix = subnetInfo.getIpPrefix().getIpPrefix();
428 if (cidrIpPrefix != null) {
429 Ipv4Prefix cidrIpv4Prefix = cidrIpPrefix.getIpv4Prefix();
430 if (cidrIpv4Prefix != null) {
431 ipBroadcastAddresses.add(getBroadcastAddressFromCidr(cidrIpv4Prefix.getValue()));
435 return ipBroadcastAddresses;
438 public static String getBroadcastAddressFromCidr(String cidr) {
439 String[] ipaddressValues = cidr.split("/");
440 int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
441 int cidrPart = Integer.parseInt(ipaddressValues[1]);
443 for (int j = 0; j < cidrPart; ++j) {
444 netmask |= 1 << 31 - j;
446 int network = address & netmask;
447 int broadcast = network | ~netmask;
448 return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
452 * Builds the ip matches.
454 * @param ipPrefixOrAddress the ip prefix or address
455 * @param matchCriteria the source_ip or destination_ip used for the match
458 public static List<MatchInfoBase> buildIpMatches(IpPrefixOrAddress ipPrefixOrAddress,
459 MatchCriteria matchCriteria) {
460 List<MatchInfoBase> flowMatches = new ArrayList<>();
461 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
462 if (ipPrefix != null) {
463 Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
464 if (ipv4Prefix != null) {
465 flowMatches.add(MatchEthernetType.IPV4);
466 if (!ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
467 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(ipv4Prefix)
468 : new MatchIpv4Destination(ipv4Prefix));
471 flowMatches.add(MatchEthernetType.IPV6);
472 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
473 ipPrefix.getIpv6Prefix()) : new MatchIpv6Destination(ipPrefix.getIpv6Prefix()));
476 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
477 if (ipAddress.getIpv4Address() != null) {
478 flowMatches.add(MatchEthernetType.IPV4);
479 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(
480 ipAddress.getIpv4Address().getValue(), "32") : new MatchIpv4Destination(
481 ipAddress.getIpv4Address().getValue(), "32"));
483 flowMatches.add(MatchEthernetType.IPV6);
484 flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source(
485 ipAddress.getIpv6Address().getValue() + "/128") : new MatchIpv6Destination(
486 ipAddress.getIpv6Address().getValue() + "/128"));
493 * Builds the arp ip matches.
494 * @param ipPrefixOrAddress the ip prefix or address
495 * @return the MatchInfoBase list
497 public static List<MatchInfoBase> buildArpIpMatches(IpPrefixOrAddress ipPrefixOrAddress) {
498 List<MatchInfoBase> flowMatches = new ArrayList<>();
499 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
500 if (ipPrefix != null) {
501 Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix();
502 if (ipv4Prefix != null && !ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
503 flowMatches.add(new MatchArpSpa(ipv4Prefix));
506 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
507 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
508 flowMatches.add(new MatchArpSpa(ipAddress.getIpv4Address().getValue(), "32"));
514 public static MatchInfoBase buildRemoteAclTagMetadataMatch(Integer remoteAclTag) {
515 return new MatchMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
516 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
519 public static Uint64 getRemoteAclTagMetadata(BigInteger remoteAclTag) {
520 return Uint64.valueOf(remoteAclTag.shiftLeft(4));
523 public static Uint64 getDropFlowCookie(int lport) {
524 return Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lport).longValue()
525 | AclConstants.COOKIE_ACL_DROP_FLOW.longValue());
529 * Does IPv4 address exists in the list of allowed address pair.
531 * @param aaps the allowed address pairs
532 * @return true, if successful
534 public static boolean doesIpv4AddressExists(List<AllowedAddressPairs> aaps) {
538 for (AllowedAddressPairs aap : aaps) {
539 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
540 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
541 if (ipPrefix != null) {
542 if (ipPrefix.getIpv4Prefix() != null) {
546 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
547 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
556 * Does IPv6 address exists in the list of allowed address pair.
558 * @param aaps the allowed address pairs
559 * @return true, if successful
561 public static boolean doesIpv6AddressExists(List<AllowedAddressPairs> aaps) {
565 for (AllowedAddressPairs aap : aaps) {
566 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
567 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
568 if (ipPrefix != null) {
569 if (ipPrefix.getIpv6Prefix() != null) {
573 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
574 if (ipAddress != null && ipAddress.getIpv6Address() != null) {
583 * Gets the lport tag match.
584 * Ingress match is based on metadata and egress match is based on masked reg6
586 * @param lportTag the lport tag
587 * @param serviceMode ingress or egress service mode
588 * @return the lport tag match
590 public static MatchInfoBase buildLPortTagMatch(int lportTag, Class<? extends ServiceModeBase> serviceMode) {
591 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
592 return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(),
593 MetaDataUtil.getLportTagMaskForReg6());
595 return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG);
599 public static List<MatchInfoBase> buildMatchesForLPortTagAndRemoteAclTag(Integer lportTag, Integer remoteAclTag,
600 Class<? extends ServiceModeBase> serviceMode) {
601 List<MatchInfoBase> matches = new ArrayList<>();
602 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
603 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
604 matches.add(AclServiceUtils.buildRemoteAclTagMetadataMatch(remoteAclTag));
606 // In case of ingress service mode, only metadata is used for
607 // matching both lportTag and aclTag. Hence performing "or"
608 // operation on both lportTag and aclTag metadata.
609 Uint64 metaData = Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lportTag).longValue()
610 | (getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)).longValue()));
611 Uint64 metaDataMask = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_LPORT_TAG.longValue()
612 | MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG.longValue());
613 matches.add(new MatchMetadata(metaData, metaDataMask));
618 public static Collection<? extends MatchInfoBase> buildMatchesForLPortTagAndConntrackClassifierType(int lportTag,
619 AclConntrackClassifierType conntrackClassifierType, Class<? extends ServiceModeBase> serviceMode) {
620 List<MatchInfoBase> matches = new ArrayList<>();
621 if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeEgress.class)) {
622 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
623 matches.add(AclServiceUtils.buildAclConntrackClassifierTypeMatch(conntrackClassifierType));
625 // In case of ingress service mode, only metadata is used for
626 // matching both lportTag and conntrackClassifierType. Hence performing "or"
627 // operation on both lportTag and conntrackClassifierType metadata.
628 Uint64 metaData = Uint64.fromLongBits(MetaDataUtil.getLportTagMetaData(lportTag).longValue()
629 | (MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
630 Uint64.valueOf(conntrackClassifierType.getValue()))).longValue());
631 Uint64 metaDataMask = Uint64.fromLongBits(MetaDataUtil.METADATA_MASK_LPORT_TAG.longValue()
632 | MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE.longValue());
633 matches.add(new MatchMetadata(metaData, metaDataMask));
638 public static InstructionWriteMetadata getWriteMetadataForAclClassifierType(
639 AclConntrackClassifierType conntrackClassifierType) {
640 return new InstructionWriteMetadata(MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
641 Uint64.valueOf(conntrackClassifierType.getValue())),
642 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
645 public static InstructionWriteMetadata getWriteMetadataForDropFlag() {
646 return new InstructionWriteMetadata(MetaDataUtil.getAclDropMetaData(AclConstants.METADATA_DROP_FLAG),
647 MetaDataUtil.METADATA_MASK_ACL_DROP);
650 public static InstructionWriteMetadata getWriteMetadataForRemoteAclTag(Integer remoteAclTag) {
651 return new InstructionWriteMetadata(getRemoteAclTagMetadata(BigInteger.valueOf(remoteAclTag)),
652 MetaDataUtil.METADATA_MASK_REMOTE_ACL_TAG);
655 public static MatchInfoBase buildAclConntrackClassifierTypeMatch(
656 AclConntrackClassifierType conntrackSupportedType) {
657 return new MatchMetadata(
658 MetaDataUtil.getAclConntrackClassifierTypeFromMetaData(
659 Uint64.valueOf(conntrackSupportedType.getValue())),
660 MetaDataUtil.METADATA_MASK_ACL_CONNTRACK_CLASSIFIER_TYPE);
663 public AclserviceConfig getConfig() {
667 public static boolean isIPv4Address(AllowedAddressPairs aap) {
668 IpPrefixOrAddress ipPrefixOrAddress = aap.getIpAddress();
669 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
670 if (ipPrefix != null) {
671 if (ipPrefix.getIpv4Prefix() != null) {
675 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
676 if (ipAddress != null && ipAddress.getIpv4Address() != null) {
683 public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) {
684 IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
685 if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null
686 && ipPrefix.getIpv4Prefix().getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
692 protected static boolean isNotIpv6AllNetwork(AllowedAddressPairs aap) {
693 IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix();
694 if (ipPrefix != null && ipPrefix.getIpv6Prefix() != null
695 && ipPrefix.getIpv6Prefix().getValue().equals(AclConstants.IPV6_ALL_NETWORK)) {
701 public static boolean isNotIpAllNetwork(AllowedAddressPairs aap) {
702 return isNotIpv4AllNetwork(aap) && isNotIpv6AllNetwork(aap);
706 public static Long getElanIdFromInterface(String elanInterfaceName, DataBroker broker) {
707 ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker);
708 if (null != elanInterface) {
709 ElanInstance elanInfo = getElanInstanceByName(elanInterface.getElanInstanceName(), broker);
710 return elanInfo != null ? elanInfo.getElanTag().toJava() : null;
716 public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) {
717 InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
718 return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
721 public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
722 return InstanceIdentifier.builder(ElanInterfaces.class)
723 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
726 // elan-instances config container
728 public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
729 InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
730 return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
733 public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
734 return InstanceIdentifier.builder(ElanInstances.class)
735 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
738 public void deleteAcesFromConfigDS(String aclName, List<Ace> deletedAceRules) {
739 List<List<Ace>> acesParts = Lists.partition(deletedAceRules, AclConstants.ACES_PER_TRANSACTION);
740 for (List<Ace> acePart : acesParts) {
741 jobCoordinator.enqueueJob(aclName,
742 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
744 for (Ace ace: acePart) {
745 InstanceIdentifier<Ace> id = InstanceIdentifier.builder(AccessLists.class)
746 .child(Acl.class, new AclKey(aclName, Ipv4Acl.class)).child(AccessListEntries.class)
747 .child(Ace.class, ace.key()).build();
750 })), AclConstants.ACEDELETE_MAX_RETRIES);
754 public static Integer allocateId(IdManagerService idManager, String poolName, String idKey, Integer defaultId) {
755 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
757 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
758 RpcResult<AllocateIdOutput> rpcResult = result.get();
759 if (rpcResult.isSuccessful()) {
760 Integer allocatedId = rpcResult.getResult().getIdValue().intValue();
761 LOG.debug("Allocated ACL ID: {} with key: {} into pool: {}", allocatedId, idKey, poolName);
764 LOG.error("RPC Call to Get Unique Id for key {} from pool {} returned with Errors {}",
765 idKey, poolName, rpcResult.getErrors());
767 } catch (InterruptedException | ExecutionException e) {
768 LOG.error("Exception when getting Unique Id for key {} from pool {} ", idKey, poolName, e);
773 public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
774 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
776 RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
777 if (!rpcResult.isSuccessful()) {
778 LOG.error("RPC Call to release Id with Key {} from pool {} returned with Errors {}",
779 idKey, poolName, rpcResult.getErrors());
781 LOG.debug("Released ACL ID with key: {} from pool: {}", idKey, poolName);
783 } catch (InterruptedException | ExecutionException e) {
784 LOG.error("Exception when releasing Id for key {} from pool {} ", idKey, poolName, e);
789 * Gets the ACL tag from cache. If not found in cache, tries to allocate and
792 * @param aclId the acl id
793 * @return the acl tag
796 public Integer getAclTag(final Uuid aclId) {
797 String aclName = aclId.getValue();
798 Integer aclTag = this.aclDataUtil.getAclTag(aclName);
799 if (aclTag == null) {
800 LOG.debug("ACL tag not found in cache for ACL={}, trying to allocate again.", aclName);
801 aclTag = allocateAclTag(aclName);
802 if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
803 this.aclDataUtil.addAclTag(aclName, aclTag);
812 * @param aclName the ACL name
813 * @return the integer
815 public Integer allocateAclTag(String aclName) {
816 return AclServiceUtils.allocateId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName,
817 AclConstants.INVALID_ACL_TAG);
823 * @param aclName the ACL name
825 public void releaseAclTag(String aclName) {
826 AclServiceUtils.releaseId(this.idManager, AclConstants.ACL_TAG_POOL_NAME, aclName);
830 * Indicates whether the interface has port security enabled or interface is DHCP service port.
832 * @param aclInterface the interface.
833 * @return true if port is security enabled or is a DHCP service port.
835 public static boolean isOfInterest(AclInterface aclInterface) {
836 return aclInterface != null && (aclInterface.isPortSecurityEnabled()
837 || aclInterface.getInterfaceType() == InterfaceAcl.InterfaceType.DhcpService);
841 * Indicates whether the interface has port security enabled or interface is DHCP service port.
843 * @param aclInterface the interface.
844 * @return true if port is security enabled or is a DHCP service port.
846 public static boolean isOfInterest(InterfaceAcl aclInterface) {
847 return aclInterface != null && (aclInterface.isPortSecurityEnabled()
848 || aclInterface.getInterfaceType() == InterfaceAcl.InterfaceType.DhcpService);
852 * Creates the id pool for ACL tag.
854 * @param poolName the pool name
856 private void createIdPoolForAclTag(String poolName) {
857 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
858 .setPoolName(poolName).setLow(AclConstants.ACL_TAG_POOL_START)
859 .setHigh(AclConstants.ACL_TAG_POOL_END).build();
861 Future<RpcResult<CreateIdPoolOutput>> result = this.idManager.createIdPool(createPool);
862 if (result != null && result.get().isSuccessful()) {
863 LOG.debug("Created IdPool for {}", poolName);
865 } catch (InterruptedException | ExecutionException e) {
866 LOG.error("Failed to create ID pool [{}] for remote ACL ids", poolName, e);
867 throw new RuntimeException("Failed to create ID pool [{}] for remote ACL ids", e);
874 * @param poolName the pool name
876 public void deleteIdPool(String poolName) {
877 DeleteIdPoolInput deletePool = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
879 Future<RpcResult<DeleteIdPoolOutput>> result = this.idManager.deleteIdPool(deletePool);
880 if (result != null && result.get().isSuccessful()) {
881 LOG.debug("Deleted IdPool for {}", poolName);
883 } catch (InterruptedException | ExecutionException e) {
884 LOG.error("Failed to delete ID pool [{}]", poolName, e);
885 throw new RuntimeException("Failed to delete ID pool [" + poolName + "]", e);
890 * Creates remote the acl id pools.
892 public void createRemoteAclIdPool() {
893 createIdPoolForAclTag(AclConstants.ACL_TAG_POOL_NAME);
897 * Delete remote the acl id pools.
899 public void deleteRemoteAclIdPool() {
900 deleteIdPool(AclConstants.ACL_TAG_POOL_NAME);
903 public static List<? extends MatchInfoBase> buildIpAndSrcServiceMatch(Integer aclTag, AllowedAddressPairs aap) {
904 List<MatchInfoBase> flowMatches = new ArrayList<>();
905 flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
906 if (aap.getIpAddress().getIpAddress() != null) {
907 if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
908 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
909 flowMatches.add(ipv4EthMatch);
910 MatchIpv4Source srcMatch = new MatchIpv4Source(
911 new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
912 flowMatches.add(srcMatch);
913 } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
914 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
915 flowMatches.add(ipv6EthMatch);
916 MatchIpv6Source srcMatch = new MatchIpv6Source(
917 new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
918 flowMatches.add(srcMatch);
920 } else if (aap.getIpAddress().getIpPrefix() != null) {
921 if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
922 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
923 flowMatches.add(ipv4EthMatch);
924 MatchIpv4Source srcMatch = new MatchIpv4Source(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
925 flowMatches.add(srcMatch);
926 } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
927 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
928 flowMatches.add(ipv6EthMatch);
929 MatchIpv6Source srcMatch = new MatchIpv6Source(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
930 flowMatches.add(srcMatch);
936 public static List<? extends MatchInfoBase> buildIpAndDstServiceMatch(Integer aclTag, AllowedAddressPairs aap) {
937 List<MatchInfoBase> flowMatches = new ArrayList<>();
938 flowMatches.add(buildRemoteAclTagMetadataMatch(aclTag));
940 if (aap.getIpAddress().getIpAddress() != null) {
941 if (aap.getIpAddress().getIpAddress().getIpv4Address() != null) {
942 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
943 flowMatches.add(ipv4EthMatch);
944 MatchIpv4Destination dstMatch = new MatchIpv4Destination(
945 new Ipv4Prefix(aap.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32"));
946 flowMatches.add(dstMatch);
947 } else if (aap.getIpAddress().getIpAddress().getIpv6Address() != null) {
948 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
949 flowMatches.add(ipv6EthMatch);
950 MatchIpv6Destination dstMatch = new MatchIpv6Destination(
951 new Ipv6Prefix(aap.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128"));
952 flowMatches.add(dstMatch);
954 } else if (aap.getIpAddress().getIpPrefix() != null) {
955 if (aap.getIpAddress().getIpPrefix().getIpv4Prefix() != null) {
956 MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4);
957 flowMatches.add(ipv4EthMatch);
958 MatchIpv4Destination dstMatch =
959 new MatchIpv4Destination(aap.getIpAddress().getIpPrefix().getIpv4Prefix());
960 flowMatches.add(dstMatch);
961 } else if (aap.getIpAddress().getIpPrefix().getIpv6Prefix() != null) {
962 MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6);
963 flowMatches.add(ipv6EthMatch);
964 MatchIpv6Destination dstMatch =
965 new MatchIpv6Destination(aap.getIpAddress().getIpPrefix().getIpv6Prefix());
966 flowMatches.add(dstMatch);
972 public static List<Ace> getAceListFromAcl(Acl acl) {
973 if (acl.getAccessListEntries() != null) {
974 List<Ace> aceList = acl.getAccessListEntries().getAce();
975 if (aceList != null && !aceList.isEmpty()
976 && aceList.get(0).augmentation(SecurityRuleAttr.class) != null) {
980 return Collections.emptyList();
984 * Builds the ip protocol matches.
986 * @param etherType the ether type
987 * @param protocol the protocol
988 * @return the list of matches.
990 public static List<MatchInfoBase> buildIpProtocolMatches(MatchEthernetType etherType, IPProtocols protocol) {
991 return Lists.newArrayList(etherType, new MatchIpProtocol(protocol.shortValue()));
995 * Does ACE have remote group id.
997 * @param aceAttr the ace attr
998 * @return true, if successful
1000 public static boolean doesAceHaveRemoteGroupId(final SecurityRuleAttr aceAttr) {
1001 return aceAttr != null && aceAttr.getRemoteGroupId() != null;
1004 public SortedSet<Integer> getRemoteAclTags(@Nullable List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
1005 SortedSet<Integer> remoteAclTags = new TreeSet<>();
1006 Set<Uuid> remoteAclIds = getRemoteAclIdsByDirection(aclIds, direction);
1007 for (Uuid remoteAclId : remoteAclIds) {
1008 Integer remoteAclTag = getAclTag(remoteAclId);
1009 if (remoteAclTag != null && remoteAclTag != AclConstants.INVALID_ACL_TAG) {
1010 remoteAclTags.add(remoteAclTag);
1013 return remoteAclTags;
1016 public Set<Uuid> getRemoteAclIdsByDirection(@Nullable List<Uuid> aclIds, Class<? extends DirectionBase> direction) {
1017 Set<Uuid> remoteAclIds = new HashSet<>();
1018 if (aclIds == null || aclIds.isEmpty()) {
1019 return remoteAclIds;
1022 for (Uuid aclId : aclIds) {
1023 Acl acl = this.aclDataUtil.getAcl(aclId.getValue());
1025 LOG.warn("ACL {} not found in cache.", aclId.getValue());
1028 remoteAclIds.addAll(getRemoteAclIdsByDirection(acl, direction));
1030 return remoteAclIds;
1033 public static Set<Uuid> getRemoteAclIdsByDirection(Acl acl, Class<? extends DirectionBase> direction) {
1034 Set<Uuid> remoteAclIds = new HashSet<>();
1035 AccessListEntries accessListEntries = acl.getAccessListEntries();
1036 if (accessListEntries != null && accessListEntries.getAce() != null) {
1037 for (Ace ace : accessListEntries.getAce()) {
1038 SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
1039 if (aceAttr != null && Objects.equals(aceAttr.getDirection(), direction)
1040 && doesAceHaveRemoteGroupId(aceAttr)) {
1041 remoteAclIds.add(aceAttr.getRemoteGroupId());
1045 return remoteAclIds;
1049 * Skip delete in case of overlapping IP.
1052 * When there are multiple ports (e.g., p1, p2, p3) having same AAP (e.g.,
1053 * 224.0.0.5) configured which are part of single SG, there would be single
1054 * flow in remote ACL table. When one of these ports (say p1) is deleted,
1055 * the single flow which is configured in remote ACL table shouldn't be
1056 * deleted. It should be deleted only when there are no more references to
1059 * @param portId the port id
1060 * @param remoteAclId the remote Acl Id
1061 * @param ipPrefix the ip prefix
1062 * @param addOrRemove the add or remove
1063 * @return true, if successful
1065 public boolean skipDeleteInCaseOfOverlappingIP(String portId, Uuid remoteAclId, IpPrefixOrAddress ipPrefix,
1067 boolean skipDelete = false;
1068 if (addOrRemove != NwConstants.DEL_FLOW) {
1071 AclIpPrefixes aclIpPrefixes = getAclIpPrefixesFromOperDs(remoteAclId.getValue(), ipPrefix);
1072 if (aclIpPrefixes != null && aclIpPrefixes.getPortIds() != null) {
1073 List<String> ignorePorts = Lists.newArrayList(portId);
1074 List<PortIds> portIds = new ArrayList<>(aclIpPrefixes.getPortIds());
1075 // Checking if there are any other ports excluding ignorePorts
1076 long noOfRemotePorts =
1077 portIds.stream().map(PortIds::getPortId).filter(y -> !ignorePorts.contains(y)).count();
1078 if (noOfRemotePorts > 0) {
1085 public static InstanceIdentifier<AclPortsByIp> aclPortsByIpPath(String aclName) {
1086 return InstanceIdentifier.builder(AclPortsLookup.class)
1087 .child(AclPortsByIp.class, new AclPortsByIpKey(aclName)).build();
1090 public static InstanceIdentifier<AclIpPrefixes> getAclIpPrefixesPath(String aclName, IpPrefixOrAddress ipPrefix) {
1091 return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(aclName))
1092 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).build();
1095 public static InstanceIdentifier<PortIds> getPortIdsPathInAclPortsLookup(String ruleName,
1096 IpPrefixOrAddress ipPrefix, String portId) {
1097 return InstanceIdentifier.builder(AclPortsLookup.class).child(AclPortsByIp.class, new AclPortsByIpKey(ruleName))
1098 .child(AclIpPrefixes.class, new AclIpPrefixesKey(ipPrefix)).child(PortIds.class, new PortIdsKey(portId))
1102 public void addAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
1103 LOG.debug("Processing interface additions for port {}", portAfter.getInterfaceId());
1104 List<AllowedAddressPairs> addedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1105 portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
1106 if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
1107 addAclPortsLookup(portAfter, portAfter.getSecurityGroups(), addedAllowedAddressPairs);
1110 List<Uuid> addedAcls = getUpdatedAclList(portAfter.getSecurityGroups(), portBefore.getSecurityGroups());
1111 if (addedAcls != null && !addedAcls.isEmpty()) {
1112 addAclPortsLookup(portAfter, addedAcls, portAfter.getAllowedAddressPairs());
1116 public void deleteAclPortsLookupForInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
1117 LOG.debug("Processing interface removals for port {}", portAfter.getInterfaceId());
1118 List<AllowedAddressPairs> deletedAllowedAddressPairs = getUpdatedAllowedAddressPairs(
1119 portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
1120 if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
1121 deleteAclPortsLookup(portAfter, portAfter.getSecurityGroups(), deletedAllowedAddressPairs);
1124 List<Uuid> deletedAcls = getUpdatedAclList(portBefore.getSecurityGroups(), portAfter.getSecurityGroups());
1125 if (deletedAcls != null && !deletedAcls.isEmpty()) {
1126 deleteAclPortsLookup(portAfter, deletedAcls, portAfter.getAllowedAddressPairs());
1130 public void addAclPortsLookup(AclInterface port, List<Uuid> aclList,
1131 List<AllowedAddressPairs> allowedAddresses) {
1132 String portId = port.getInterfaceId();
1133 LOG.trace("Adding AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1135 if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1136 LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1141 for (Uuid aclId : aclList) {
1142 String aclName = aclId.getValue();
1143 jobCoordinator.enqueueJob(aclName, () -> {
1144 List<ListenableFuture<Void>> futures = new ArrayList<>();
1145 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
1146 for (AllowedAddressPairs aap : allowedAddresses) {
1148 new PortIdsBuilder().withKey(new PortIdsKey(portId)).setPortId(portId).build();
1149 InstanceIdentifier<PortIds> path =
1150 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1151 tx.put(path, portIdObj, CREATE_MISSING_PARENTS);
1159 public void deleteAclPortsLookup(AclInterface port, List<Uuid> aclList,
1160 List<AllowedAddressPairs> allowedAddresses) {
1161 String portId = port.getInterfaceId();
1162 LOG.trace("Deleting AclPortsLookup for port={}, acls={}, AAPs={}", portId, aclList, allowedAddresses);
1164 if (aclList == null || allowedAddresses == null || allowedAddresses.isEmpty()) {
1165 LOG.warn("aclList or allowedAddresses is null. port={}, acls={}, AAPs={}", portId, aclList,
1170 for (Uuid aclId : aclList) {
1171 String aclName = aclId.getValue();
1172 jobCoordinator.enqueueJob(aclName, () -> {
1173 List<ListenableFuture<Void>> futures = new ArrayList<>();
1174 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
1175 for (AllowedAddressPairs aap : allowedAddresses) {
1176 InstanceIdentifier<PortIds> path =
1177 AclServiceUtils.getPortIdsPathInAclPortsLookup(aclName, aap.getIpAddress(), portId);
1181 cleanUpStaleEntriesInAclPortsLookup(aclName, tx);
1188 private void cleanUpStaleEntriesInAclPortsLookup(String aclName, TypedWriteTransaction<Operational> tx) {
1189 AclPortsByIp aclPortsByIp = getAclPortsByIpFromOperDs(aclName);
1190 if (aclPortsByIp == null) {
1193 boolean deleteEntireAcl;
1194 List<AclIpPrefixes> ipPrefixes = aclPortsByIp.getAclIpPrefixes();
1195 if (ipPrefixes == null || ipPrefixes.isEmpty()) {
1196 deleteEntireAcl = true;
1198 boolean deleteMap = true;
1199 for (AclIpPrefixes ipPrefix : ipPrefixes) {
1200 if (ipPrefix.getPortIds() != null && !ipPrefix.getPortIds().isEmpty()) {
1205 deleteEntireAcl = deleteMap;
1207 if (deleteEntireAcl) {
1208 tx.delete(AclServiceUtils.aclPortsByIpPath(aclName));
1210 for (AclIpPrefixes ipPrefix : ipPrefixes) {
1211 if (ipPrefix.getPortIds() == null || ipPrefix.getPortIds().isEmpty()) {
1212 InstanceIdentifier<AclIpPrefixes> delPath =
1213 AclServiceUtils.getAclIpPrefixesPath(aclName, ipPrefix.getIpPrefix());
1221 private AclPortsByIp getAclPortsByIpFromOperDs(String aclName) {
1222 InstanceIdentifier<AclPortsByIp> path = aclPortsByIpPath(aclName);
1223 try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
1224 return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
1225 } catch (ReadFailedException e) {
1226 LOG.error("Failed to read ACL ports {}", path, e);
1232 private AclIpPrefixes getAclIpPrefixesFromOperDs(String aclName, IpPrefixOrAddress ipPrefix) {
1233 InstanceIdentifier<AclIpPrefixes> path = getAclIpPrefixesPath(aclName, ipPrefix);
1234 try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction()) {
1235 return tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet().orNull();
1236 } catch (ReadFailedException e) {
1237 LOG.error("Failed to read ACL IP prefixes {}", path, e);
1243 * Gets the ace flow priority.
1245 * @param aclName the acl name
1246 * @return the ace flow priority
1248 public Integer getAceFlowPriority(String aclName) {
1249 Integer priority = AclConstants.ACE_DEFAULT_PRIORITY;
1250 Integer aclTag = getAclTag(new Uuid(aclName));
1251 if (aclTag != null && aclTag != AclConstants.INVALID_ACL_TAG) {
1252 // To handle overlapping rules, aclTag is added to priority
1255 LOG.warn("aclTag={} is null or invalid for aclName={}", aclTag, aclName);
1261 * Returns the hard timeout based on the protocol when a ACL rule removed from the instance.
1262 * It will returns the timeout configured in the {@link AclserviceConfig} class.
1264 * @param ace the ace
1265 * @param aclServiceUtils acl service utils
1266 * @return the hard time out
1268 public static Integer getHardTimoutForApplyStatefulChangeOnExistingTraffic(Ace ace,
1269 AclServiceUtils aclServiceUtils) {
1270 int hardTimeout = AclConstants.SECURITY_GROUP_ICMP_IDLE_TIME_OUT;
1271 Matches matches = ace.getMatches();
1272 AceIp acl = (AceIp) matches.getAceType();
1273 Short protocol = acl.getProtocol() != null ? acl.getProtocol().toJava() : null;
1274 if (protocol == null) {
1276 } else if (protocol == NwConstants.IP_PROT_TCP
1277 && aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout() != null) {
1278 hardTimeout = aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout().toJava();
1279 } else if (protocol == NwConstants.IP_PROT_UDP
1280 && aclServiceUtils.getConfig().getSecurityGroupTcpIdleTimeout() != null) {
1281 hardTimeout = aclServiceUtils.getConfig().getSecurityGroupUdpIdleTimeout().toJava();
1287 * This method creates and returns the ct_mark instruction when a ACL rule removed from the
1288 * instance. This instruction will reset the ct_mark value and stops the existing traffics.
1290 * @param filterTable the filterTable
1291 * @param elanId the Elan id
1292 * @return list of instruction
1294 public static List<InstructionInfo> createCtMarkInstructionForNewState(Short filterTable, Long elanId) {
1296 List<InstructionInfo> instructions = new ArrayList<>();
1297 List<ActionInfo> actionsInfos = new ArrayList<>();
1298 List<NxCtAction> ctActionsList = new ArrayList<>();
1299 NxCtAction nxCtMarkClearAction = new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_NEW_STATE);
1300 ctActionsList.add(nxCtMarkClearAction);
1302 ActionNxConntrack actionNxConntrack = new ActionNxConntrack(2, 1, 0, elanId.intValue(),
1303 (short) 255, ctActionsList);
1304 actionsInfos.add(actionNxConntrack);
1305 instructions.add(new InstructionApplyActions(actionsInfos));
1306 instructions.add(new InstructionGotoTable(filterTable));
1308 return instructions;
1311 public static List<AllowedAddressPairs> excludeMulticastAAPs(@Nullable List<AllowedAddressPairs> allowedAddresses) {
1312 List<AllowedAddressPairs> filteredAAPs = new ArrayList<>();
1313 if (allowedAddresses != null) {
1314 for (AllowedAddressPairs allowedAddress : allowedAddresses) {
1315 InetAddress inetAddr = getInetAddress(allowedAddress.getIpAddress());
1316 if (inetAddr != null && !inetAddr.isMulticastAddress()) {
1317 filteredAAPs.add(allowedAddress);
1321 return filteredAAPs;
1324 public static String getRecoverServiceRegistryKey() {
1325 return NetvirtAcl.class.toString();
1329 private static InetAddress getInetAddress(IpPrefixOrAddress ipPrefixOrAddress) {
1332 IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
1333 if (ipPrefix != null) {
1334 addr = ipPrefix.stringValue().split("/")[0];
1336 IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
1337 if (ipAddress == null) {
1338 LOG.error("Invalid address : {}", ipPrefixOrAddress);
1341 addr = ipAddress.stringValue();
1345 return InetAddress.getByName(addr);
1346 } catch (UnknownHostException e) {
1347 LOG.error("Invalid address : {}", addr, e);
1352 public static Boolean isIpv6Subnet(List<SubnetInfo> subnetInfoList) {
1353 if (subnetInfoList != null && !subnetInfoList.isEmpty()) {
1354 for (SubnetInfo subnetInfo : subnetInfoList) {
1355 if (subnetInfo != null && IpVersionV6.class.equals(subnetInfo.getIpVersion())) {
1364 * Gets the subnet difference by performing (subnetInfo1 - subnetInfo2).
1366 * @param subnetInfo1 the subnet info 1
1367 * @param subnetInfo2 the subnet info 2
1368 * @return the subnet diff
1370 public static List<SubnetInfo> getSubnetDiff(List<SubnetInfo> subnetInfo1, List<SubnetInfo> subnetInfo2) {
1371 if (subnetInfo1 == null) {
1372 return Collections.emptyList();
1374 List<SubnetInfo> newSubnetList = new ArrayList<>(subnetInfo1);
1375 if (subnetInfo2 == null) {
1376 return newSubnetList;
1378 newSubnetList.removeAll(subnetInfo2);
1379 return newSubnetList;