X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=vpnservice%2Faclservice%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Faclservice%2Futils%2FAclServiceUtils.java;h=719e9ec84e878c08836ee31bdb3077c77208060d;hb=414e98dd1bc98809689ea89315eb8dd6bccc1988;hp=2f70839018b09816d1824110e57d2c184444432d;hpb=2e17a47b37c41e7bacca5eda54fcdfdf727030f4;p=netvirt.git diff --git a/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java b/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java index 2f70839018..719e9ec84e 100644 --- a/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java +++ b/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java @@ -9,7 +9,6 @@ package org.opendaylight.netvirt.aclservice.utils; import com.google.common.base.Optional; - import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; @@ -18,19 +17,17 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; - import javax.inject.Inject; import javax.inject.Singleton; - import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil; import org.opendaylight.genius.mdsalutil.MDSALUtil; -import org.opendaylight.genius.mdsalutil.MatchInfo; import org.opendaylight.genius.mdsalutil.MatchInfoBase; import org.opendaylight.genius.mdsalutil.MetaDataUtil; -import org.opendaylight.genius.mdsalutil.NxMatchFieldType; +import org.opendaylight.genius.mdsalutil.NwConstants; import org.opendaylight.genius.mdsalutil.NxMatchInfo; import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType; import org.opendaylight.genius.mdsalutil.matches.MatchIcmpv6; @@ -42,15 +39,23 @@ import org.opendaylight.genius.mdsalutil.matches.MatchIpv6Source; import org.opendaylight.genius.mdsalutil.matches.MatchMetadata; import org.opendaylight.genius.mdsalutil.matches.MatchUdpDestinationPort; import org.opendaylight.genius.mdsalutil.matches.MatchUdpSourcePort; +import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister; import org.opendaylight.netvirt.aclservice.api.AclServiceManager.MatchCriteria; import org.opendaylight.netvirt.aclservice.api.utils.AclInterface; +import org.opendaylight.netvirt.aclservice.api.utils.AclInterfaceCacheUtil; +import org.opendaylight.netvirt.vpnmanager.api.VpnHelper; +import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.PacketHandling; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; @@ -60,6 +65,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder; @@ -69,6 +78,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpc import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder; @@ -89,6 +99,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; @@ -101,15 +112,19 @@ import org.slf4j.LoggerFactory; public final class AclServiceUtils { private static final Logger LOG = LoggerFactory.getLogger(AclServiceUtils.class); + public static final AclserviceConfig.DefaultBehavior DEFAULT_DENY = AclserviceConfig.DefaultBehavior.Deny; + public static final AclserviceConfig.DefaultBehavior DEFAULT_ALLOW = AclserviceConfig.DefaultBehavior.Allow; private final AclDataUtil aclDataUtil; private final AclserviceConfig config; + private final IdManagerService idManager; @Inject - public AclServiceUtils(AclDataUtil aclDataUtil, AclserviceConfig config) { + public AclServiceUtils(AclDataUtil aclDataUtil, AclserviceConfig config, IdManagerService idManager) { super(); this.aclDataUtil = aclDataUtil; this.config = config; + this.idManager = idManager; } /** @@ -149,7 +164,7 @@ public final class AclServiceUtils { try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) { return tx.read(datastoreType, path).checkedGet(); } catch (ReadFailedException e) { - LOG.warn("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e); + LOG.error("Failed to read InstanceIdentifier {} from {}", path, datastoreType, e); return Optional.absent(); } } @@ -283,15 +298,17 @@ public final class AclServiceUtils { * @param srcPort the source port. * @param dstPort the destination port. * @param lportTag the lport tag + * @param serviceMode ingress or egress service * @return list of matches. */ - public static List buildDhcpMatches(int srcPort, int dstPort, int lportTag) { + public static List buildDhcpMatches(int srcPort, int dstPort, int lportTag, + Class serviceMode) { List matches = new ArrayList<>(6); matches.add(MatchEthernetType.IPV4); matches.add(MatchIpProtocol.UDP); matches.add(new MatchUdpDestinationPort(dstPort)); matches.add(new MatchUdpSourcePort(srcPort)); - matches.add(AclServiceUtils.buildLPortTagMatch(lportTag)); + matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode)); return matches; } @@ -301,15 +318,17 @@ public final class AclServiceUtils { * @param srcPort the source port. * @param dstPort the destination port. * @param lportTag the lport tag + * @param serviceMode ingress or egress * @return list of matches. */ - public static List buildDhcpV6Matches(int srcPort, int dstPort, int lportTag) { + public static List buildDhcpV6Matches(int srcPort, int dstPort, int lportTag, + Class serviceMode) { List matches = new ArrayList<>(6); matches.add(MatchEthernetType.IPV6); matches.add(MatchIpProtocol.UDP); matches.add(new MatchUdpDestinationPort(dstPort)); matches.add(new MatchUdpSourcePort(srcPort)); - matches.add(AclServiceUtils.buildLPortTagMatch(lportTag)); + matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode)); return matches; } @@ -319,16 +338,18 @@ public final class AclServiceUtils { * @param icmpType the icmpv6-type. * @param icmpCode the icmpv6-code. * @param lportTag the lport tag + * @param serviceMode ingress or egress * @return list of matches. */ - public static List buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag) { + public static List buildIcmpV6Matches(int icmpType, int icmpCode, int lportTag, + Class serviceMode) { List matches = new ArrayList<>(6); matches.add(MatchEthernetType.IPV6); matches.add(MatchIpProtocol.ICMPV6); if (icmpType != 0) { matches.add(new MatchIcmpv6((short) icmpType, (short) icmpCode)); } - matches.add(AclServiceUtils.buildLPortTagMatch(lportTag)); + matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode)); return matches; } @@ -445,10 +466,13 @@ public final class AclServiceUtils { List flowMatches = new ArrayList<>(); IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix(); if (ipPrefix != null) { - if (ipPrefix.getIpv4Prefix() != null) { + Ipv4Prefix ipv4Prefix = ipPrefix.getIpv4Prefix(); + if (ipv4Prefix != null) { flowMatches.add(MatchEthernetType.IPV4); - flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source( - ipPrefix.getIpv4Prefix()) : new MatchIpv4Destination(ipPrefix.getIpv4Prefix())); + if (!ipv4Prefix.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) { + flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv4Source(ipv4Prefix) + : new MatchIpv4Destination(ipv4Prefix)); + } } else { flowMatches.add(MatchEthernetType.IPV6); flowMatches.add(matchCriteria == MatchCriteria.MATCH_SOURCE ? new MatchIpv6Source( @@ -471,14 +495,43 @@ public final class AclServiceUtils { return flowMatches; } + private List buildAclIdMetadataMatch(Uuid remoteAclId) { + List flowMatches = new ArrayList<>(); + BigInteger aclId = buildAclId(remoteAclId); + if (aclId.intValue() != AclConstants.INVALID_ACL_ID) { + MatchMetadata metadataMatch = new MatchMetadata(getAclIdMetadata(aclId), + MetaDataUtil.METADATA_MASK_REMOTE_ACL_ID); + flowMatches.add(metadataMatch); + } else { + LOG.error("Failed building metadata match for Acl id match. Failed to allocate id"); + } + return flowMatches; + } + + public BigInteger buildAclId(Uuid remoteAclId) { + Integer aclId = allocateAclId(remoteAclId.getValue()); + return BigInteger.valueOf(aclId); + } + + public static BigInteger getAclIdMetadata(BigInteger aclId) { + return aclId.shiftLeft(1); + } + /** * Gets the lport tag match. + * Ingress match is based on metadata and egress match is based on masked reg6 * * @param lportTag the lport tag + * @param serviceMode ingress or egress service mode * @return the lport tag match */ - public static MatchInfo buildLPortTagMatch(int lportTag) { - return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG); + public static MatchInfoBase buildLPortTagMatch(int lportTag, Class serviceMode) { + if (serviceMode != null && serviceMode.isAssignableFrom(ServiceModeIngress.class)) { + return new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getLportTagForReg6(lportTag).longValue(), + MetaDataUtil.getLportTagMaskForReg6()); + } else { + return new MatchMetadata(MetaDataUtil.getLportTagMetaData(lportTag), MetaDataUtil.METADATA_MASK_LPORT_TAG); + } } public static List getAceWithRemoteAclId(DataBroker dataBroker, AclInterface port, Uuid remoteAcl) { @@ -497,42 +550,54 @@ public final class AclServiceUtils { return remoteAclRuleList; } - public Map> getFlowForRemoteAcl(Uuid remoteAclId, String ignoreInterfaceId, - Map> - flowMatchesMap, boolean - isSourceIpMacMatch) { - List interfaceList = aclDataUtil.getInterfaceList(remoteAclId); - if (flowMatchesMap == null || interfaceList == null || interfaceList.isEmpty()) { - return null; + public Map> getFlowForRemoteAcl(AclInterface aclInterface, Uuid remoteAclId, + String ignoreInterfaceId, Map> flowMatchesMap, boolean isSourceIpMacMatch) { + boolean singleAcl = false; + List interfaceList = null; + if (aclInterface.getSecurityGroups() != null && aclInterface.getSecurityGroups().size() == 1) { + singleAcl = true; + } else { + interfaceList = aclDataUtil.getInterfaceList(remoteAclId); + if (flowMatchesMap == null || interfaceList == null || interfaceList.isEmpty()) { + return null; + } } Map> updatedFlowMatchesMap = new HashMap<>(); MatchInfoBase ipv4Match = MatchEthernetType.IPV4; MatchInfoBase ipv6Match = MatchEthernetType.IPV6; for (String flowName : flowMatchesMap.keySet()) { List flows = flowMatchesMap.get(flowName); + if (singleAcl) { + LOG.debug("port {} is in only one SG. " + + "Doesn't adding it's IPs {} to matches (handled in acl id match)", + aclInterface.getLPortTag(), aclInterface.getAllowedAddressPairs()); + List matchInfoBaseList = addFlowMatchForAclId(remoteAclId, flows); + String flowId = flowName + "_remoteACL_id_" + remoteAclId.getValue(); + updatedFlowMatchesMap.put(flowId, matchInfoBaseList); + continue; + } for (AclInterface port : interfaceList) { if (port.getInterfaceId().equals(ignoreInterfaceId)) { continue; } - //get allow address pair + + // get allow address pair List allowedAddressPair = port.getAllowedAddressPairs(); // iterate over allow address pair and update match type for (AllowedAddressPairs aap : allowedAddressPair) { List matchInfoBaseList; String flowId; - if (flows.contains(ipv4Match) && isIPv4Address(aap)) { + if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) { matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap); - flowId = flowName + "_ipv4_remoteACL_interface_aap_" + aap.getKey(); + flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap); updatedFlowMatchesMap.put(flowId, matchInfoBaseList); - } else if (flows.contains(ipv6Match) && !isIPv4Address(aap)) { + } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) { matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap); - flowId = flowName + "_ipv6_remoteACL_interface_aap_" + aap.getKey(); + flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap); updatedFlowMatchesMap.put(flowId, matchInfoBaseList); } } - } - } return updatedFlowMatchesMap; } @@ -557,11 +622,9 @@ public final class AclServiceUtils { return false; } - public static Map> getFlowForAllowedAddresses(List - syncAllowedAddresses, - Map> - flowMatchesMap, boolean - isSourceIpMacMatch) { + public static Map> getFlowForAllowedAddresses( + List syncAllowedAddresses, Map> flowMatchesMap, + boolean isSourceIpMacMatch) { if (flowMatchesMap == null) { return null; } @@ -574,21 +637,42 @@ public final class AclServiceUtils { for (AllowedAddressPairs aap : syncAllowedAddresses) { List matchInfoBaseList; String flowId; - if (flows.contains(ipv4Match) && isIPv4Address(aap)) { + if (flows.contains(ipv4Match) && isIPv4Address(aap) && isNotIpv4AllNetwork(aap)) { matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap); - flowId = flowName + "_ipv4_remoteACL_interface_aap_" + aap.getKey(); + flowId = flowName + "_ipv4_remoteACL_interface_aap_" + getAapFlowId(aap); updatedFlowMatchesMap.put(flowId, matchInfoBaseList); - } else if (flows.contains(ipv6Match) && !isIPv4Address(aap)) { + } else if (flows.contains(ipv6Match) && !isIPv4Address(aap) && isNotIpv6AllNetwork(aap)) { matchInfoBaseList = updateAAPMatches(isSourceIpMacMatch, flows, aap); - flowId = flowName + "_ipv6_remoteACL_interface_aap_" + aap.getKey(); + flowId = flowName + "_ipv6_remoteACL_interface_aap_" + getAapFlowId(aap); updatedFlowMatchesMap.put(flowId, matchInfoBaseList); } } - } return updatedFlowMatchesMap; } + public static boolean isNotIpv4AllNetwork(AllowedAddressPairs aap) { + IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix(); + if (ipPrefix != null && ipPrefix.getIpv4Prefix() != null + && ipPrefix.getIpv4Prefix().getValue().equals(AclConstants.IPV4_ALL_NETWORK)) { + return false; + } + return true; + } + + protected static boolean isNotIpv6AllNetwork(AllowedAddressPairs aap) { + IpPrefix ipPrefix = aap.getIpAddress().getIpPrefix(); + if (ipPrefix != null && ipPrefix.getIpv6Prefix() != null + && ipPrefix.getIpv6Prefix().getValue().equals(AclConstants.IPV6_ALL_NETWORK)) { + return false; + } + return true; + } + + private static String getAapFlowId(AllowedAddressPairs aap) { + return aap.getMacAddress().getValue() + "_" + String.valueOf(aap.getIpAddress().getValue()); + } + public static Long getElanIdFromInterface(String elanInterfaceName,DataBroker broker) { ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(elanInterfaceName, broker); if (null != elanInterface) { @@ -598,6 +682,14 @@ public final class AclServiceUtils { return null; } + public static Long getElanIdFromAclInterface(String elanInterfaceName) { + AclInterface aclInterface = AclInterfaceCacheUtil.getAclInterfaceFromCache(elanInterfaceName); + if (null != aclInterface) { + return aclInterface.getElanId(); + } + return null; + } + public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName,DataBroker broker) { InstanceIdentifier elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName); return read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull(); @@ -619,6 +711,14 @@ public final class AclServiceUtils { .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build(); } + public static Long getVpnIdFromInterface(DataBroker broker, String vpnInterfaceName) { + VpnInterface vpnInterface = VpnHelper.getVpnInterface(broker, vpnInterfaceName); + if (vpnInterface != null) { + return VpnHelper.getVpnId(broker, vpnInterface.getVpnInstanceName()); + } + return null; + } + private static List updateAAPMatches(boolean isSourceIpMacMatch, List flows, AllowedAddressPairs aap) { List matchInfoBaseList; @@ -631,18 +731,23 @@ public final class AclServiceUtils { return matchInfoBaseList; } - public static MatchInfoBase getMatchInfoByType(List flows, NxMatchFieldType type) { + private List addFlowMatchForAclId(Uuid remoteAclId, List flows) { + List matchInfoBaseList; + matchInfoBaseList = buildAclIdMetadataMatch(remoteAclId); + matchInfoBaseList.addAll(flows); + return matchInfoBaseList; + } + + public static MatchInfoBase getMatchInfoByType(List flows, Class type) { for (MatchInfoBase mib : flows) { - if (mib instanceof NxMatchInfo) { - if (((NxMatchInfo)mib).getMatchField() == type) { - return mib; - } + if (type.isAssignableFrom(mib.getClass())) { + return mib; } } return null; } - public static boolean containsMatchFieldType(List flows, NxMatchFieldType type) { + public static boolean containsMatchFieldType(List flows, Class type) { return getMatchInfoByType(flows, type) != null; } @@ -654,20 +759,22 @@ public final class AclServiceUtils { return flows.contains(MatchIpProtocol.UDP); } - public static Integer allocateId(IdManagerService idManager, String poolName, String idKey) { + public static Integer allocateId(IdManagerService idManager, String poolName, String idKey, Integer defaultId) { AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build(); try { Future> result = idManager.allocateId(getIdInput); RpcResult rpcResult = result.get(); if (rpcResult.isSuccessful()) { - return rpcResult.getResult().getIdValue().intValue(); + Integer allocatedId = rpcResult.getResult().getIdValue().intValue(); + LOG.debug("Allocated ACL ID: {} with key: {} into pool: {}", allocatedId, idKey, poolName); + return allocatedId; } else { LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); } } catch (InterruptedException | ExecutionException e) { LOG.warn("Exception when getting Unique Id", e); } - return AclConstants.PROTO_MATCH_PRIORITY; + return defaultId; } public static void releaseId(IdManagerService idManager, String poolName, String idKey) { @@ -677,12 +784,66 @@ public final class AclServiceUtils { RpcResult rpcResult = result.get(); if (!rpcResult.isSuccessful()) { LOG.warn("RPC Call to release Id {} with Key {} returned with Errors {}", idKey, rpcResult.getErrors()); + } else { + LOG.debug("Released ACL ID with key: {} from pool: {}", idKey, poolName); } } catch (InterruptedException | ExecutionException e) { LOG.warn("Exception when releasing Id for key {}", idKey, e); } } + /** + * Allocate and save flow priority in cache. + * + * @param key the key + * @return the integer + */ + public Integer allocateAndSaveFlowPriorityInCache(BigInteger dpId, short tableId, String key, + PacketHandling packetHandling) { + String poolName = getAclPoolName(dpId, tableId, packetHandling); + Integer flowPriority = AclServiceUtils.allocateId(this.idManager, poolName, key, + AclConstants.PROTO_MATCH_PRIORITY); + this.aclDataUtil.addAclFlowPriority(key, flowPriority); + return flowPriority; + } + + /** + * Allocate acl id. + * + * @param key the key + */ + public Integer allocateAclId(String key) { + Integer aclId = AclServiceUtils.allocateId(this.idManager, AclConstants.ACL_ID_POOL_NAME, key, + AclConstants.INVALID_ACL_ID); + return aclId; + } + + /** + * Allocate and save flow priority in cache. + * + * @param key the key + */ + public void releaseAclId(String key) { + AclServiceUtils.releaseId(idManager, AclConstants.ACL_ID_POOL_NAME, key); + } + + /** + * Release and remove flow priority from cache. + * + * @param key the key + * @return the integer + */ + public Integer releaseAndRemoveFlowPriorityFromCache(BigInteger dpId, short tableId, String key, + PacketHandling packetHandling) { + String poolName = getAclPoolName(dpId, tableId, packetHandling); + AclServiceUtils.releaseId(this.idManager, poolName, key); + Integer flowPriority = this.aclDataUtil.removeAclFlowPriority(key); + if (flowPriority == null) { + flowPriority = AclConstants.PROTO_MATCH_PRIORITY; + } + return flowPriority; + } + /** * Indicates whether the interface has port security enabled. * @param aclInterface the interface. @@ -692,4 +853,269 @@ public final class AclServiceUtils { return aclInterface != null && aclInterface.getPortSecurityEnabled() != null && aclInterface.isPortSecurityEnabled(); } + + /** + * Creates the id pool. + * + * @param poolName the pool name + */ + public void createIdPool(String poolName, AclConstants.PacketHandlingType packetHandlingType) { + CreateIdPoolInput createPool = null; + + // If the default behavior is Deny, then ACLs with Allow packetHandling must have lower priority than + // ACLs with Deny packetHandling - otherwise the Deny ACLs are redundant, and vice versa + if ((config.getDefaultBehavior() == DEFAULT_DENY + && packetHandlingType == AclConstants.PacketHandlingType.PERMIT) + || (config.getDefaultBehavior() == DEFAULT_ALLOW + && packetHandlingType == AclConstants.PacketHandlingType.DENY)) { + createPool = new CreateIdPoolInputBuilder() + .setPoolName(poolName).setLow(AclConstants.ACL_FLOW_PRIORITY_LOW_POOL_START) + .setHigh(AclConstants.ACL_FLOW_PRIORITY_LOW_POOL_END).build(); + } else if ((config.getDefaultBehavior() == DEFAULT_DENY + && packetHandlingType == AclConstants.PacketHandlingType.DENY) + || (config.getDefaultBehavior() == DEFAULT_ALLOW + && packetHandlingType == AclConstants.PacketHandlingType.PERMIT)) { + createPool = new CreateIdPoolInputBuilder() + .setPoolName(poolName).setLow(AclConstants.ACL_FLOW_PRIORITY_HIGH_POOL_START) + .setHigh(AclConstants.ACL_FLOW_PRIORITY_HIGH_POOL_END).build(); + } else { + LOG.error("Got unexpected PacketHandling {} combined with default behavior {}, skipping creation" + + "of pool {}", packetHandlingType, config.getDefaultBehavior(), poolName); + return; + } + try { + Future> result = this.idManager.createIdPool(createPool); + if ((result != null) && (result.get().isSuccessful())) { + LOG.debug("Created IdPool for {}", poolName); + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to create ID pool [{}] for ACL flow priority", poolName, e); + throw new RuntimeException("Failed to create ID pool for ACL flow priority", e); + } + } + + /** + * Creates the id pool. + * + * @param poolName the pool name + */ + private void createIdPoolForAclId(String poolName) { + CreateIdPoolInput createPool = new CreateIdPoolInputBuilder() + .setPoolName(poolName).setLow(AclConstants.ACL_ID_METADATA_POOL_START) + .setHigh(AclConstants.ACL_ID_METADATA_POOL_END).build(); + try { + Future> result = this.idManager.createIdPool(createPool); + if ((result != null) && (result.get().isSuccessful())) { + LOG.debug("Created IdPool for {}", poolName); + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to create ID pool [{}] for remote ACL ids", poolName, e); + throw new RuntimeException("Failed to create ID pool [{}] for remote ACL ids", e); + } + } + + /** + * Delete id pool. + * + * @param poolName the pool name + */ + public void deleteIdPool(String poolName) { + DeleteIdPoolInput deletePool = new DeleteIdPoolInputBuilder().setPoolName(poolName).build(); + try { + Future> result = this.idManager.deleteIdPool(deletePool); + if ((result != null) && (result.get().isSuccessful())) { + LOG.debug("Deleted IdPool for {}", poolName); + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Failed to delete ID pool [{}]", poolName, e); + throw new RuntimeException("Failed to delete ID pool [" + poolName + "]", e); + } + } + + /** + * Gets the acl pool name. + * + * @param dpId the dp id + * @param tableId the table id + * @param packetHandlingType packet handling type + * @return the acl pool name + */ + public static String getAclPoolName(BigInteger dpId, short tableId, + AclConstants.PacketHandlingType packetHandlingType) { + return AclConstants.ACL_FLOW_PRIORITY_POOL_NAME + "." + dpId + "." + tableId + "." + packetHandlingType; + } + + /** + * Gets the acl pool name. + * + * @param dpId the dp id + * @param tableId the table id + * @param packetHandling packet handling type + * @return the acl pool name + */ + public static String getAclPoolName(BigInteger dpId, short tableId, PacketHandling packetHandling) { + return packetHandling instanceof Permit + ? getAclPoolName(dpId, tableId, AclConstants.PacketHandlingType.PERMIT) + : getAclPoolName(dpId, tableId, AclConstants.PacketHandlingType.DENY); + } + + /** + * Creates the acl id pools. + * + * @param dpId the dp id + */ + public void createAclIdPools(BigInteger dpId) { + createIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.PERMIT), AclConstants.PacketHandlingType.PERMIT); + createIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.DENY), AclConstants.PacketHandlingType.DENY); + createIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.PERMIT), AclConstants.PacketHandlingType.PERMIT); + createIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.DENY), AclConstants.PacketHandlingType.DENY); + } + + /** + * Creates remote the acl id pools. + */ + public void createRemoteAclIdPool() { + createIdPoolForAclId(AclConstants.ACL_ID_POOL_NAME); + } + + /** + * Delete remote the acl id pools. + */ + public void deleteRemoteAclIdPool() { + deleteIdPool(AclConstants.ACL_ID_POOL_NAME); + } + + /** + * Delete acl id pools. + * + * @param dpId the dp id + */ + public void deleteAclIdPools(BigInteger dpId) { + deleteIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.PERMIT)); + deleteIdPool(getAclPoolName(dpId, NwConstants.INGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.DENY)); + deleteIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.PERMIT)); + deleteIdPool(getAclPoolName(dpId, NwConstants.EGRESS_ACL_FILTER_TABLE, + AclConstants.PacketHandlingType.DENY)); + } + + public static List buildIpAndSrcServiceMatch(long elanTag, AllowedAddressPairs ip, + DataBroker dataBroker, Long vpnId) { + List flowMatches = new ArrayList<>(); + MatchMetadata metadatMatch = null; + if (vpnId == null) { + metadatMatch = + new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE); + } else { + metadatMatch = + new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID); + } + flowMatches.add(metadatMatch); + if (ip.getIpAddress().getIpAddress() != null) { + if (ip.getIpAddress().getIpAddress().getIpv4Address() != null) { + MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4); + flowMatches.add(ipv4EthMatch); + MatchIpv4Source srcMatch = new MatchIpv4Source( + new Ipv4Prefix(ip.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32")); + flowMatches.add(srcMatch); + } else if (ip.getIpAddress().getIpAddress().getIpv6Address() != null) { + MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6); + flowMatches.add(ipv6EthMatch); + MatchIpv6Source srcMatch = new MatchIpv6Source( + new Ipv6Prefix(ip.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128")); + flowMatches.add(srcMatch); + } + } else if (ip.getIpAddress().getIpPrefix() != null) { + if (ip.getIpAddress().getIpPrefix().getIpv4Prefix() != null) { + MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4); + flowMatches.add(ipv4EthMatch); + MatchIpv4Source srcMatch = new MatchIpv4Source(ip.getIpAddress().getIpPrefix().getIpv4Prefix()); + flowMatches.add(srcMatch); + } else if (ip.getIpAddress().getIpPrefix().getIpv6Prefix() != null) { + MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6); + flowMatches.add(ipv6EthMatch); + MatchIpv6Source srcMatch = new MatchIpv6Source(ip.getIpAddress().getIpPrefix().getIpv6Prefix()); + flowMatches.add(srcMatch); + } + } + return flowMatches; + } + + public static List buildIpAndDstServiceMatch(Long elanTag, AllowedAddressPairs ip, + DataBroker dataBroker, Long vpnId) { + List flowMatches = new ArrayList<>(); + MatchMetadata metadatMatch = null; + if (vpnId == null) { + metadatMatch = + new MatchMetadata(MetaDataUtil.getElanTagMetadata(elanTag), MetaDataUtil.METADATA_MASK_SERVICE); + } else { + metadatMatch = + new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID); + } + flowMatches.add(metadatMatch); + + if (ip.getIpAddress().getIpAddress() != null) { + if (ip.getIpAddress().getIpAddress().getIpv4Address() != null) { + MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4); + flowMatches.add(ipv4EthMatch); + MatchIpv4Destination dstMatch = new MatchIpv4Destination( + new Ipv4Prefix(ip.getIpAddress().getIpAddress().getIpv4Address().getValue() + "/32")); + flowMatches.add(dstMatch); + } else if (ip.getIpAddress().getIpAddress().getIpv6Address() != null) { + MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6); + flowMatches.add(ipv6EthMatch); + MatchIpv6Destination dstMatch = new MatchIpv6Destination( + new Ipv6Prefix(ip.getIpAddress().getIpAddress().getIpv6Address().getValue() + "/128")); + flowMatches.add(dstMatch); + } + } else if (ip.getIpAddress().getIpPrefix() != null) { + if (ip.getIpAddress().getIpPrefix().getIpv4Prefix() != null) { + MatchEthernetType ipv4EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV4); + flowMatches.add(ipv4EthMatch); + MatchIpv4Destination dstMatch = + new MatchIpv4Destination(ip.getIpAddress().getIpPrefix().getIpv4Prefix()); + flowMatches.add(dstMatch); + } else if (ip.getIpAddress().getIpPrefix().getIpv6Prefix() != null) { + MatchEthernetType ipv6EthMatch = new MatchEthernetType(NwConstants.ETHTYPE_IPV6); + flowMatches.add(ipv6EthMatch); + MatchIpv6Destination dstMatch = + new MatchIpv6Destination(ip.getIpAddress().getIpPrefix().getIpv6Prefix()); + flowMatches.add(dstMatch); + } + } + return flowMatches; + } + + public static boolean exactlyOneAcl(AclInterface port) { + return (port.getSecurityGroups() != null) && (port.getSecurityGroups().size() == 1); + } + + public static boolean isOfAclInterest(Acl acl) { + List aceList = acl.getAccessListEntries().getAce(); + if ((aceList != null) && !aceList.isEmpty()) { + return (aceList.get(0).getAugmentation(SecurityRuleAttr.class) != null); + } + return false; + } + + public static void addLportTagMetadataMatch(int lportTag, List flowMatches, + Class serviceMode) { + MatchInfoBase lportMatch = buildLPortTagMatch(lportTag, serviceMode); + InterfaceServiceUtil.mergeMetadataMatchsOrAdd(flowMatches, lportMatch); + } + + static AclInterface buildAclInterfaceState(String interfaceId, InterfaceAcl aclInPort) { + AclInterface aclInterface = new AclInterface(); + aclInterface.setInterfaceId(interfaceId); + aclInterface.setPortSecurityEnabled(aclInPort.isPortSecurityEnabled()); + aclInterface.setSecurityGroups(aclInPort.getSecurityGroups()); + aclInterface.setAllowedAddressPairs(aclInPort.getAllowedAddressPairs()); + return aclInterface; + } }