+ /**
+ * 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.
+ * @return true if port is security enabled.
+ */
+ public static boolean isOfInterest(AclInterface aclInterface) {
+ 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<RpcResult<Void>> 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<RpcResult<Void>> 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<RpcResult<Void>> 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<? extends MatchInfoBase> buildIpAndSrcServiceMatch(long elanTag, AllowedAddressPairs ip,
+ DataBroker dataBroker, Long vpnId) {
+ List<MatchInfoBase> 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<? extends MatchInfoBase> buildIpAndDstServiceMatch(Long elanTag, AllowedAddressPairs ip,
+ DataBroker dataBroker, Long vpnId) {
+ List<MatchInfoBase> 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<Ace> aceList = acl.getAccessListEntries().getAce();
+ if ((aceList != null) && !aceList.isEmpty()) {
+ return (aceList.get(0).getAugmentation(SecurityRuleAttr.class) != null);