Registration point for renderer capabilities 42/29642/14
authorMartin Sunal <msunal@cisco.com>
Fri, 13 Nov 2015 11:49:49 +0000 (12:49 +0100)
committerKonstantin Blagov <kblagov@cisco.com>
Wed, 25 Nov 2015 16:29:02 +0000 (17:29 +0100)
Change-Id: Ifa5db51b89c499926c088deafec454e81e7b3fbc
Signed-off-by: Martin Sunal <msunal@cisco.com>
Signed-off-by: Konstantin Blagov <kblagov@cisco.com>
25 files changed:
groupbasedpolicy/pom.xml
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/ClassifierInstanceValidator.java [new file with mode: 0755]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/SubjectFeatureDefinitionProvider.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/SupportedClassifierDefinitionListener.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/actions/AllowActionDefinition.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/actions/ChainActionDefinition.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/classifiers/EtherTypeClassifierDefinition.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/classifiers/IpProtoClassifierDefinition.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/classifiers/L4ClassifierDefinition.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java
groupbasedpolicy/src/main/yang/model/common.yang [changed mode: 0644->0755]
groupbasedpolicy/src/main/yang/model/policy.yang
groupbasedpolicy/src/main/yang/model/renderer.yang [new file with mode: 0755]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/sf/SupportedClassifierDefinitionListenerTest.java [new file with mode: 0755]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/test/CustomDataBrokerTest.java [new file with mode: 0644]
groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/test/GbpDataBrokerTest.java [new file with mode: 0644]
renderers/ofoverlay/pom.xml [changed mode: 0644->0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/Classifier.java [changed mode: 0644->0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/EtherTypeClassifier.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/IpProtoClassifier.java [changed mode: 0644->0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/L4Classifier.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatureDefinitionsListener.java [new file with mode: 0755]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatures.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatureDefinitionsListenerTest.java [new file with mode: 0755]

index a9dfe57a9749d5d2d2076bc42069b805c1d07ac6..03e91496d75ae0d9ee5cd3f910b2a3854de22545 100755 (executable)
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 <!-- project build -->
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/ClassifierInstanceValidator.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/ClassifierInstanceValidator.java
new file mode 100755 (executable)
index 0000000..47c2d78
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.sf;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.parameters.type.ParameterType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.parameters.type.parameter.type.Int;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.parameters.type.parameter.type.Range;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.parameters.type.parameter.type.String;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueInRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported.range.value.fields.SupportedRangeValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported.string.value.fields.SupportedStringValueBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class ClassifierInstanceValidator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ClassifierInstanceValidator.class);
+    private final Map<ParameterName, Optional<ParameterType>> parameterByName = new HashMap<>();
+
+    public ClassifierInstanceValidator(SupportedClassifierDefinition constraint) {
+        for (SupportedParameterValues supportedParams : constraint.getSupportedParameterValues()) {
+            ParameterName parameterName = checkNotNull(supportedParams.getParameterName());
+            ParameterType parameterType = supportedParams.getParameterType();
+            parameterByName.put(parameterName, Optional.fromNullable(parameterType));
+        }
+    }
+
+    public boolean validate(ClassifierInstance ci) {
+        List<ParameterValue> params = ci.getParameterValue();
+        for (ParameterValue param : params) {
+            ParameterName paramName = param.getName();
+            Optional<ParameterType> potentialParamConstraint = parameterByName.get(paramName);
+            if (potentialParamConstraint == null) {
+                LOG.info("Parameter {} with value {} is not supported.", paramName, param);
+                return false;
+            }
+            if (!potentialParamConstraint.isPresent()) {
+                LOG.info("There is no constraint for parameter {}. \nTherefore the parameter is considered as valid.",
+                        param);
+                continue;
+            }
+            ParameterType paramConstraint = potentialParamConstraint.get();
+            if (paramConstraint instanceof Int) {
+                boolean paramValid = isParamValid(param, (Int) paramConstraint);
+                if (!paramValid) {
+                    LOG.info("Parameter {} with value {} is not valid.", paramName, param);
+                    return false;
+                }
+            } else if (paramConstraint instanceof Range) {
+                boolean paramValid = isParamValid(param, (Range) paramConstraint);
+                if (!paramValid) {
+                    LOG.info("Parameter {} with value {} is not valid.", paramName, param);
+                    return false;
+                }
+            } else if (paramConstraint instanceof String) {
+                boolean paramValid = isParamValid(param, (String) paramConstraint);
+                if (!paramValid) {
+                    LOG.info("Parameter {} with value {} is not valid.", paramName, param);
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean isParamValid(ParameterValue param, Int constraint) {
+        Long value = param.getIntValue();
+        if (value == null) {
+            return false;
+        }
+        if (constraint.getSupportedIntValue() != null
+                && constraint.getSupportedIntValue().contains(new SupportedIntValueBuilder().setValue(value).build())) {
+            return true;
+        }
+        List<SupportedIntValueInRange> intRangeValues = constraint.getSupportedIntValueInRange();
+        if (intRangeValues != null) {
+            for (SupportedIntValueInRange supportedValue : intRangeValues) {
+                if (supportedValue.getMin() <= value && supportedValue.getMax() >= value) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean isParamValid(ParameterValue param, Range constraint) {
+        RangeValue value = param.getRangeValue();
+        if (value == null) {
+            return false;
+        }
+        List<SupportedRangeValue> intRangeValues = constraint.getSupportedRangeValue();
+        if (intRangeValues != null) {
+            for (SupportedRangeValue supportedValue : intRangeValues) {
+                if (supportedValue.getMin() <= value.getMin() && supportedValue.getMax() >= value.getMax()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean isParamValid(ParameterValue param, String constraint) {
+        java.lang.String value = param.getStringValue();
+        if (value == null) {
+            return false;
+        }
+        if (constraint.getSupportedStringValue() != null && constraint.getSupportedStringValue()
+            .contains(new SupportedStringValueBuilder().setValue(value).build())) {
+            return true;
+        }
+        return false;
+    }
+
+    public Set<ParameterName> getSupportedParameters() {
+        return parameterByName.keySet();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((parameterByName == null) ? 0 : parameterByName.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ClassifierInstanceValidator other = (ClassifierInstanceValidator) obj;
+        if (parameterByName == null) {
+            if (other.parameterByName != null)
+                return false;
+        } else if (!parameterByName.equals(other.parameterByName))
+            return false;
+        return true;
+    }
+
+    @Override
+    public java.lang.String toString() {
+        return "ClassifierInstanceValidator [parameterByName=" + parameterByName + "]";
+    }
+
+}
index dd2b53021680594d3476bf7a7fb66dd2b62b1ab5..d18c6e92a25afcede02c2958bdb9022151e1850f 100755 (executable)
@@ -17,15 +17,11 @@ import org.opendaylight.groupbasedpolicy.sf.actions.ChainActionDefinition;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.EtherTypeClassifierDefinition;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.IpProtoClassifierDefinition;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.L4ClassifierDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
- * On creation, puts known Subject Feature Definitions to operational datastore; deletes them on #close()
+ * On creation, puts known Subject Feature Definitions to config datastore; deletes them on #close()
  */
 public class SubjectFeatureDefinitionProvider implements AutoCloseable {
-    private static final Logger LOG =
-            LoggerFactory.getLogger(SubjectFeatureDefinitionProvider.class);
 
     private final DataBroker dataProvider;
 
@@ -38,7 +34,6 @@ public class SubjectFeatureDefinitionProvider implements AutoCloseable {
     public SubjectFeatureDefinitionProvider(DataBroker dataProvider)
             throws TransactionCommitFailedException {
         this.dataProvider = dataProvider;
-
         putSubjectFeatureDefinitions();
     }
 
@@ -50,16 +45,16 @@ public class SubjectFeatureDefinitionProvider implements AutoCloseable {
     private void putSubjectFeatureDefinitions() throws TransactionCommitFailedException {
         WriteTransaction wt = this.dataProvider.newWriteOnlyTransaction();
 
-        wt.put(LogicalDatastoreType.OPERATIONAL, EtherTypeClassifierDefinition.IID,
+        wt.put(LogicalDatastoreType.CONFIGURATION, EtherTypeClassifierDefinition.IID,
                 EtherTypeClassifierDefinition.DEFINITION);
-        wt.put(LogicalDatastoreType.OPERATIONAL, IpProtoClassifierDefinition.IID,
+        wt.put(LogicalDatastoreType.CONFIGURATION, IpProtoClassifierDefinition.IID,
                 IpProtoClassifierDefinition.DEFINITION);
-        wt.put(LogicalDatastoreType.OPERATIONAL, L4ClassifierDefinition.IID,
+        wt.put(LogicalDatastoreType.CONFIGURATION, L4ClassifierDefinition.IID,
                 L4ClassifierDefinition.DEFINITION);
 
-        wt.put(LogicalDatastoreType.OPERATIONAL, AllowActionDefinition.IID,
+        wt.put(LogicalDatastoreType.CONFIGURATION, AllowActionDefinition.IID,
                 AllowActionDefinition.DEFINITION);
-        wt.put(LogicalDatastoreType.OPERATIONAL, ChainActionDefinition.IID,
+        wt.put(LogicalDatastoreType.CONFIGURATION, ChainActionDefinition.IID,
                 ChainActionDefinition.DEFINITION);
 
         wt.submit().checkedGet();
@@ -68,12 +63,12 @@ public class SubjectFeatureDefinitionProvider implements AutoCloseable {
     private void deleteSubjectFeatureDefinitions() throws TransactionCommitFailedException {
         WriteTransaction wt = this.dataProvider.newWriteOnlyTransaction();
 
-        wt.delete(LogicalDatastoreType.OPERATIONAL, EtherTypeClassifierDefinition.IID);
-        wt.delete(LogicalDatastoreType.OPERATIONAL, IpProtoClassifierDefinition.IID);
-        wt.delete(LogicalDatastoreType.OPERATIONAL, L4ClassifierDefinition.IID);
+        wt.delete(LogicalDatastoreType.CONFIGURATION, EtherTypeClassifierDefinition.IID);
+        wt.delete(LogicalDatastoreType.CONFIGURATION, IpProtoClassifierDefinition.IID);
+        wt.delete(LogicalDatastoreType.CONFIGURATION, L4ClassifierDefinition.IID);
 
-        wt.delete(LogicalDatastoreType.OPERATIONAL, AllowActionDefinition.IID);
-        wt.delete(LogicalDatastoreType.OPERATIONAL, ChainActionDefinition.IID);
+        wt.delete(LogicalDatastoreType.CONFIGURATION, AllowActionDefinition.IID);
+        wt.delete(LogicalDatastoreType.CONFIGURATION, ChainActionDefinition.IID);
 
         wt.submit().checkedGet();
     }
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/SupportedClassifierDefinitionListener.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/sf/SupportedClassifierDefinitionListener.java
new file mode 100644 (file)
index 0000000..6ccaa78
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.sf;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.Capabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
+
+public class SupportedClassifierDefinitionListener
+        implements DataTreeChangeListener<SupportedClassifierDefinition>, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SupportedClassifierDefinitionListener.class);
+
+    private final DataBroker dataProvider;
+    private final ListenerRegistration<SupportedClassifierDefinitionListener> registration;
+    @VisibleForTesting
+    final SetMultimap<ClassifierDefinitionId, InstanceIdentifier<SupportedClassifierDefinition>> supportedCdIidByCdId =
+            HashMultimap.create();
+    @VisibleForTesting
+    final Map<InstanceIdentifier<SupportedClassifierDefinition>, ClassifierInstanceValidator> ciValidatorBySupportedCdIid =
+            new HashMap<>();
+
+    public SupportedClassifierDefinitionListener(DataBroker dataProvider) {
+        this.dataProvider = checkNotNull(dataProvider);
+        registration =
+                dataProvider.registerDataTreeChangeListener(
+                        new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                                InstanceIdentifier.builder(Renderers.class)
+                                    .child(Renderer.class)
+                                    .child(Capabilities.class)
+                                    .child(SupportedClassifierDefinition.class)
+                                    .build()),
+                        this);
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<SupportedClassifierDefinition>> changes) {
+        for (DataTreeModification<SupportedClassifierDefinition> change : changes) {
+            DataObjectModification<SupportedClassifierDefinition> rootNode = change.getRootNode();
+            InstanceIdentifier<SupportedClassifierDefinition> rootIdentifier = change.getRootPath().getRootIdentifier();
+            switch (rootNode.getModificationType()) {
+                case WRITE:
+                    ClassifierDefinitionId classifierDefinitionId = rootNode.getDataAfter().getClassifierDefinitionId();
+                    if (containsParameters(rootNode.getDataAfter())) {
+                        ClassifierInstanceValidator ciValidator =
+                                new ClassifierInstanceValidator(rootNode.getDataAfter());
+                        ciValidatorBySupportedCdIid.put(rootIdentifier, ciValidator);
+                        // TODO register validator to Policy Resolver service
+                    }
+                    supportedCdIidByCdId.put(classifierDefinitionId, rootIdentifier);
+                    putOrRemoveClassifierDefinitionInOperDs(classifierDefinitionId);
+                    break;
+                case DELETE:
+                    classifierDefinitionId = rootNode.getDataBefore().getClassifierDefinitionId();
+                    // TODO unregister validator from Policy Resolver service
+                    supportedCdIidByCdId.remove(classifierDefinitionId, rootIdentifier);
+                    ciValidatorBySupportedCdIid.remove(rootIdentifier);
+                    putOrRemoveClassifierDefinitionInOperDs(classifierDefinitionId);
+                    break;
+                case SUBTREE_MODIFIED:
+                    classifierDefinitionId = rootNode.getDataAfter().getClassifierDefinitionId();
+                    if (containsParameters(rootNode.getDataAfter())) {
+                        ClassifierInstanceValidator ciValidator =
+                                new ClassifierInstanceValidator(rootNode.getDataAfter());
+                        ClassifierInstanceValidator oldCiValidator =
+                                ciValidatorBySupportedCdIid.put(rootIdentifier, ciValidator);
+                        // TODO unregister old validator from Policy Resolver service and register
+                        // new one
+                    }
+                    putOrRemoveClassifierDefinitionInOperDs(classifierDefinitionId);
+                    break;
+            }
+        }
+    }
+
+    private boolean containsParameters(SupportedClassifierDefinition supportedClassifierDefinition) {
+        return supportedClassifierDefinition.getSupportedParameterValues() != null
+                && !supportedClassifierDefinition.getSupportedParameterValues().isEmpty();
+    }
+
+    private void putOrRemoveClassifierDefinitionInOperDs(ClassifierDefinitionId classifierDefinitionId) {
+        ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+        ClassifierDefinition cd = createClassifierDefinitionWithUnionOfParams(classifierDefinitionId, rwTx);
+        if (cd != null) {
+            rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.classifierDefinitionIid(classifierDefinitionId), cd);
+        } else {
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                    IidFactory.classifierDefinitionIid(classifierDefinitionId), rwTx);
+        }
+        DataStoreHelper.submitToDs(rwTx);
+    }
+
+    @VisibleForTesting
+    ClassifierDefinition createClassifierDefinitionWithUnionOfParams(ClassifierDefinitionId classifierDefinitionId,
+            ReadTransaction rTx) {
+        Optional<ClassifierDefinition> potentialCdFromDs = DataStoreHelper.readFromDs(
+                LogicalDatastoreType.CONFIGURATION, IidFactory.classifierDefinitionIid(classifierDefinitionId), rTx);
+        if (!potentialCdFromDs.isPresent()) {
+            LOG.error("Classifier-definition with ID {} does not exist in CONF datastore.", classifierDefinitionId);
+            return null;
+        }
+        ClassifierDefinition cdFromDs = potentialCdFromDs.get();
+        Set<InstanceIdentifier<SupportedClassifierDefinition>> supportedCdIids =
+                supportedCdIidByCdId.get(classifierDefinitionId);
+        if (supportedCdIids.isEmpty()) {
+            LOG.debug("Classifier-definition with ID {} is not supported by any renderer.", classifierDefinitionId);
+            return null;
+        }
+        if (cdFromDs.getParameter() == null || cdFromDs.getParameter().isEmpty()) {
+            LOG.debug("Classifier-definition with ID {} does not contain any parameter", classifierDefinitionId);
+            return cdFromDs;
+        }
+        List<Parameter> params = new ArrayList<>();
+        for (InstanceIdentifier<SupportedClassifierDefinition> supportedCdIid : supportedCdIids) {
+            ClassifierInstanceValidator ciValidator = ciValidatorBySupportedCdIid.get(supportedCdIid);
+            Set<ParameterName> supportedParams = ciValidator.getSupportedParameters();
+            for (ParameterName supportedParamName : supportedParams) {
+                for (Parameter param : cdFromDs.getParameter()) {
+                    if (param.getName().equals(supportedParamName)) {
+                        params.add(param);
+                    }
+                }
+            }
+        }
+        ClassifierDefinitionBuilder cdBuilder = new ClassifierDefinitionBuilder(cdFromDs);
+        return cdBuilder.setParameter(params).build();
+    }
+
+    @Override
+    public void close() throws Exception {
+        registration.close();
+    }
+
+}
index ab0d137d93ea99efeecd112895609f0275a42765..311c7643025ff6bb435239538259a9a6732a1811 100755 (executable)
@@ -30,7 +30,7 @@ public class AllowActionDefinition {
         .setDescription(new Description("Allow the specified traffic to pass"))
         .build();
 
-    public static final InstanceIdentifier IID =
+    public static final InstanceIdentifier<ActionDefinition> IID =
             InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
                     .child(ActionDefinition.class, DEFINITION.getKey())
                     .build();
index f00cbc2de01a7f006086bd3f5ea81c704b6a9eb4..dfec4e5ea578a33850e606a4c25fd3738ca72182 100755 (executable)
@@ -46,7 +46,7 @@ public class ChainActionDefinition {
                     .build())))
         .build();
 
-    public static final InstanceIdentifier IID =
+    public static final InstanceIdentifier<ActionDefinition> IID =
             InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
                     .child(ActionDefinition.class, DEFINITION.getKey())
                     .build();
index 8275ec229239339a4da057adbfd42d73ae8b245f..b9a5b35b351359580d70c32862ff7e9dfbe760a9 100755 (executable)
@@ -59,7 +59,7 @@ public class EtherTypeClassifierDefinition {
                     .build()))
         .build();
 
-    public static final InstanceIdentifier IID =
+    public static final InstanceIdentifier<ClassifierDefinition> IID =
             InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
                     .child(ClassifierDefinition.class, DEFINITION.getKey())
                     .build();
index 9da66b3432082373159a305660669efbd96481b0..125bb9c8a518401d6ccbebd795e01cff737d9ce2 100755 (executable)
@@ -66,7 +66,7 @@ public class IpProtoClassifierDefinition {
                                             .build()))
                     .build();
 
-    public static final InstanceIdentifier IID =
+    public static final InstanceIdentifier<ClassifierDefinition> IID =
             InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
                     .child(ClassifierDefinition.class, DEFINITION.getKey())
                     .build();
index da922cf1a534d72f47229b905f268ba11cfa11a3..3f0d7bf6ab8fedca241c0256d2bd05b7ecd382ab 100755 (executable)
@@ -14,6 +14,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.IsRequired;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.Type;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.ParameterBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
@@ -56,21 +57,26 @@ public class L4ClassifierDefinition {
                         new ParameterBuilder().setName(new ParameterName(SRC_PORT_PARAM))
                             .setDescription(new Description("The source port number to match against"))
                             .setType(Type.Int)
+                            .setIsRequired(IsRequired.Optional)
                             .build(),
                         new ParameterBuilder().setName(new ParameterName(SRC_PORT_RANGE_PARAM))
                             .setDescription(new Description("The source port range to match against"))
                             .setType(Type.Range)
+                            .setIsRequired(IsRequired.Optional)
                             .build(),
                         new ParameterBuilder().setName(new ParameterName(DST_PORT_PARAM))
                             .setDescription(new Description("The destination port number to match against"))
                             .setType(Type.Int)
-                            .build(), new ParameterBuilder().setName(new ParameterName(DST_PORT_RANGE_PARAM))
+                            .setIsRequired(IsRequired.Optional)
+                            .build(), 
+                        new ParameterBuilder().setName(new ParameterName(DST_PORT_RANGE_PARAM))
                             .setDescription(new Description("The destination port range to match against"))
                             .setType(Type.Range)
+                            .setIsRequired(IsRequired.Optional)
                             .build()))
         .build();
 
-    public static final InstanceIdentifier IID =
+    public static final InstanceIdentifier<ClassifierDefinition> IID =
             InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
                     .child(ClassifierDefinition.class, DEFINITION.getKey())
                     .build();
index 81999b96d7cc31fff4b4fa07b85bc8a02ca2b6e4..1602ce2c928e0d425ceb41d2c03c25feb4ac95ce 100644 (file)
@@ -12,6 +12,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
@@ -31,9 +32,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
@@ -153,6 +157,13 @@ public class IidFactory {
             .build();
     }
 
+    public static InstanceIdentifier<ClassifierDefinition> classifierDefinitionIid(
+            ClassifierDefinitionId classifierDefinitionId) {
+        return InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
+            .child(ClassifierDefinition.class, new ClassifierDefinitionKey(classifierDefinitionId))
+            .build();
+    }
+
     public static InstanceIdentifier<ClassifierRef> classifierRefIid(TenantId tenantId, ContractId contractId,
             SubjectName subjectName, RuleName ruleName, ClassifierName classifierRefName) {
         return InstanceIdentifier.builder(Tenants.class)
old mode 100644 (file)
new mode 100755 (executable)
index 6149142..2e63e9a
@@ -63,6 +63,13 @@ module gbp-common {
         description "A globally unique identifier";
     }
 
+    typedef unique-id-string {
+        type string {
+            length "1..256";
+        }
+        description "A globally unique identifier (based on String)";
+    }
+
     // *************
     // Relator names
     // *************
@@ -218,7 +225,7 @@ module gbp-common {
     // ****************
 
     typedef subject-feature-id {
-        type unique-id;
+        type unique-id-string;
         description "A unique ID for a parameterized object";
     }
 
index caa7325cb1b9672cb34a25e1c95b18832dffb786..a9b90bc57d775fe6fcb9db64e5afc2998195dbd1 100755 (executable)
@@ -636,6 +636,37 @@ module policy {
     // Global Configuration
     // ********************
 
+    grouping classifier-definition-fields {
+        uses subject-feature-definition;
+
+        leaf id {
+            description "A unique ID for the classifier definition";
+            type gbp-common:classifier-definition-id;
+            mandatory true;
+        }
+
+        leaf name {
+            description
+                "A user-visible name for the classifier definition";
+            type gbp-common:classifier-name;
+        }
+    }
+
+    grouping action-definition-fields {
+        uses subject-feature-definition;
+
+        leaf id {
+            description "A unique ID for the action";
+            type gbp-common:action-definition-id;
+            mandatory true;
+        }
+
+        leaf name {
+            description "A user-visible name for the action";
+            type gbp-common:action-name;
+        }
+    }
+
     container subject-feature-definitions {
         description
             "Contains configuration for the set of actions and
@@ -667,19 +698,7 @@ module policy {
                  references it.";
 
             key "id";
-            uses subject-feature-definition;
-
-            leaf id {
-                description "A unique ID for the classifier definition";
-                type gbp-common:classifier-definition-id;
-                mandatory true;
-            }
-
-            leaf name {
-                description
-                    "A user-visible name for the classifier definition";
-                type gbp-common:classifier-name;
-            }
+            uses classifier-definition-fields;
         }
 
         list action-definition {
@@ -690,18 +709,7 @@ module policy {
                  references it.";
 
             key "id";
-            uses subject-feature-definition;
-
-            leaf id {
-                description "A unique ID for the action";
-                type gbp-common:action-definition-id;
-                mandatory true;
-            }
-
-            leaf name {
-                description "A user-visible name for the action";
-                type gbp-common:action-name;
-            }
+            uses action-definition-fields;
         }
     }
 
diff --git a/groupbasedpolicy/src/main/yang/model/renderer.yang b/groupbasedpolicy/src/main/yang/model/renderer.yang
new file mode 100755 (executable)
index 0000000..d725024
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+module renderer {
+    yang-version 1;
+
+    namespace "urn:opendaylight:groupbasedpolicy:renderer";
+    prefix "gbp-renderer";
+
+    import gbp-common {
+        prefix gbp-common;
+        revision-date 2014-04-21;
+    }
+    import policy {
+        prefix policy;
+        revision-date 2014-04-21;
+    }
+    import ietf-inet-types {
+        prefix inet;
+        revision-date 2010-09-24;
+    }
+
+    description
+        "This module defines renderer capabilities.";
+
+    revision "2015-11-03" {
+        description
+            "Initial revision.";
+    }
+
+    typedef renderer-name {
+        type gbp-common:name;
+        description "A name for a renderer";
+    }
+
+    grouping supported-string-value-fields {
+        list supported-string-value {
+            description "String value has to be identical.";
+            key value;
+            leaf value {
+                type string;
+            }
+        }
+    }
+
+    grouping supported-int-value-fields {
+        list supported-int-value {
+            description "Int value has to be identical.";
+            key value;
+            leaf value {
+                type int64;
+            }
+        }
+        list supported-int-value-in-range {
+            description "Int value has to be inside the range include boundaries.";
+            key "min max";
+            leaf min {
+                type int64;
+            }
+            leaf max {
+                type int64;
+            }
+        }
+    }
+
+    grouping supported-range-value-fields {
+        list supported-range-value {
+            description "Min and max values have to be inside the range include boundaries.";
+            key "min max";
+            leaf min {
+                type int64;
+            }
+            leaf max {
+                type int64;
+            }
+        }
+    }
+
+    grouping has-parameters-type {
+        choice parameter-type {
+            case string {
+                uses supported-string-value-fields;
+            }
+            case int {
+                uses supported-int-value-fields;
+            }
+            case range {
+                uses supported-range-value-fields;
+            }
+        }
+    }
+
+    container renderers {
+        description
+            "Leaf containing all renderers' description.";
+
+        config false;
+
+        list renderer {
+            description
+                "A renderer provides a list of capabilities.";
+
+            key name;
+
+            leaf name {
+                description
+                    "A user-visible name for the renderer";
+                type renderer-name;
+            }
+
+            container capabilities {
+                description "Capabilities this renderer provides.";
+
+                list supported-classifier-definition {
+                    description
+                        "Classifier definitions this renderer can use.";
+
+                    key classifier-definition-id;
+
+                    leaf classifier-definition-id {
+                        description "Reference to a classifier definition in config datastore.";
+                        type leafref {
+                            path "/policy:subject-feature-definitions/policy:classifier-definition/policy:id";
+                        }
+                    }
+
+                    leaf parent-classifier-definition-id {
+                        description
+                            "Optional reference to a parent classifier definition,
+                            to provide a hierarchical structure.";
+                        type leafref {
+                            path "/policy:subject-feature-definitions/policy:classifier-definition/policy:id";
+                        }
+                    }
+
+                    list supported-parameter-values {
+                        description "Represents supported paramters and its values by renderer.
+                            If it contains only parameter-name without paramater-type, it means that any value is supported.";
+                        key parameter-name;
+
+                        leaf parameter-name {
+                            description "TODO";
+                            type leafref {
+                                path "/policy:subject-feature-definitions/policy:classifier-definition/policy:parameter/policy:name";
+                            }
+                        }
+
+                        uses has-parameters-type;
+                    }
+                }
+
+                list supported-action-definition {
+                    description
+                        "Action definitions this renderer can use.";
+
+                    key action-definition-id;
+
+                    leaf action-definition-id {
+                        description "Reference to an action definition in config datastore.";
+                        type leafref {
+                            path "/policy:subject-feature-definitions/policy:action-definition/policy:id";
+                        }
+                    }
+
+                    leaf parent-action-definition-id {
+                        description
+                            "Optional reference to a parent action definition,
+                            to provide a hierarchical structure.";
+                        type leafref {
+                            path "/policy:subject-feature-definitions/policy:action-definition/policy:id";
+                        }
+                    }
+
+                    list supported-parameter-values {
+                        description "Represents supported paramters and its values by renderer.
+                            If it contains only parameter-name without paramater-type, it means that any value is supported.";
+                        key parameter-name;
+
+                        leaf parameter-name {
+                            description "TODO";
+                            type leafref {
+                                path "/policy:subject-feature-definitions/policy:action-definition/policy:parameter/policy:name";
+                            }
+                        }
+
+                        uses has-parameters-type;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/sf/SupportedClassifierDefinitionListenerTest.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/sf/SupportedClassifierDefinitionListenerTest.java
new file mode 100755 (executable)
index 0000000..5ab03f8
--- /dev/null
@@ -0,0 +1,110 @@
+package org.opendaylight.groupbasedpolicy.sf;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.sf.classifiers.EtherTypeClassifierDefinition;
+import org.opendaylight.groupbasedpolicy.sf.classifiers.L4ClassifierDefinition;
+import org.opendaylight.groupbasedpolicy.test.GbpDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.Capabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.collect.ImmutableList;
+
+public class SupportedClassifierDefinitionListenerTest extends GbpDataBrokerTest {
+
+    private SupportedClassifierDefinitionListener listener;
+
+    @Before
+    public void init() {
+        listener = new SupportedClassifierDefinitionListener(getDataBroker());
+    }
+
+    @Test
+    public void testCreateClassifierDefinitionWithUnionOfParams_allParamsSupportedByRenderer() throws Exception {
+        WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.classifierDefinitionIid(EtherTypeClassifierDefinition.ID),
+                EtherTypeClassifierDefinition.DEFINITION, true);
+        wTx.submit().get();
+
+        SupportedClassifierDefinition supportedClassifierDefinition = new SupportedClassifierDefinitionBuilder()
+            .setClassifierDefinitionId(EtherTypeClassifierDefinition.ID)
+            .setSupportedParameterValues(
+                    ImmutableList.<SupportedParameterValues>of(new SupportedParameterValuesBuilder()
+                        .setParameterName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM)).build()))
+            .build();
+        Renderer renderer = createRenderer("renderer1");
+        registerSupportedClassifierDefByRenderer(supportedClassifierDefinition, renderer);
+
+        ClassifierDefinition newCd = listener.createClassifierDefinitionWithUnionOfParams(
+                EtherTypeClassifierDefinition.ID, getDataBroker().newReadOnlyTransaction());
+        Assert.assertEquals(EtherTypeClassifierDefinition.DEFINITION, newCd);
+    }
+
+    @Test
+    public void testCreateClassifierDefinitionWithUnionOfParams_someParamsSupportedByRenderer() throws Exception {
+        WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.classifierDefinitionIid(L4ClassifierDefinition.ID),
+                L4ClassifierDefinition.DEFINITION, true);
+        wTx.submit().get();
+
+        SupportedClassifierDefinition supportedClassifierDefinition = new SupportedClassifierDefinitionBuilder()
+            .setClassifierDefinitionId(L4ClassifierDefinition.ID)
+            .setSupportedParameterValues(
+                    ImmutableList.<SupportedParameterValues>of(new SupportedParameterValuesBuilder()
+                        .setParameterName(new ParameterName(L4ClassifierDefinition.DST_PORT_PARAM)).build()))
+            .build();
+        Renderer renderer = createRenderer("renderer1");
+        registerSupportedClassifierDefByRenderer(supportedClassifierDefinition, renderer);
+
+        ClassifierDefinition newCd = listener.createClassifierDefinitionWithUnionOfParams(L4ClassifierDefinition.ID,
+                getDataBroker().newReadOnlyTransaction());
+        ClassifierDefinition expectedCd = new ClassifierDefinitionBuilder(L4ClassifierDefinition.DEFINITION)
+            .setParameter(ImmutableList.<Parameter>of(getParameterFromDefinition(L4ClassifierDefinition.DEFINITION,
+                    L4ClassifierDefinition.DST_PORT_PARAM)))
+            .build();
+        Assert.assertEquals(expectedCd, newCd);
+    }
+
+    private Renderer createRenderer(String rendererName) {
+        return new RendererBuilder().setName(new RendererName(rendererName)).build();
+    }
+
+    private Parameter getParameterFromDefinition(ClassifierDefinition cd, String parameter) {
+        for (Parameter param : cd.getParameter()) {
+            if (param.getName().getValue().equals(parameter)) {
+                return param;
+            }
+        }
+        throw new IllegalArgumentException("Parameter " + parameter + " is not located in " + cd);
+    }
+
+    private void registerSupportedClassifierDefByRenderer(SupportedClassifierDefinition supportedClassifierDefinition,
+            Renderer renderer) {
+        InstanceIdentifier<SupportedClassifierDefinition> scdIid = InstanceIdentifier.builder(Renderers.class)
+            .child(Renderer.class, renderer.getKey())
+            .child(Capabilities.class)
+            .child(SupportedClassifierDefinition.class, supportedClassifierDefinition.getKey())
+            .build();
+        listener.ciValidatorBySupportedCdIid.put(scdIid,
+                new ClassifierInstanceValidator(supportedClassifierDefinition));
+        listener.supportedCdIidByCdId.put(supportedClassifierDefinition.getClassifierDefinitionId(), scdIid);
+    }
+
+}
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/test/CustomDataBrokerTest.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/test/CustomDataBrokerTest.java
new file mode 100644 (file)
index 0000000..d838b86
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.test;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+
+/**
+ * Loads only modules of GBP and it's dependencies for data broker.
+ * <br>
+ * Therefore this implementation is faster than {@link AbstractDataBrokerTest}
+ */
+public abstract class CustomDataBrokerTest extends AbstractDataBrokerTest {
+
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo>builder();
+        for (Class<?> clazz : getClassesFromModules()) {
+            loadModuleInfos(clazz, moduleInfoSet);
+        }
+        return moduleInfoSet.build();
+    }
+
+    /**
+     * @return a class from every yang module which needs to be loaded. Cannot return {@code null}
+     *         or empty collection.
+     */
+    public abstract @Nonnull Collection<Class<?>> getClassesFromModules();
+
+    public static void loadModuleInfos(Class<?> clazzFromModule, Builder<YangModuleInfo> moduleInfoSet)
+            throws Exception {
+        YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(clazzFromModule);
+        checkState(moduleInfo != null, "Module Info for %s is not available.", clazzFromModule);
+        collectYangModuleInfo(moduleInfo, moduleInfoSet);
+    }
+
+    private static void collectYangModuleInfo(final YangModuleInfo moduleInfo,
+            final Builder<YangModuleInfo> moduleInfoSet) throws IOException {
+        moduleInfoSet.add(moduleInfo);
+        for (YangModuleInfo dependency : moduleInfo.getImportedModules()) {
+            collectYangModuleInfo(dependency, moduleInfoSet);
+        }
+    }
+}
diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/test/GbpDataBrokerTest.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/test/GbpDataBrokerTest.java
new file mode 100644 (file)
index 0000000..5300147
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.test;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Loads only modules of GBP and it's dependencies for data broker.
+ * <br>
+ * Therefore this implementation is faster than {@link AbstractDataBrokerTest}
+ */
+public class GbpDataBrokerTest extends CustomDataBrokerTest {
+
+    @Override
+    public Collection<Class<?>> getClassesFromModules() {
+        return ImmutableList.<Class<?>>of(Renderers.class, Tenants.class, Endpoints.class, ResolvedPolicies.class);
+    }
+
+}
old mode 100644 (file)
new mode 100755 (executable)
index f9d4b39..b774aee
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <version>${mdsal.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
   <!-- project build -->
       </plugin>
     </plugins>
   </build>
-</project>
\ No newline at end of file
+</project>
index c599f1eb87cd10bdd8f9e2c81949e07938c1ed42..f50f57f47b324f68f2738cd92c26bd4d7a0a9106 100755 (executable)
@@ -122,16 +122,7 @@ public class PolicyManager
                     + "Max. table ID would be out of range. Check config-subsystem.\n{}", e);
         }
 
-        // TODO this will be writing to capabilities in DS
-//        if (dataBroker != null) {
-//            WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-//            t.put(LogicalDatastoreType.OPERATIONAL,
-//                  InstanceIdentifier
-//                      .builder(SubjectFeatureDefinitions.class)
-//                      .build(),
-//                  SubjectFeatures.OF_OVERLAY_FEATURES);
-//            t.submit();
-//        }
+        // TODO write capabilities in DS
 
         for(Entry<ActionDefinitionId, Action> entry : SubjectFeatures.getActions().entrySet()) {
             policyResolver.registerActionDefinitions(entry.getKey(), entry.getValue());
old mode 100644 (file)
new mode 100755 (executable)
index 4e26d84..331b684
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- * 
+ *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
@@ -12,12 +12,12 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import com.google.common.base.Strings;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
-
-import com.google.common.base.Strings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
 
 /**
  * Represent a classifier definition, and provide tools for generating flow
@@ -47,7 +47,7 @@ public abstract class Classifier {
      *
      * @return the {@link ClassifierDefinition} for this classifier
      */
-    public abstract ClassifierDefinition getClassDef();
+    public abstract ClassifierDefinition getClassifierDefinition();
 
     /**
      * @return parent classifier, see {@link Classifier}
@@ -83,7 +83,7 @@ public abstract class Classifier {
                 } catch (IllegalArgumentException e) {
                     hasReqParams = false;
                 }
-                if (hasReqParams == true) {
+                if (hasReqParams) {
                     matchBuilders = parent.update(matchBuilders, params);
                     updatedClassifiers.add(parent);
                 }
@@ -102,6 +102,8 @@ public abstract class Classifier {
         return new ClassificationResult(matchBuilders);
     }
 
+    public abstract List<SupportedParameterValues> getSupportedParameterValues();
+
     /**
      * Checks presence of required {@code params} in order to decide if classifier can update {@code matches} properly
      * in  method {@link #update(List, Map)}
index 6f1c4034cd5a1329a8be503ebb5f8abdcfeb09a7..7f788279967bb042558e334e616fc0cef5cd3f2e 100755 (executable)
@@ -11,11 +11,18 @@ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
 import java.util.List;
 import java.util.Map;
 
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.EtherTypeClassifierDefinition;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
 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.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
@@ -36,24 +43,42 @@ public class EtherTypeClassifier extends Classifier {
     }
 
     @Override
-    public ClassifierDefinition getClassDef() {
+    public ClassifierDefinition getClassifierDefinition() {
         return EtherTypeClassifierDefinition.DEFINITION;
     }
 
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+
+        List<SupportedIntValue> values = ImmutableList.of(
+                new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.ARP_VALUE)
+                        .build(),
+                new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv4_VALUE)
+                        .build(),
+                new SupportedIntValueBuilder().setValue(EtherTypeClassifierDefinition.IPv6_VALUE)
+                        .build());
+        SupportedParameterValuesBuilder b = new SupportedParameterValuesBuilder();
+        b.setParameterName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM));
+        b.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+        return ImmutableList.of(b.build());
+    }
+
     @Override
     protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
         if (params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM) == null) {
-            throw new IllegalArgumentException("Parameter " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM
-                    + " not specified.");
+            throw new IllegalArgumentException(
+                    "Parameter " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " not specified.");
         }
         if (params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM).getIntValue() == null) {
-            throw new IllegalArgumentException("Value of " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM
-                    + " parameter is not present.");
+            throw new IllegalArgumentException(
+                    "Value of " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " parameter is not present.");
         }
     }
 
     @Override
-    protected List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
+    protected List<MatchBuilder> update(List<MatchBuilder> matches,
+            Map<String, ParameterValue> params) {
         Long type = params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM).getIntValue();
         for (MatchBuilder match : matches) {
             EthernetMatchBuilder em;
@@ -72,10 +97,10 @@ public class EtherTypeClassifier extends Classifier {
     private void equalOrNotSetValidation(EthernetType ethTypeInMatch, long paramValue) {
         if (ethTypeInMatch != null) {
             if (paramValue != ethTypeInMatch.getType().getValue().longValue()) {
-                throw new IllegalArgumentException("Classification conflict detected at "
-                        + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " parameter for values "
-                        + ethTypeInMatch.getType().getValue() + " and " + paramValue + ". It is not allowed "
-                        + "to assign different values to the same parameter among all the classifiers within one rule.");
+                throw new IllegalArgumentException(
+                        "Classification conflict detected at " + EtherTypeClassifierDefinition.ETHERTYPE_PARAM + " parameter for values " + ethTypeInMatch
+                                .getType()
+                                .getValue() + " and " + paramValue + ". It is not allowed " + "to assign different values to the same parameter among all the classifiers within one rule.");
             }
         }
     }
old mode 100644 (file)
new mode 100755 (executable)
index 039adfe..d1ea4f9
@@ -11,13 +11,20 @@ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
 import java.util.List;
 import java.util.Map;
 
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.IpProtoClassifierDefinition;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.EtherTypeClassifierDefinition;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
 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.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
 
 /**
@@ -35,10 +42,29 @@ public class IpProtoClassifier extends Classifier {
     }
 
     @Override
-    public ClassifierDefinition getClassDef() {
+    public ClassifierDefinition getClassifierDefinition() {
         return IpProtoClassifierDefinition.DEFINITION;
     }
 
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+
+        List<SupportedIntValue> values = ImmutableList.of(
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.ICMP_VALUE)
+                        .build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.SCTP_VALUE)
+                        .build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.TCP_VALUE)
+                        .build(),
+                new SupportedIntValueBuilder().setValue(IpProtoClassifierDefinition.UDP_VALUE)
+                        .build());
+        SupportedParameterValuesBuilder b = new SupportedParameterValuesBuilder();
+        b.setParameterName(new ParameterName(IpProtoClassifierDefinition.PROTO_PARAM));
+        b.setParameterType(new IntBuilder().setSupportedIntValue(values).build());
+
+        return ImmutableList.of(b.build());
+    }
+
     @Override
     protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
         if (params.get(IpProtoClassifierDefinition.PROTO_PARAM) == null) {
index 6d9966af1af74e67dadbba21d4f1eafab6810f18..832a585029e3a5a374d32f093f6e8705560d3a09 100755 (executable)
@@ -14,14 +14,23 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.IpProtoClassifierDefinition;
 import org.opendaylight.groupbasedpolicy.sf.classifiers.L4ClassifierDefinition;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.parameters.type.parameter.type.IntBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValuesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueInRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported._int.value.fields.SupportedIntValueInRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported.range.value.fields.SupportedRangeValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.supported.range.value.fields.SupportedRangeValueBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;
@@ -45,10 +54,41 @@ public class L4Classifier extends Classifier {
     }
 
     @Override
-    public ClassifierDefinition getClassDef() {
+    public ClassifierDefinition getClassifierDefinition() {
         return L4ClassifierDefinition.DEFINITION;
     }
 
+    @Override
+    public List<SupportedParameterValues> getSupportedParameterValues() {
+        List<SupportedIntValueInRange> allPossiblePortsIntInRange = ImmutableList.of(
+                new SupportedIntValueInRangeBuilder().setMin(1L).setMax(65535L).build());
+        List<SupportedRangeValue> allPossiblePortsRange = ImmutableList.of(
+                new SupportedRangeValueBuilder().setMin(1L).setMax(65535L).build());
+
+        SupportedParameterValuesBuilder srcPorts = new SupportedParameterValuesBuilder();
+        srcPorts.setParameterName(new ParameterName(L4ClassifierDefinition.SRC_PORT_PARAM));
+        srcPorts.setParameterType(
+                new IntBuilder().setSupportedIntValueInRange(allPossiblePortsIntInRange).build());
+
+        SupportedParameterValuesBuilder dstPorts = new SupportedParameterValuesBuilder();
+        dstPorts.setParameterName(new ParameterName(L4ClassifierDefinition.DST_PORT_PARAM));
+        dstPorts.setParameterType(
+                new IntBuilder().setSupportedIntValueInRange(allPossiblePortsIntInRange).build());
+
+        SupportedParameterValuesBuilder srcPortsRange = new SupportedParameterValuesBuilder();
+        srcPorts.setParameterName(new ParameterName(L4ClassifierDefinition.SRC_PORT_RANGE_PARAM));
+        srcPorts.setParameterType(
+                new IntBuilder().setSupportedIntValueInRange(allPossiblePortsIntInRange).build());
+
+        SupportedParameterValuesBuilder dstPortsRange = new SupportedParameterValuesBuilder();
+        dstPorts.setParameterName(new ParameterName(L4ClassifierDefinition.DST_PORT_RANGE_PARAM));
+        dstPorts.setParameterType(
+                new IntBuilder().setSupportedIntValueInRange(allPossiblePortsIntInRange).build());
+
+        return ImmutableList.of(srcPorts.build(), dstPorts.build(), srcPortsRange.build(),
+                dstPortsRange.build());
+    }
+
     @Override
     protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
         validatePortParam(params, L4ClassifierDefinition.SRC_PORT_PARAM, L4ClassifierDefinition.SRC_PORT_RANGE_PARAM);
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatureDefinitionsListener.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatureDefinitionsListener.java
new file mode 100755 (executable)
index 0000000..b5d5925
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.Capabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinitionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.supported.classifier.definition.SupportedParameterValues;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SubjectFeatureDefinitionsListener
+        implements DataTreeChangeListener<ClassifierDefinition>, AutoCloseable {
+
+    private static final Logger LOG =
+            LoggerFactory.getLogger(SubjectFeatureDefinitionsListener.class);
+
+    private final DataBroker dataProvider;
+    private final ListenerRegistration<SubjectFeatureDefinitionsListener> registration;
+
+    private static final Map<ClassifierDefinitionId, Classifier> OF_CLASSIFIERS =
+            SubjectFeatures.getClassifiers();
+
+    public SubjectFeatureDefinitionsListener(DataBroker dataProvider) {
+        this.dataProvider = checkNotNull(dataProvider);
+        registration = dataProvider.registerDataTreeChangeListener(
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                        InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
+                                .child(ClassifierDefinition.class)
+                                .build()), this);
+
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<ClassifierDefinition>> changes) {
+
+        for (DataTreeModification<ClassifierDefinition> change : changes) {
+            DataObjectModification<ClassifierDefinition> rootNode = change.getRootNode();
+
+            List<SupportedClassifierDefinition> supportedClassifierDefinitions = new ArrayList<>();
+
+            switch (rootNode.getModificationType()) {
+                case WRITE:
+                case SUBTREE_MODIFIED:
+                    ClassifierDefinition classifierDefinitionAfter =
+                            checkNotNull(rootNode.getDataAfter());
+                    Classifier ourClassifier =
+                            OF_CLASSIFIERS.get(classifierDefinitionAfter.getId());
+                    if (ourClassifier != null) {
+                        List<SupportedParameterValues> spValues =
+                                ourClassifier.getSupportedParameterValues();
+
+                        SupportedClassifierDefinitionBuilder scdBuilder =
+                                new SupportedClassifierDefinitionBuilder().setClassifierDefinitionId(
+                                        ourClassifier.getClassifierDefinition().getId())
+                                        .setSupportedParameterValues(spValues);
+                        if (ourClassifier.getParent() != null) {
+                            scdBuilder.setParentClassifierDefinitionId(
+                                    ourClassifier.getParent().getId());
+                        }
+                        supportedClassifierDefinitions.add(scdBuilder.build());
+                    }
+
+                    if (!supportedClassifierDefinitions.isEmpty()) {
+                        WriteTransaction wt = dataProvider.newWriteOnlyTransaction();
+                        for (SupportedClassifierDefinition def : supportedClassifierDefinitions) {
+                            wt.put(LogicalDatastoreType.OPERATIONAL,
+                                    InstanceIdentifier.builder(Renderers.class)
+                                            .child(Renderer.class)
+                                            .child(Capabilities.class)
+                                            .child(SupportedClassifierDefinition.class)
+                                            .build(), def, true);
+                        }
+                        wt.submit();
+                    }
+                    break;
+
+                case DELETE:
+                    ClassifierDefinition classifierDefinitionBefore =
+                            checkNotNull(rootNode.getDataAfter());
+                    ClassifierDefinitionId id = classifierDefinitionBefore.getId();
+                    WriteTransaction wt = dataProvider.newWriteOnlyTransaction();
+                    wt.delete(LogicalDatastoreType.OPERATIONAL,
+                            InstanceIdentifier.builder(Renderers.class)
+                                    .child(Renderer.class)
+                                    .child(Capabilities.class)
+                                    .child(SupportedClassifierDefinition.class,
+                                            new SupportedClassifierDefinitionKey(id))
+                                    .build());
+                    wt.submit();
+                    break;
+            }
+
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        registration.close();
+    }
+}
index 313a7b6d80d8b58ea18359e34eb54037d7caa2da..a490fbc04741d493f354af5da72cf37ac29a6152 100755 (executable)
@@ -33,26 +33,25 @@ import com.google.common.collect.ImmutableMap;
  * Defines the subject features that are supported by the OF overlay renderer
  */
 public class SubjectFeatures {
-    private static final Map<ClassifierDefinitionId, Classifier> classifiers =
-            ImmutableMap.<ClassifierDefinitionId, Classifier>
-                of(EtherTypeClassifierDefinition.ID, Classifier.ETHER_TYPE_CL,
-                   IpProtoClassifierDefinition.ID, Classifier.IP_PROTO_CL,
-                   L4ClassifierDefinition.ID, Classifier.L4_CL);
+
+    private static final Map<ClassifierDefinitionId, Classifier> classifiers = ImmutableMap.
+            of(EtherTypeClassifierDefinition.ID, Classifier.ETHER_TYPE_CL,
+                    IpProtoClassifierDefinition.ID, Classifier.IP_PROTO_CL,
+                    L4ClassifierDefinition.ID, Classifier.L4_CL);
 
     private static final List<ClassifierDefinition> classifierDefs =
             ImmutableList.copyOf(Collections2.transform(classifiers.values(),
                 new Function<Classifier, ClassifierDefinition>() {
                     @Override
                     public ClassifierDefinition apply(Classifier input) {
-                        return input.getClassDef();
+                        return input.getClassifierDefinition();
                     }
                 }
             ));
 
-    private static final Map<ActionDefinitionId, Action> actions =
-            ImmutableMap.<ActionDefinitionId, Action>
-                of(AllowActionDefinition.ID, new AllowAction(),
-                   ChainActionDefinition.ID, new ChainAction());
+    private static final Map<ActionDefinitionId, Action> actions = ImmutableMap.
+            of(AllowActionDefinition.ID, new AllowAction(), ChainActionDefinition.ID,
+                    new ChainAction());
 
     private static final List<ActionDefinition> actionDefs =
             ImmutableList.copyOf(Collections2.transform(actions.values(),
@@ -81,6 +80,11 @@ public class SubjectFeatures {
         return classifiers.get(id);
     }
 
+
+    public static Map<ClassifierDefinitionId, Classifier> getClassifiers() {
+        return classifiers;
+    }
+
     public static Map<ActionDefinitionId, Action> getActions() {
         return actions;
     }
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatureDefinitionsListenerTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatureDefinitionsListenerTest.java
new file mode 100755 (executable)
index 0000000..7b48939
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.groupbasedpolicy.sf.classifiers.EtherTypeClassifierDefinition;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.ParameterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.Capabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.capabilities.SupportedClassifierDefinitionKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubjectFeatureDefinitionsListenerTest extends AbstractDataBrokerTest {
+
+    private static final Parameter PARAM_INT =
+            new ParameterBuilder().setName(new ParameterName("paramInt"))
+                    .setType(Parameter.Type.Int)
+                    .build();
+    private static final ClassifierDefinition CD_WITH_PARAM_INT =
+            new ClassifierDefinitionBuilder().setId(
+                    new ClassifierDefinitionId(EtherTypeClassifierDefinition.ID.getValue()))
+                    .setDescription(new Description("some description"))
+                    .setName(new ClassifierName("cd_with_one_param"))
+                    .setParameter(ImmutableList.of(PARAM_INT))
+                    .build();
+
+    @Test
+    public void testPutEtherTypeClassifierDefinition() throws Exception {
+        Renderer renderer1 = new RendererBuilder().setName(new RendererName("renderer1")).build();
+        WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(Renderers.class).child(Renderer.class, renderer1.getKey()).build(),
+                renderer1);
+
+        wTx.put(LogicalDatastoreType.CONFIGURATION,
+                IidFactory.classifierDefinitionIid(CD_WITH_PARAM_INT.getId()), CD_WITH_PARAM_INT,
+                true);
+        wTx.submit().get();
+
+        ReadOnlyTransaction rTx = getDataBroker().newReadOnlyTransaction();
+        CheckedFuture<Optional<SupportedClassifierDefinition>, ReadFailedException> f =
+                rTx.read(LogicalDatastoreType.OPERATIONAL,
+                        InstanceIdentifier.builder(Renderers.class)
+                                .child(Renderer.class, renderer1.getKey())
+                                .child(Capabilities.class)
+                                .child(SupportedClassifierDefinition.class,
+                                        new SupportedClassifierDefinitionKey(
+                                                EtherTypeClassifierDefinition.ID))
+                                .build());
+        Futures.addCallback(f, new FutureCallback<Optional<SupportedClassifierDefinition>>() {
+
+            @Override
+            public void onSuccess(Optional<SupportedClassifierDefinition> result) {
+                if (result.isPresent()) {
+                    SupportedClassifierDefinition def = result.get();
+                    Assert.assertEquals(CD_WITH_PARAM_INT.getId(), def.getClassifierDefinitionId());
+                    Assert.assertEquals(SubjectFeatures.getClassifier(CD_WITH_PARAM_INT.getId())
+                            .getSupportedParameterValues(), def.getSupportedParameterValues());
+                }
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                throw new RuntimeException(t);
+            }
+        });
+        f.checkedGet();
+    }
+
+}