Bug 3240 3613: Asymetric policy in neutron
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / rule / SecRuleEntityDecoder.java
diff --git a/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/SecRuleEntityDecoder.java b/neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/SecRuleEntityDecoder.java
new file mode 100644 (file)
index 0000000..440c640
--- /dev/null
@@ -0,0 +1,254 @@
+package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule;\r
+\r
+import static com.google.common.base.Preconditions.checkNotNull;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.annotation.Nullable;\r
+\r
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;\r
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.EtherTypeClassifier;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.IpProtoClassifier;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;\r
+import org.opendaylight.neutron.spi.NeutronSecurityRule;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef.ConnectionTracking;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.EndpointIdentificationConstraints;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.EndpointIdentificationConstraintsBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.L3EndpointIdentificationConstraintsBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraint;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraintBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValueBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchers;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstanceBuilder;\r
+\r
+import com.google.common.base.Strings;\r
+import com.google.common.collect.ImmutableList;\r
+\r
+public class SecRuleEntityDecoder {\r
+\r
+    private SecRuleEntityDecoder() {\r
+        throw new UnsupportedOperationException("Cannot create an instace.");\r
+    }\r
+\r
+    public static TenantId getTenantId(NeutronSecurityRule secRule) {\r
+        return new TenantId(Utils.normalizeUuid(secRule.getSecurityRuleTenantID()));\r
+    }\r
+\r
+    public static EndpointGroupId getProviderEpgId(NeutronSecurityRule secRule) {\r
+        return new EndpointGroupId(Utils.normalizeUuid(secRule.getSecurityRuleGroupID()));\r
+    }\r
+\r
+    /**\r
+     * @return {@code null} if {@link NeutronSecurityRule#getSecurityRemoteGroupID()} is null\r
+     */\r
+    public static @Nullable EndpointGroupId getConsumerEpgId(NeutronSecurityRule secRule) {\r
+        if (Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {\r
+            return null;\r
+        }\r
+        return new EndpointGroupId(Utils.normalizeUuid(secRule.getSecurityRemoteGroupID()));\r
+    }\r
+\r
+    public static ContractId getContractId(NeutronSecurityRule secRule) {\r
+        return new ContractId(Utils.normalizeUuid(secRule.getSecurityRuleUUID()));\r
+    }\r
+\r
+    public static ClassifierInstance getClassifierInstance(NeutronSecurityRule secRule) {\r
+        ClassifierInstanceBuilder classifierBuilder = new ClassifierInstanceBuilder();\r
+        List<ParameterValue> params = new ArrayList<>();\r
+        Integer portMin = secRule.getSecurityRulePortMin();\r
+        Integer portMax = secRule.getSecurityRulePortMax();\r
+        if (portMin != null && portMax != null) {\r
+            classifierBuilder.setClassifierDefinitionId(L4Classifier.DEFINITION.getId());\r
+            if (portMin.equals(portMax)) {\r
+                params.add(new ParameterValueBuilder().setName(new ParameterName(L4Classifier.DST_PORT_PARAM))\r
+                    .setIntValue(portMin.longValue())\r
+                    .build());\r
+            } else {\r
+                params.add(new ParameterValueBuilder().setName(new ParameterName(L4Classifier.DST_PORT_RANGE_PARAM))\r
+                    .setRangeValue(\r
+                            new RangeValueBuilder().setMin(portMin.longValue()).setMax(portMax.longValue()).build())\r
+                    .build());\r
+            }\r
+        }\r
+        Long protocol = getProtocol(secRule);\r
+        if (protocol != null) {\r
+            if (classifierBuilder.getClassifierDefinitionId() == null) {\r
+                classifierBuilder.setClassifierDefinitionId(IpProtoClassifier.DEFINITION.getId());\r
+            }\r
+            params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifier.PROTO_PARAM))\r
+                .setIntValue(protocol)\r
+                .build());\r
+        }\r
+        Long ethertype = getEtherType(secRule);\r
+        if (ethertype != null) {\r
+            if (classifierBuilder.getClassifierDefinitionId() == null) {\r
+                classifierBuilder.setClassifierDefinitionId(EtherTypeClassifier.DEFINITION.getId());\r
+            }\r
+            params.add(new ParameterValueBuilder().setName(new ParameterName(EtherTypeClassifier.ETHERTYPE_PARAM))\r
+                .setIntValue(ethertype)\r
+                .build());\r
+        }\r
+        ClassifierName classifierName = SecRuleNameDecoder.getClassifierInstanceName(secRule);\r
+        return classifierBuilder.setParameterValue(params).setName(new ClassifierName(classifierName)).build();\r
+    }\r
+\r
+    public static ClassifierRef getClassifierRef(NeutronSecurityRule secRule) {\r
+        checkNotNull(secRule);\r
+        ClassifierName classifierInstanceName = SecRuleNameDecoder.getClassifierInstanceName(secRule);\r
+        ClassifierRefBuilder classifierRefBuilder = new ClassifierRefBuilder()\r
+            .setConnectionTracking(ConnectionTracking.Reflexive).setInstanceName(classifierInstanceName);\r
+        Direction direction = getDirection(secRule);\r
+        classifierRefBuilder.setDirection(direction);\r
+        ClassifierName classifierRefName = SecRuleNameDecoder.getClassifierRefName(secRule);\r
+        return classifierRefBuilder.setName(classifierRefName).build();\r
+    }\r
+\r
+    /**\r
+     * @param secRule\r
+     * @return direction resolved from {@link NeutronSecurityRule#getSecurityRuleDirection()}\r
+     * @throws IllegalArgumentException if return value of\r
+     *         {@link NeutronSecurityRule#getSecurityRuleDirection()} is other than "ingress" or\r
+     *         "egress"\r
+     */\r
+    public static Direction getDirection(NeutronSecurityRule secRule) {\r
+        String direction = secRule.getSecurityRuleDirection();\r
+        if (NeutronUtils.INGRESS.equals(direction)) {\r
+            return Direction.In;\r
+        }\r
+        if (NeutronUtils.EGRESS.equals(direction)) {\r
+            return Direction.Out;\r
+        }\r
+        throw new IllegalArgumentException("Direction " + direction + " from security group rule "\r
+                + secRule.getSecurityRuleUUID() + " is not supported. Direction can be only 'ingress' or 'egress'.");\r
+    }\r
+\r
+    /**\r
+     * @param secRule {@link NeutronSecurityRule#getSecurityRuleRemoteIpPrefix()} is used for EIC\r
+     *        and subject selection\r
+     * @return clause with the subject and with a consumer matcher containing EIC\r
+     */\r
+    public static Clause getClause(NeutronSecurityRule secRule) {\r
+        checkNotNull(secRule);\r
+        SubjectName subjectName = SecRuleNameDecoder.getSubjectName(secRule);\r
+        ClauseBuilder clauseBuilder =\r
+                new ClauseBuilder().setSubjectRefs(ImmutableList.of(subjectName)).setName(SecRuleNameDecoder.getClauseName(secRule));\r
+        String remoteIpPrefix = secRule.getSecurityRuleRemoteIpPrefix();\r
+        if (!Strings.isNullOrEmpty(remoteIpPrefix)) {\r
+            clauseBuilder.setConsumerMatchers(createConsumerMatchersWithEic(remoteIpPrefix));\r
+        }\r
+        return clauseBuilder.build();\r
+    }\r
+\r
+    private static ConsumerMatchers createConsumerMatchersWithEic(String remoteIpPrefix) {\r
+        IpPrefix ipPrefix = Utils.createIpPrefix(remoteIpPrefix);\r
+        PrefixConstraint consumerPrefixConstraint = new PrefixConstraintBuilder().setIpPrefix(ipPrefix).build();\r
+        EndpointIdentificationConstraints eic =\r
+                new EndpointIdentificationConstraintsBuilder()\r
+                    .setL3EndpointIdentificationConstraints(new L3EndpointIdentificationConstraintsBuilder()\r
+                        .setPrefixConstraint(ImmutableList.<PrefixConstraint>of(consumerPrefixConstraint)).build())\r
+                    .build();\r
+        return new ConsumerMatchersBuilder().setEndpointIdentificationConstraints(eic).build();\r
+    }\r
+\r
+    public static boolean isEtherTypeOfOneWithinTwo(NeutronSecurityRule one, NeutronSecurityRule two) {\r
+        Long oneEtherType = getEtherType(one);\r
+        Long twoEtherType = getEtherType(two);\r
+        return twoIsNullOrEqualsOne(oneEtherType, twoEtherType);\r
+    }\r
+\r
+    public static boolean isProtocolOfOneWithinTwo(NeutronSecurityRule one, NeutronSecurityRule two) {\r
+        Long oneProtocol = getProtocol(one);\r
+        Long twoProtocol = getProtocol(two);\r
+        return twoIsNullOrEqualsOne(oneProtocol, twoProtocol);\r
+    }\r
+\r
+    private static <T> boolean twoIsNullOrEqualsOne(T one, T two) {\r
+        if (two == null)\r
+            return true;\r
+        if (two.equals(one))\r
+            return true;\r
+        return false;\r
+    }\r
+\r
+    public static boolean isPortsOfOneWithinTwo(NeutronSecurityRule one, NeutronSecurityRule two) {\r
+        Integer onePortMin = one.getSecurityRulePortMin();\r
+        Integer onePortMax = one.getSecurityRulePortMax();\r
+        Integer twoPortMin = two.getSecurityRulePortMin();\r
+        Integer twoPortMax = two.getSecurityRulePortMax();\r
+        if (twoPortMin == null && twoPortMax == null) {\r
+            return true;\r
+        }\r
+        if ((onePortMin != null && twoPortMin != null && onePortMin >= twoPortMin)\r
+                && (onePortMax != null && twoPortMax != null && onePortMax <= twoPortMax)) {\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * @param secRule\r
+     * @return {@code null} if {@link NeutronSecurityRule#getSecurityRuleEthertype()} is null or\r
+     *         empty; value of {@link EtherTypeClassifier#IPv4_VALUE} or\r
+     *         {@link EtherTypeClassifier#IPv6_VALUE}\r
+     * @throws IllegalArgumentException if return value of\r
+     *         {@link NeutronSecurityRule#getSecurityRuleEthertype()} is not empty/null and is other\r
+     *         than "IPv4" or "IPv6"\r
+     */\r
+    public static Long getEtherType(NeutronSecurityRule secRule) {\r
+        String ethertype = secRule.getSecurityRuleEthertype();\r
+        if (Strings.isNullOrEmpty(ethertype)) {\r
+            return null;\r
+        }\r
+        if (NeutronUtils.IPv4.equals(ethertype)) {\r
+            return EtherTypeClassifier.IPv4_VALUE;\r
+        }\r
+        if (NeutronUtils.IPv6.equals(ethertype)) {\r
+            return EtherTypeClassifier.IPv6_VALUE;\r
+        }\r
+        throw new IllegalArgumentException("Ethertype " + ethertype + " is not supported.");\r
+    }\r
+\r
+    /**\r
+     * @param secRule\r
+     * @return {@code null} if {@link NeutronSecurityRule#getSecurityRuleProtocol()} is null or\r
+     *         empty; Otherwise protocol number\r
+     * @throws IllegalArgumentException if return value of\r
+     *         {@link NeutronSecurityRule#getSecurityRuleProtocol()} is not empty/null and is other\r
+     *         than "tcp", "udp", "icmp"\r
+     */\r
+    public static Long getProtocol(NeutronSecurityRule secRule) {\r
+        String protocol = secRule.getSecurityRuleProtocol();\r
+        if (Strings.isNullOrEmpty(protocol)) {\r
+            return null;\r
+        }\r
+        if (NeutronUtils.TCP.equals(protocol)) {\r
+            return IpProtoClassifier.TCP_VALUE;\r
+        }\r
+        if (NeutronUtils.UDP.equals(protocol)) {\r
+            return IpProtoClassifier.UDP_VALUE;\r
+        }\r
+        if (NeutronUtils.ICMP.equals(protocol)) {\r
+            return IpProtoClassifier.ICMP_VALUE;\r
+        }\r
+        throw new IllegalArgumentException("Protocol " + protocol + " is not supported.");\r
+    }\r
+\r
+}\r