Upgrading ACL implementation
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / policy / acl / AccessListUtil.java
index 9f7715da15063c6c112d20a0cae24987bf8c0795..2d927d9601a83e2f1032cdd207501defa121f8c3 100644 (file)
@@ -25,16 +25,15 @@ import org.opendaylight.groupbasedpolicy.renderer.util.AddressEndpointUtils;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.RendererResolvedPolicy;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.SubjectFeatures;
-import org.opendaylight.groupbasedpolicy.util.EndpointUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.Actions;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.ActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
 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.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.SubnetAugmentRenderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.has.subnet.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
@@ -50,15 +49,15 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
- /*
 * Transforms Renderer policy into access-list configuration for Honeycomb.
 *
 * */
+/*
+ * Transforms Renderer policy into access-list configuration for Honeycomb.
+ *
+ */
 
 public class AccessListUtil {
 
     private static final Logger LOG = LoggerFactory.getLogger(AccessListUtil.class);
-    private static final String UNDERSCORE = "_";
+    static final String UNDERSCORE = "_";
     private static final String PERMIT_EXTERNAL_INGRESS = "permit_external_ingress";
     private static final String PERMIT_EXTERNAL_EGRESS = "permit_external_egress";
     private static final String DENY_INGRESS_IPV4 = "deny_ingress_ipv4";
@@ -81,26 +80,27 @@ public class AccessListUtil {
             .stream()
             .filter(peerEpKey -> peerHasLocation(ctx, peerEpKey))
             .forEach(peerEpKey -> {
+                List<GbpAceBuilder> rules = new ArrayList<>();
                 ctx.getPolicyTable().get(rEpKey, peerEpKey).forEach(resolvedRules -> {
-                    List<GbpAceBuilder> rules = new ArrayList<>();
-                    LOG.debug("Resolving policy for {} and peer endpoint {}", rEpKey, peerEpKey);
                     Direction classifDir = calculateClassifDirection(resolvedRules.getRendererEndpointParticipation(),
                             policyDirection);
-                    rules.addAll(resolveAclRulesFromPolicy(resolvedRules, classifDir,
-                            rEpKey.getAddress() + UNDERSCORE + peerEpKey.getAddress()));
-                    updateAddressesInRules(rules, rEpKey, peerEpKey, ctx, policyDirection, true);
-                    aclWrapper.writeRules(rules);
+                    rules.addAll(resolveAclRulesFromPolicy(resolvedRules, classifDir, rEpKey, peerEpKey));
 
                 });
+                if (validateAndUpdateAddressesInRules(rules, rEpKey, peerEpKey, ctx, policyDirection, true)) {
+                    aclWrapper.writeRules(rules);
+                }
             });
     }
 
     /**
      * Resolves direction for classifiers that will be applied to INBOUND or OUTBOUND direction.
      * </p>
-     * Rule is applied in INGRESS direction when participation is PROVIDER and classifier direction is OUT
+     * Rule is applied in INGRESS direction when participation is PROVIDER and classifier direction
+     * is OUT
      * </p>
-     * Rule is applied in INGRESS direction when participation is CONSUMER and classifier direction is IN
+     * Rule is applied in INGRESS direction when participation is CONSUMER and classifier direction
+     * is IN
      * </p>
      * INBOUND direction is applied otherwise.
      * </p>
@@ -112,11 +112,12 @@ public class AccessListUtil {
      * </p>
      * IN is resolved otherwise.
      * </p>
+     * 
      * @param participation provider or consumer
      * @param direction EGRESS or INGRESS
      * @return Direction that classifiers should match for given policy direction.
      */
-    private static Direction calculateClassifDirection(EndpointPolicyParticipation participation, ACE_DIRECTION direction) {
+    static Direction calculateClassifDirection(EndpointPolicyParticipation participation, ACE_DIRECTION direction) {
         if (EndpointPolicyParticipation.PROVIDER.equals(participation) && ACE_DIRECTION.INGRESS.equals(direction)) {
             return Direction.Out;
         }
@@ -126,67 +127,81 @@ public class AccessListUtil {
         return Direction.In;
     }
 
-    private static void updateAddressesInRules(List<GbpAceBuilder> rules, RendererEndpointKey rEpKey,
+    static boolean validateAndUpdateAddressesInRules(List<GbpAceBuilder> rules, RendererEndpointKey rEpKey,
             PeerEndpointKey peerEpKey, PolicyContext ctx, ACE_DIRECTION policyDirection,
             boolean resolveForLocationPeers) {
         for (AddressMapper addrMapper : Arrays.asList(new SourceMapper(policyDirection),
                 new DestinationMapper(policyDirection))) {
             if (peerHasLocation(ctx, peerEpKey) && resolveForLocationPeers) {
-                addrMapper.updateRules(rules, findAddrEp(ctx, rEpKey), findAddrEp(ctx, peerEpKey));
+                if (!addrMapper.updateRules(rules, findAddrEp(ctx, rEpKey), findAddrEp(ctx, peerEpKey))) {
+                    return false;
+                }
             } else if (!peerHasLocation(ctx, peerEpKey) && !resolveForLocationPeers) {
                 addrMapper.updateExtRules(rules, findAddrEp(ctx, rEpKey), null);
             }
         }
+        return true;
     }
 
     private static boolean peerHasLocation(PolicyContext ctx, PeerEndpointKey peerEpKey) {
-        return ctx.getAddrEpByKey().get(
-                AddressEndpointUtils.fromPeerEpKey(peerEpKey)) != null;
+        return ctx.getAddrEpByKey().get(AddressEndpointUtils.fromPeerEpKey(peerEpKey)) != null;
     }
 
     static AddressEndpointWithLocation findAddrEp(PolicyContext ctx, RendererEndpointKey rEpKey) {
-        return ctx.getAddrEpByKey().get(
-                AddressEndpointUtils.fromRendererEpKey(rEpKey));
+        return ctx.getAddrEpByKey().get(AddressEndpointUtils.fromRendererEpKey(rEpKey));
     }
 
     private static AddressEndpointWithLocation findAddrEp(PolicyContext ctx, PeerEndpointKey rEpKey) {
-        return ctx.getAddrEpByKey().get(
-                AddressEndpointUtils.fromPeerEpKey(rEpKey));
+        return ctx.getAddrEpByKey().get(AddressEndpointUtils.fromPeerEpKey(rEpKey));
     }
 
-    /** Transform a resolved rule to ACE with corresponding classification and action fields
+    /**
+     * Transform a resolved rule to ACE with corresponding classification and action fields
      *
      * @param resolvedPolicy resolved rules, with the same participation - provider or consumer
      * @param direction rules matching corresponding direction will be collected
      * @return resolved ACE entries
      */
+
+    static @Nonnull String resolveAceName(@Nonnull RuleName ruleName, @Nonnull RendererEndpointKey key,
+            @Nonnull PeerEndpointKey peer) {
+        return ruleName.getValue() + "_" + key.getAddress() + "_" + peer.getAddress();
+    }
+
     private static List<GbpAceBuilder> resolveAclRulesFromPolicy(RendererResolvedPolicy resolvedPolicy,
-            Direction direction, String namePasphrase) {
+            Direction direction, RendererEndpointKey r, PeerEndpointKey p) {
         List<GbpAceBuilder> aclRules = new ArrayList<>();
         for (ResolvedRule resolvedRule : resolvedPolicy.getRuleGroup().getRules()) {
-            Map<String, ParameterValue> params = resolveClassifParamsForDir(direction, resolvedRule.getClassifier());
-            if (params.isEmpty()) {
-                continue;
-            }
-            LOG.debug("Processing classifification params {} in resolved rule {}.", params,
-                    resolvedRule.getName() + UNDERSCORE + namePasphrase);
-            org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier classif =
-                    resolveImplementedClassifForDir(direction, resolvedRule.getClassifier());
-            GbpAceBuilder aclRuleBuilder =
-                    new GbpAceBuilder(resolvedRule.getName().getValue() + UNDERSCORE + namePasphrase);
-            boolean updated = classif != null && classif.updateMatch(aclRuleBuilder, params);
-            Optional<Actions> optAction = resolveActions(resolvedRule.getAction());
-            if (!optAction.isPresent() || !updated) {
-                LOG.error("Failed to process rule {}. Resolved parameters {}, resolved classifier. Actions resolved: {}"
-                        + "{}.", resolvedRule.getName().getValue(), params, classif, optAction.isPresent());
-                continue;
+            Optional<GbpAceBuilder> resolveAce = resolveAceClassifersAndAction(resolvedRule, direction,
+                    resolveAceName(resolvedRule.getName(), r, p));
+            if (resolveAce.isPresent()) {
+                aclRules.add(resolveAce.get());
             }
-            aclRuleBuilder.setAction(optAction.get());
-            aclRules.add(aclRuleBuilder);
         }
         return aclRules;
     }
 
+    public static Optional<GbpAceBuilder> resolveAceClassifersAndAction(ResolvedRule resolvedRule, Direction direction,
+            String ruleName) {
+        Map<String, ParameterValue> params = resolveClassifParamsForDir(direction, resolvedRule.getClassifier());
+        if (params.isEmpty()) {
+            return Optional.absent();
+        }
+        org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier classif =
+                resolveImplementedClassifForDir(direction, resolvedRule.getClassifier());
+        GbpAceBuilder aclRuleBuilder = new GbpAceBuilder(ruleName);
+        // new GbpAceBuilder(resolvedRule.getName().getValue() + UNDERSCORE + namePasphrase);
+        boolean updated = classif != null && classif.updateMatch(aclRuleBuilder, params);
+        Optional<Actions> optAction = resolveActions(resolvedRule.getAction());
+        if (!optAction.isPresent() || !updated) {
+            LOG.error("Failed to process rule {}. Resolved parameters {}, resolved classifier. Actions resolved: {}"
+                    + "{}.", resolvedRule.getName().getValue(), params, classif, optAction.isPresent());
+            return Optional.absent();
+        }
+        aclRuleBuilder.setAction(optAction.get());
+        return Optional.of(aclRuleBuilder);
+    }
+
     private static org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier resolveImplementedClassifForDir(
             @Nonnull Direction direction, @Nonnull List<Classifier> classifiers) {
         org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier feasibleClassifier = null;
@@ -211,27 +226,22 @@ public class AccessListUtil {
         classifier.stream()
             .filter(classif -> direction.equals(classif.getDirection()) || direction.equals(Direction.Bidirectional))
             .forEach(classif -> {
-                LOG.trace("Resolving parameters for classiifier: {} with direction", classif, direction);
                 classif.getParameterValue()
                     .stream()
                     .filter(v -> params.get(v.getName().getValue()) == null) // not unique
                     .filter(v -> v.getIntValue() != null || v.getStringValue() != null || v.getRangeValue() != null)
                     .forEach(v -> params.put(v.getName().getValue(), v));
-                LOG.trace("Resolved parameters {} for classiifier: {} with direction {}", params, classif, direction);
             });
         return params;
     }
 
     private static Optional<Actions> resolveActions(List<Action> actions) {
         for (Action action : actions) {
-            if (AllowActionDefinition.ID
-                .equals(action.getActionDefinitionId())) {
-                LOG.trace("Applying supported action: {}", action);
+            if (AllowActionDefinition.ID.equals(action.getActionDefinitionId())) {
                 return Optional
                     .of(new ActionsBuilder().setPacketHandling(new PermitBuilder().setPermit(true).build()).build());
             }
         }
-        LOG.warn("No supported action found among actions: {}", actions);
         return Optional.absent();
     }
 
@@ -240,39 +250,33 @@ public class AccessListUtil {
      * purposes
      * TODO initial workaround for external networking
      */
-   static Optional<GbpAceBuilder> allowExternalNetworksForEp(@Nonnull AddressEndpointWithLocation addrEp,
+    static GbpAceBuilder allowExternalNetworksForEp(@Nonnull RendererEndpointKey rendEp,
             AccessListUtil.ACE_DIRECTION dir) {
-        List<ParentEndpoint> parentEndpoints = EndpointUtils.getParentEndpoints(addrEp.getParentEndpointChoice());
-        if (parentEndpoints.isEmpty()) {
-            return Optional.absent();
+        InetAddress byName;
+        try {
+            byName = InetAddress.getByName(substringBeforeSlash(rendEp.getAddress()));
+        } catch (UnknownHostException e) {
+            LOG.error("Failed to parse IP address {}", e);
+            return null;
         }
-        for (ParentEndpoint parentEp : parentEndpoints) {
-            InetAddress byName;
-            try {
-                byName = InetAddress.getByName(substringBeforeSlash(parentEp.getAddress()));
-            } catch (UnknownHostException e) {
-                LOG.error("Failed to parse IP address {}", e);
-                return Optional.absent();
+        if (byName instanceof Inet4Address) {
+            if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
+                return new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS)
+                    .setIpAddresses(new Ipv4Prefix(rendEp.getAddress()), null).setPermit();
+            } else {
+                return new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS)
+                    .setIpAddresses(null, new Ipv4Prefix(rendEp.getAddress())).setPermit();
             }
-            if (byName instanceof Inet4Address) {
-                if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
-                    return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS).setIpAddresses(
-                            new Ipv4Prefix(parentEp.getAddress()), null).setPermit());
-                } else {
-                    return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS).setIpAddresses(null,
-                            new Ipv4Prefix(parentEp.getAddress())).setPermit());
-                }
-            } else if (byName instanceof Inet6Address) {
-                if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
-                    return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS).setIpAddresses(
-                            new Ipv6Prefix(parentEp.getAddress()), null).setPermit());
-                } else {
-                    return Optional.of(new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS).setIpAddresses(null,
-                            new Ipv6Prefix(parentEp.getAddress())).setPermit());
-                }
+        } else if (byName instanceof Inet6Address) {
+            if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(dir)) {
+                new GbpAceBuilder(PERMIT_EXTERNAL_INGRESS).setIpAddresses(new Ipv6Prefix(rendEp.getAddress()), null)
+                    .setPermit();
+            } else {
+                new GbpAceBuilder(PERMIT_EXTERNAL_EGRESS).setIpAddresses(null, new Ipv6Prefix(rendEp.getAddress()))
+                    .setPermit();
             }
         }
-        return Optional.absent();
+        return null;
     }
 
     /**
@@ -290,7 +294,7 @@ public class AccessListUtil {
             .getRendererForwardingByTenant()) {
             rf.getRendererNetworkDomain()
                 .stream()
-                .filter(rnd -> org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.Subnet.class
+                .filter(rnd -> org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.Subnet.class
                     .equals(rnd.getNetworkDomainType()))
                 .forEach(rnd -> {
                     SubnetAugmentRenderer subnetAug = rnd.getAugmentation(SubnetAugmentRenderer.class);
@@ -298,8 +302,7 @@ public class AccessListUtil {
                     subnetAug.getSubnet();
                     if (policyDirection.equals(ACE_DIRECTION.INGRESS) && subnetAug.getSubnet().isIsTenant()) {
                         aclRuleBuilders.add(denyIngressTrafficForPrefix(subnetAug.getSubnet()));
-                    }
-                    else if (subnetAug.getSubnet().isIsTenant()) {
+                    } else if (subnetAug.getSubnet().isIsTenant()) {
                         aclRuleBuilders.add(denyEgressTrafficForPrefix(subnetAug.getSubnet()));
                     }
                 });
@@ -320,8 +323,7 @@ public class AccessListUtil {
     }
 
     static void setSourceL3Address(GbpAceBuilder rule, String address) throws UnknownHostException {
-        InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
-        if (addr instanceof Inet6Address) {
+        if (isIpv6Address(address)) {
             rule.setIpAddresses(new Ipv6Prefix(address), null);
         } else {
             rule.setIpAddresses(new Ipv4Prefix(address), null);
@@ -329,14 +331,23 @@ public class AccessListUtil {
     }
 
     static void setDestinationL3Address(GbpAceBuilder rule, String address) throws UnknownHostException {
-        InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
-        if (addr instanceof Inet6Address) {
+        if (isIpv6Address(address)) {
             rule.setIpAddresses(null, new Ipv6Prefix(address));
         } else {
             rule.setIpAddresses(null, new Ipv4Prefix(address));
         }
     }
 
+    public static boolean isIpv4Address(String address) throws UnknownHostException {
+        InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
+        return addr instanceof Inet4Address;
+    }
+
+    public static boolean isIpv6Address(String address) throws UnknownHostException {
+        InetAddress addr = InetAddress.getByName(substringBeforeSlash(address));
+        return addr instanceof Inet6Address;
+    }
+
     static GbpAceBuilder denyIngressTrafficForPrefix(Subnet subnet) {
         IpPrefix ipPrefix = subnet.getIpPrefix();
         if (ipPrefix.getIpv4Prefix() != null) {