Classifiers - implementation changes. 04/17204/16
authorTomas Cechvala <tcechval@cisco.com>
Thu, 26 Mar 2015 23:03:29 +0000 (16:03 -0700)
committerTomas Cechvala <tcechval@cisco.com>
Thu, 2 Apr 2015 18:17:36 +0000 (11:17 -0700)
This commit solves bug 2883.

Change-Id: I1b5b886734833bd30129c71be78eb3a5af4387a8
Signed-off-by: Tomas Cechvala <tcechval@cisco.com>
15 files changed:
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcer.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassificationResult.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/Classifier.java
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
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/L4Classifier.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ParamDerivator.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/SubjectFeatures.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/OfTableTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassifierTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassifierTestUtils.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/EtherTypeClassifierTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/IpProtoClassifierTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/L4ClassifierTest.java [new file with mode: 0644]
util/dockerTestOfOverlay/policy_config.py

index 7a7937bfc24e792a32227e32944d550daf7dcb18..2ecfd5ebc7155557a0d65fe1a85bee384253f416 100644 (file)
@@ -24,8 +24,10 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ClassificationResult;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Classifier;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Action;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ParamDerivator;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
 import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
@@ -89,7 +91,7 @@ public class PolicyEnforcer extends FlowTable {
 
     @Override
     public void sync(ReadWriteTransaction t, InstanceIdentifier<Table> tiid,
-                     Map<String, FlowCtx> flowMap, NodeId nodeId, 
+                     Map<String, FlowCtx> flowMap, NodeId nodeId,
                      PolicyInfo policyInfo, Dirty dirty)
                              throws Exception {
         dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
@@ -100,12 +102,12 @@ public class PolicyEnforcer extends FlowTable {
         for (EgKey sepg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
             // Allow traffic within the same endpoint group if the policy
             // specifies
-            IndexedTenant tenant = 
+            IndexedTenant tenant =
                     ctx.getPolicyResolver().getTenant(sepg.getTenantId());
-            EndpointGroup group = 
+            EndpointGroup group =
                     tenant.getEndpointGroup(sepg.getEgId());
             IntraGroupPolicy igp = group.getIntraGroupPolicy();
-            int sepgId = 
+            int sepgId =
                     ctx.getPolicyManager().getContextOrdinal(sepg.getTenantId(),
                                                         sepg.getEgId());
             if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
@@ -115,46 +117,45 @@ public class PolicyEnforcer extends FlowTable {
             for (Endpoint src : ctx.getEndpointManager().getEPsForNode(nodeId, sepg)) {
                 if (src.getTenant() == null || src.getEndpointGroup() == null)
                     continue;
-                
-                List<ConditionName> conds = 
+
+                List<ConditionName> conds =
                         ctx.getEndpointManager().getCondsForEndpoint(src);
                 ConditionGroup scg = policyInfo.getEgCondGroup(sepg, conds);
                 int scgId = ctx.getPolicyManager().getCondGroupOrdinal(scg);
-                
+
                 Set<EgKey> peers = policyInfo.getPeers(sepg);
                 for (EgKey depg : peers) {
-                    int depgId = 
+                    int depgId =
                             ctx.getPolicyManager().getContextOrdinal(depg.getTenantId(),
                                                                 depg.getEgId());
-                
+
                     for (Endpoint dst : ctx.getEndpointManager().getEndpointsForGroup(depg)) {
-                
+
                         conds = ctx.getEndpointManager().getCondsForEndpoint(dst);
-                        ConditionGroup dcg = 
+                        ConditionGroup dcg =
                                 policyInfo.getEgCondGroup(new EgKey(dst.getTenant(),
                                                                     dst.getEndpointGroup()),
                                                           conds);
                         int dcgId = ctx.getPolicyManager().getCondGroupOrdinal(dcg);
-                        
+
                         CgPair p = new CgPair(depgId, sepgId, dcgId, scgId);
                         if (visitedPairs.contains(p)) continue;
                         visitedPairs.add(p);
-                        syncPolicy(t, tiid, flowMap, nodeId, policyInfo, 
+                        syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
                                    p, depg, sepg, dcg, scg);
-                
+
                         p = new CgPair(sepgId, depgId, scgId, dcgId);
                         if (visitedPairs.contains(p)) continue;
                         visitedPairs.add(p);
-                        syncPolicy(t, tiid, flowMap, nodeId, policyInfo, 
+                        syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
                                    p, sepg, depg, scg, dcg);
-                        
                     }
                 }
             }
         }
     }
-    
-    private void allowSameEpg(ReadWriteTransaction t, 
+
+    private void allowSameEpg(ReadWriteTransaction t,
                               InstanceIdentifier<Table> tiid,
                               Map<String, FlowCtx> flowMap, NodeId nodeId,
                               int sepgId) {
@@ -163,7 +164,7 @@ public class PolicyEnforcer extends FlowTable {
             .append(sepgId).toString());
         if (visit(flowMap, flowId.getValue())) {
             MatchBuilder mb = new MatchBuilder();
-            addNxRegMatch(mb, 
+            addNxRegMatch(mb,
                           RegMatch.of(NxmNxReg0.class,Long.valueOf(sepgId)),
                           RegMatch.of(NxmNxReg2.class,Long.valueOf(sepgId)));
             FlowBuilder flow = base()
@@ -174,8 +175,8 @@ public class PolicyEnforcer extends FlowTable {
             writeFlow(t, tiid, flow.build());
         }
     }
-    
-    private void allowFromTunnel(ReadWriteTransaction t, 
+
+    private void allowFromTunnel(ReadWriteTransaction t,
                                  InstanceIdentifier<Table> tiid,
                                  Map<String, FlowCtx> flowMap, NodeId nodeId) {
         NodeConnectorId tunPort =
@@ -186,7 +187,7 @@ public class PolicyEnforcer extends FlowTable {
         if (visit(flowMap, flowId.getValue())) {
             MatchBuilder mb = new MatchBuilder()
                 .setInPort(tunPort);
-            addNxRegMatch(mb, 
+            addNxRegMatch(mb,
                           RegMatch.of(NxmNxReg1.class,Long.valueOf(0xffffff)));
             FlowBuilder flow = base()
                 .setId(flowId)
@@ -196,19 +197,19 @@ public class PolicyEnforcer extends FlowTable {
             writeFlow(t, tiid, flow.build());
         }
     }
-    
-    private void syncPolicy(ReadWriteTransaction t, 
+
+    private void syncPolicy(ReadWriteTransaction t,
                             InstanceIdentifier<Table> tiid,
                             Map<String, FlowCtx> flowMap, NodeId nodeId,
-                            PolicyInfo policyInfo, 
+                            PolicyInfo policyInfo,
                             CgPair p, EgKey sepg, EgKey depg,
-                            ConditionGroup scg, ConditionGroup dcg) 
+                            ConditionGroup scg, ConditionGroup dcg)
                              throws Exception {
         // XXX - TODO raise an exception for rules between the same
         // endpoint group that are asymmetric
         Policy policy = policyInfo.getPolicy(sepg, depg);
         List<RuleGroup> rgs = policy.getRules(scg, dcg);
-        
+
         int priority = 65000;
         for (RuleGroup rg : rgs) {
             TenantId tenantId = rg.getContractTenant().getId();
@@ -218,7 +219,7 @@ public class PolicyEnforcer extends FlowTable {
                                     p, r, Direction.In, priority);
                 syncDirection(t, tiid, flowMap, nodeId, tenant,
                                     p, r, Direction.Out, priority);
-                
+
                 priority -= 1;
             }
         }
@@ -249,7 +250,7 @@ public class PolicyEnforcer extends FlowTable {
 
     }
 
-    private void syncDirection(ReadWriteTransaction t, 
+    private void syncDirection(ReadWriteTransaction t,
                                InstanceIdentifier<Table> tiid,
                                Map<String, FlowCtx> flowMap, NodeId nodeId,
                                IndexedTenant contractTenant,
@@ -308,15 +309,14 @@ public class PolicyEnforcer extends FlowTable {
             abl = act.updateAction(abl, new HashMap<String,Object>(),  0);
         }
 
-
         for (ClassifierRef cr : r.getClassifierRef()) {
-            if (cr.getDirection() != null && 
-                !cr.getDirection().equals(Direction.Bidirectional) && 
+            if (cr.getDirection() != null &&
+                !cr.getDirection().equals(Direction.Bidirectional) &&
                 !cr.getDirection().equals(d))
                 continue;
-            
+
             StringBuilder idb = new StringBuilder();
-            // XXX - TODO - implement connection tracking (requires openflow 
+            // XXX - TODO - implement connection tracking (requires openflow
             // extension and data plane support - in 2.4. Will need to handle
             // case where we are working with mix of nodes.
 
@@ -332,7 +332,7 @@ public class PolicyEnforcer extends FlowTable {
                     .append(p.dcgId)
                     .append("|")
                     .append(priority);
-                addNxRegMatch(baseMatch, 
+                addNxRegMatch(baseMatch,
                               RegMatch.of(NxmNxReg0.class,Long.valueOf(p.sepg)),
                               RegMatch.of(NxmNxReg1.class,Long.valueOf(p.scgId)),
                               RegMatch.of(NxmNxReg2.class,Long.valueOf(p.depg)),
@@ -346,19 +346,18 @@ public class PolicyEnforcer extends FlowTable {
                     .append("|")
                     .append(p.scgId)
                     .append("|")
-                    .append(priority);                
-                addNxRegMatch(baseMatch, 
+                    .append(priority);
+                addNxRegMatch(baseMatch,
                               RegMatch.of(NxmNxReg0.class,Long.valueOf(p.depg)),
                               RegMatch.of(NxmNxReg1.class,Long.valueOf(p.dcgId)),
                               RegMatch.of(NxmNxReg2.class,Long.valueOf(p.sepg)),
                               RegMatch.of(NxmNxReg3.class,Long.valueOf(p.scgId)));
             }
 
-
             ClassifierInstance ci = contractTenant.getClassifier(cr.getName());
             if (ci == null) {
                 // XXX TODO fail the match and raise an exception
-                LOG.warn("Classifier instance {} not found", 
+                LOG.warn("Classifier instance {} not found",
                          cr.getName().getValue());
                 return;
             }
@@ -366,41 +365,42 @@ public class PolicyEnforcer extends FlowTable {
                     .getClassifier(ci.getClassifierDefinitionId());
             if (cfier == null) {
                 // XXX TODO fail the match and raise an exception
-                LOG.warn("Classifier definition {} not found", 
+                LOG.warn("Classifier definition {} not found",
                          ci.getClassifierDefinitionId().getValue());
                 return;
             }
 
-            List<MatchBuilder> matches = Collections.singletonList(baseMatch);
-            Map<String,Object> params = new HashMap<>();
+            Map<String,ParameterValue> params = new HashMap<>();
             for (ParameterValue v : ci.getParameterValue()) {
-                if (v.getName() == null) continue;
                 if (v.getIntValue() != null) {
-                    params.put(v.getName().getValue(), v.getIntValue());
+                    params.put(v.getName().getValue(), v);
                 } else if (v.getStringValue() != null) {
-                    params.put(v.getName().getValue(), v.getStringValue());
+                    params.put(v.getName().getValue(), v);
                 } else if (v.getRangeValue() != null) {
-                    params.put(v.getName().getValue(), v.getRangeValue());
+                    params.put(v.getName().getValue(), v);
                 }
             }
-            
-            matches = cfier.updateMatch(matches, params);
-            String baseId = idb.toString();
-            FlowBuilder flow = base()
-                    .setPriority(Integer.valueOf(priority));
-            for (MatchBuilder match : matches) {
-                Match m = match.build();
-                FlowId flowId = new FlowId(baseId + "|" + m.toString());
-                if (visit(flowMap, flowId.getValue())) {
-                    flow.setMatch(m)
-                        .setId(flowId)
-                        .setPriority(Integer.valueOf(priority))
-                        .setInstructions(instructions(applyActionIns(abl)));
-                    writeFlow(t, tiid, flow.build());
+            List<Map<String, ParameterValue>> derivedParams = ParamDerivator.ETHER_TYPE_DERIVATOR.deriveParameter(params);
+            for (Map<String, ParameterValue> flowParams : derivedParams) {
+                List<MatchBuilder> matches = Collections.singletonList(new MatchBuilder(baseMatch.build()));
+                ClassificationResult result = cfier.updateMatch(matches, flowParams);
+                if(!result.isSuccessfull()) {
+                    //TODO consider different handling.
+                    throw new IllegalArgumentException(result.getMessage());
+                }
+                String baseId = idb.toString();
+                FlowBuilder flow = base().setPriority(Integer.valueOf(priority));
+                for (MatchBuilder match : result.getMatchBuilders()) {
+                    Match m = match.build();
+                    FlowId flowId = new FlowId(baseId + "|" + m.toString());
+                    if (visit(flowMap, flowId.getValue())) {
+                        flow.setMatch(m).setId(flowId).setPriority(Integer.valueOf(priority))
+                                .setInstructions(instructions(applyActionIns(abl)));
+                        writeFlow(t, tiid, flow.build());
+                    }
                 }
             }
-        } 
-
+        }
     }
 
     @Immutable
@@ -409,7 +409,7 @@ public class PolicyEnforcer extends FlowTable {
         private final int depg;
         private final int scgId;
         private final int dcgId;
-        
+
         public CgPair(int sepg, int depg, int scgId, int dcgId) {
             super();
             this.sepg = sepg;
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassificationResult.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassificationResult.java
new file mode 100644 (file)
index 0000000..5f38f90
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+
+import com.google.common.base.Preconditions;
+
+public class ClassificationResult {
+
+    private final String message;
+    private final boolean isSuccessful;
+    private final List<MatchBuilder> matchBuilders;
+
+    public ClassificationResult(String errorMessage) {
+        this.message = Preconditions.checkNotNull(errorMessage);
+        this.isSuccessful = false;
+        matchBuilders = null;
+    }
+
+    public ClassificationResult(List<MatchBuilder> matches) {
+        message = "";
+        this.matchBuilders = Preconditions.checkNotNull(matches);
+        this.isSuccessful = true;
+    }
+
+    public List<MatchBuilder> getMatchBuilders() {
+        if (isSuccessful == false) {
+            throw new IllegalStateException("Classification was not successfull.");
+        }
+        return matchBuilders;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public boolean isSuccessfull() {
+        return isSuccessful;
+    }
+}
\ No newline at end of file
index a8d4d0d4623bfcc58214179baa1ba9c199bff2e6..bf59d95fdeeff3438405abb0fa3ba7988a7a39d8 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * 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
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
 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;
 
 /**
  * Represent a classifier definition, and provide tools for generating flow
  * rules based on the classifier
- * @author readams
  */
 public abstract class Classifier {
+
+    protected final Classifier parent;
+
+    public static final EtherTypeClassifier ETHER_TYPE_CL = new EtherTypeClassifier(null);
+    public static final IpProtoClassifier IP_PROTO_CL = new IpProtoClassifier(ETHER_TYPE_CL);
+    public static final L4Classifier L4_CL = new L4Classifier(IP_PROTO_CL);
+
+    protected Classifier(Classifier parent) {
+        this.parent = parent;
+    }
+
     /**
-     * Get the classifier definition for this classifier
-     * @return the {@link ClassifierDefinition} for this classifier
+     * Get the classifier definition id for this classifier
+     *
+     * @return the {@link ClassifierDefinitionId} for this classifier
      */
     public abstract ClassifierDefinitionId getId();
 
     /**
      * Get the classifier definition for this classifier
+     *
      * @return the {@link ClassifierDefinition} for this classifier
      */
     public abstract ClassifierDefinition getClassDef();
-    
+
+    /**
+     * @return parent classifier
+     * @see {@link ClassifierDefinition}
+     */
+    public final Classifier getParent() {
+        return parent;
+    }
+
+    /**
+     * Template method for resolving {@code matches}.
+     *
+     * @param matches list of builders containing {@code matches} to update
+     * @param params parameters of classifier-instance inserted by user
+     * @return result, which indicates if all the matching fields were updated successfully and
+     *         contain updated {@code matches}
+     * @see {@link ClassificationResult}
+     */
+    public final ClassificationResult updateMatch(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
+        if (params == null) {
+            return new ClassificationResult("Classifier: {" + this.getClassDef().getName() + "} No parameters present.");
+        }
+        List<MatchBuilder> matchBuilders = matches;
+        try {
+            checkPresenceOfRequiredParams(params);
+            matchBuilders = this.update(matchBuilders, params);
+            Classifier parent = this.getParent();
+            List<Classifier> updatedClassifiers = new ArrayList<>();
+            updatedClassifiers.add(this);
+            while (parent != null) {
+                boolean hasReqParams = true;
+                try {
+                    parent.checkPresenceOfRequiredParams(params);
+                } catch (IllegalArgumentException e) {
+                    hasReqParams = false;
+                }
+                if (hasReqParams == true) {
+                    matchBuilders = parent.update(matchBuilders, params);
+                    updatedClassifiers.add(parent);
+                }
+                parent = parent.getParent();
+            }
+            for (Classifier updatedClassifier : updatedClassifiers) {
+                updatedClassifier.checkPrereqs(matchBuilders);
+            }
+        } catch (IllegalArgumentException e) {
+            if (!Strings.isNullOrEmpty(e.getMessage())) {
+                return new ClassificationResult(e.getMessage());
+            } else
+                return new ClassificationResult("Error while processing data of " + this.getClassDef().getName()
+                        + " classifier. Classification was not successful.");
+        }
+        return new ClassificationResult(matchBuilders);
+    }
+
+/**
+     * Checks presence of required {@code params} in order to decide if classifier can update {@code matches} properly
+     * in  method {@link #update(List, Map)
+     * @param  params  inserted parameters, not null
+     * @return  true, if required parameters are present
+     * @throws  IllegalArgumentException when any of required {@code params} is not present
+     * @see  {@link #updateMatch(List, Map)}
+     */
+    protected abstract void checkPresenceOfRequiredParams(Map<String, ParameterValue> params);
+
+    /**
+     * Resolves {@code matches} from inserted {@code params} and updates them.
+     * <p>
+     * Updates fields in {@code matches} or it can creates new matches. If it creates new matches it
+     * has to always use match from {@code matches} as parameter in constructor
+     * {@code MatchBuilder(Match base)}
+     *
+     * @param matches - fields to update
+     * @param params - input parameters
+     * @return updated {@code matches}. It is allowed to return new object.
+     * @throws IllegalArgumentException when update fails because of bad input
+     *         (e.g. overriding existing matches with different values is not permitted)
+     */
+    protected abstract List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params);
+
     /**
-     * Construct a set of matches that will apply to the traffic.  Augment
-     * the existing list of matches or add new matches.  It's important
-     * that the order of the returned list be consistent however
-     * @param matches The existing matches
-     * @param params the parameters for the classifier instance
-     * @return the updated list of matches (may be a different length)
+     * Checks whether prerequisites (required {@code matches}) for the match that this classifier
+     * updates are present
+     * according to Openflow specifications.
+     *
+     * @param matches input list of matches to check
+     * @throws IllegalArgumentException when any of prerequisites is not present
      */
-    public abstract List<MatchBuilder> updateMatch(List<MatchBuilder> matches,
-                                                   Map<String, Object> params);
+    protected abstract void checkPrereqs(List<MatchBuilder> matches);
 }
index e752ed60de371c13b3193d10f2651773804ae0f3..70ba21e7aadd2b77c62dea54fdaf014375a27f80 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * 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
@@ -21,7 +21,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 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.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.policy.rev140421.subject.feature.instance.ParameterValue;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
 
@@ -31,21 +33,23 @@ import com.google.common.collect.ImmutableList;
  * Match on the ether type of the traffic
  */
 public class EtherTypeClassifier extends Classifier {
-    public static final ClassifierDefinitionId ID = 
-            new ClassifierDefinitionId("6a48ab45-a462-429d-b18c-3a575b2c8bef");
-    protected static final String TYPE = "type";
-    protected static final ClassifierDefinition DEF = 
-            new ClassifierDefinitionBuilder()
-                .setId(ID)
-                .setName(new ClassifierName("ether_type"))
-                .setDescription(new Description("Match on the ether type of the traffic"))
-                .setParameter(ImmutableList.of(new ParameterBuilder()
-                    .setName(new ParameterName(TYPE))
+
+    public static final ClassifierDefinitionId ID = new ClassifierDefinitionId("6a48ab45-a462-429d-b18c-3a575b2c8bef");
+    public static final String ETHER_TYPE = "ethertype";
+    protected static final ClassifierDefinition DEF = new ClassifierDefinitionBuilder().setId(ID)
+        .setName(new ClassifierName("ether_type"))
+        .setDescription(new Description("Match on the ether type of the traffic"))
+        .setParameter(
+                ImmutableList.of(new ParameterBuilder().setName(new ParameterName(ETHER_TYPE))
                     .setDescription(new Description("The ethertype to match against"))
                     .setIsRequired(IsRequired.Required)
                     .setType(Type.Int)
                     .build()))
-                .build();
+        .build();
+
+    protected EtherTypeClassifier(Classifier parent) {
+        super(parent);
+    }
 
     @Override
     public ClassifierDefinitionId getId() {
@@ -58,23 +62,46 @@ public class EtherTypeClassifier extends Classifier {
     }
 
     @Override
-    public List<MatchBuilder> updateMatch(List<MatchBuilder> matches,
-                                          Map<String, Object> params) {
-        Object param = params.get(TYPE);
-        // XXX TODO generate exception and fail the match
-        if (param == null || !(param instanceof Long)) return matches;
-        Long type = (Long)param;
+    protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
+        if (params.get(ETHER_TYPE) == null) {
+            throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                    + "}+ Parameter ethertype not present.");
+        }
+        if (params.get(ETHER_TYPE).getIntValue() == null) {
+            throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                    + "}+ Value of ethertype parameter is not present.");
+        }
+    }
+
+    @Override
+    protected List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
+        Long type = params.get(ETHER_TYPE).getIntValue();
         for (MatchBuilder match : matches) {
             EthernetMatchBuilder em;
-            if (match.getEthernetMatch() != null)
-                em = new EthernetMatchBuilder(match.getEthernetMatch());
-            else
+            if (match.getEthernetMatch() != null) {
+                equalOrNotSetValidation(match.getEthernetMatch().getEthernetType(), type);
+                continue;
+            } else {
                 em = new EthernetMatchBuilder();
-            em.setEthernetType(new EthernetTypeBuilder()
-                .setType(new EtherType(type)).build());
+            }
+            em.setEthernetType(new EthernetTypeBuilder().setType(new EtherType(type)).build());
             match.setEthernetMatch(em.build());
         }
         return matches;
     }
 
+    private void equalOrNotSetValidation(EthernetType ethTypeInMatch, long paramValue) {
+        if (ethTypeInMatch != null) {
+            if (paramValue != ethTypeInMatch.getType().getValue().longValue()) {
+                throw new IllegalArgumentException("Classification conflict at " + this.getClassDef().getName()
+                        + ": Trying to override ether-type value: " + ethTypeInMatch.getType().getValue()
+                        + " by value " + paramValue);
+            }
+        }
+    }
+
+    @Override
+    protected void checkPrereqs(List<MatchBuilder> matches) {
+        // So far EthType has no prereqs.
+    }
 }
index e02f8d0c9613c31ec060705931d0daa18adb69b4..d884cec61db5c99c635fecbdb930a58624f7412d 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * 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
@@ -8,8 +8,6 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -24,36 +22,36 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 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.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.policy.rev140421.subject.feature.instance.ParameterValue;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 
 /**
  * Match on the IP protocol of IP traffic
  */
-public class IpProtoClassifier extends EtherTypeClassifier {
-    public static final ClassifierDefinitionId ID = 
-            new ClassifierDefinitionId("79c6fdb2-1e1a-4832-af57-c65baf5c2335");
-    protected static final String PROTO = "proto";
-    protected static final ClassifierDefinition DEF = 
-            new ClassifierDefinitionBuilder()
-                .setId(ID)
-                .setParent(EtherTypeClassifier.ID)
-                .setName(new ClassifierName("ip_proto"))
-                .setDescription(new Description("Match on the IP protocol of IP traffic"))
-                .setParameter(ImmutableList.of(new ParameterBuilder()
-                    .setName(new ParameterName(PROTO))
+public class IpProtoClassifier extends Classifier {
+
+    public static final Long TCP = Long.valueOf(6);
+    public static final Long UDP = Long.valueOf(17);
+    public static final Long SCTP = Long.valueOf(132);
+    public static final String PROTO = "proto";
+    public static final ClassifierDefinitionId ID = new ClassifierDefinitionId("79c6fdb2-1e1a-4832-af57-c65baf5c2335");
+    protected static final ClassifierDefinition DEF = new ClassifierDefinitionBuilder().setId(ID)
+        .setParent(EtherTypeClassifier.ID)
+        .setName(new ClassifierName("ip_proto"))
+        .setDescription(new Description("Match on the IP protocol of IP traffic"))
+        .setParameter(
+                ImmutableList.of(new ParameterBuilder().setName(new ParameterName(PROTO))
                     .setDescription(new Description("The IP protocol to match against"))
                     .setIsRequired(IsRequired.Required)
                     .setType(Type.Int)
                     .build()))
-                .build();
+        .build();
 
-    private static final Map<String, Object> ipv4 = 
-        ImmutableMap.<String,Object>of(TYPE, FlowUtils.IPv4);
-    private static final Map<String, Object> ipv6 = 
-            ImmutableMap.<String,Object>of(TYPE, FlowUtils.IPv6);
+    protected IpProtoClassifier(Classifier parent) {
+        super(parent);
+    }
 
     @Override
     public ClassifierDefinitionId getId() {
@@ -66,36 +64,73 @@ public class IpProtoClassifier extends EtherTypeClassifier {
     }
 
     @Override
-    public List<MatchBuilder> updateMatch(List<MatchBuilder> matches,
-                                          Map<String, Object> params) {
-        Object param = params.get(PROTO);
-        // XXX TODO generate exception and fail the match
-        if (param == null || !(param instanceof Long)) return matches;
-        Long proto = (Long)param;
-        
-        ArrayList<MatchBuilder> r = new ArrayList<>();
-        for (MatchBuilder b : matches) {
-            r.addAll(updateMatch(new MatchBuilder(b.build()), proto, ipv4));
-            r.addAll(updateMatch(new MatchBuilder(b.build()), proto, ipv6));
+    protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
+        if (params.get(PROTO) == null) {
+            throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                    + "}+ Parameter proto not present.");
+        }
+        if (params.get(PROTO).getIntValue() == null) {
+            throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                    + "}+ Value of proto parameter is not present.");
         }
-        return r;
     }
 
-    private List<MatchBuilder> updateMatch(MatchBuilder match,
-                                           Long proto,
-                                           Map<String, Object> parentParams) {
-        List<MatchBuilder> r = 
-                super.updateMatch(Collections.singletonList(match), 
-                                  parentParams);
-        for (MatchBuilder mb : r) {
+    @Override
+    protected List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
+        Long proto = params.get(PROTO).getIntValue();
+        for (MatchBuilder match : matches) {
             IpMatchBuilder imb;
-            if (mb.getIpMatch() != null)
-                imb = new IpMatchBuilder(mb.getIpMatch());
-            else 
+            if (match.getIpMatch() != null) {
+                equalOrNotSetValidation(match.getIpMatch().getIpProtocol(), proto);
+                continue;
+            } else {
                 imb = new IpMatchBuilder();
+            }
             imb.setIpProtocol(proto.shortValue());
-            mb.setIpMatch(imb.build());
+            match.setIpMatch(imb.build());
+        }
+        return matches;
+    }
+
+    private void equalOrNotSetValidation(Short protoInMatch, long paramValue) {
+        if (protoInMatch != null) {
+            if (paramValue != protoInMatch.longValue()) {
+                throw new IllegalArgumentException("Classification conflict at " + this.getClassDef().getName()
+                        + ": Trying to override proto value: " + protoInMatch.shortValue() + " by value " + paramValue);
+            }
+        }
+    }
+
+    @Override
+    protected void checkPrereqs(List<MatchBuilder> matches) {
+        for (MatchBuilder match : matches) {
+            Long readEthType = null;
+            try {
+                readEthType = match.getEthernetMatch().getEthernetType().getType().getValue();
+            } catch (NullPointerException e) {
+                throw new IllegalArgumentException("Ether-type match is missing.");
+            }
+            if (!FlowUtils.IPv4.equals(readEthType) && !FlowUtils.IPv6.equals(readEthType)) {
+                throw new IllegalArgumentException("Ether-type value should be " + FlowUtils.IPv4 + " or "
+                        + FlowUtils.IPv6 + ".");
+            }
+        }
+    }
+
+    /**
+     * May return null.
+     */
+    public static Long getIpProtoValue(Map<String, ParameterValue> params) {
+        if (params == null) {
+            return null;
+        }
+        if (params.get(PROTO) == null) {
+            return null;
+        }
+        Long proto = params.get(PROTO).getIntValue();
+        if (proto != null) {
+            return proto;
         }
-        return r;
+        return null;
     }
 }
index 4f32e54dbc20520291a83c3a3d4ffdbf8dad6edb..ce15981b620d1a0872311b314540760b71925be6 100755 (executable)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * 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
@@ -9,6 +9,7 @@
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
 
 
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -16,79 +17,66 @@ import java.util.Map;
 import java.util.Set;
 
 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.Match;
 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.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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
+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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 
 /**
  * Match against TCP or UDP, and source and/or destination ports
  */
-public class L4Classifier extends IpProtoClassifier {
-    private static final Logger LOG = LoggerFactory.getLogger(L4Classifier.class);
-    public static final ClassifierDefinitionId ID = 
-            new ClassifierDefinitionId("4250ab32-e8b8-445a-aebb-e1bd2cdd291f");
-    private static final String SPORT = "sourceport";
-    private static final String SPORT_RANGE = "sourceport_range";
-    private static final String DPORT = "destport";
-    private static final String DPORT_RANGE = "destport_range";
-    private static final ClassifierDefinition DEF =
-            new ClassifierDefinitionBuilder()
-                .setId(new ClassifierDefinitionId("4250ab32-e8b8-445a-aebb-e1bd2cdd291f"))
-                .setParent(IpProtoClassifier.ID)
-                .setName(new ClassifierName("l4"))
-                .setDescription(new Description("Match on the port number of UDP or TCP traffic"))
-                .setParameter(ImmutableList.of(new ParameterBuilder()
-                                .setName(new ParameterName(SPORT))
-                                .setDescription(new Description("The source port number to match against"))
-                                .setType(Type.Int)
-                                .build(),
-                        new ParameterBuilder()
-                                .setName(new ParameterName(SPORT_RANGE))
-                                .setDescription(new Description("The source port range to match against"))
-                                .setType(Type.Range)
-                                .build(),
-                        new ParameterBuilder()
-                                .setName(new ParameterName(DPORT))
-                                .setDescription(new Description("The destination port number to match against"))
-                                .setType(Type.Int)
-                                .build(),
-                        new ParameterBuilder()
-                                .setName(new ParameterName(DPORT_RANGE))
-                                .setDescription(new Description("The destination port range to match against"))
-                                .setType(Type.Range)
-                                .build(),
-                        new ParameterBuilder()
-                                .setName(new ParameterName(TYPE))
-                                .setDescription(new Description("TCP or UDP"))
-                                .setIsRequired(IsRequired.Required)
-                                .setType(Type.String)
-                                .build()))
-                .build();
-    
-    private static final Map<String, Object> tcp = 
-            ImmutableMap.<String,Object>of(PROTO, Long.valueOf(6));
-    private static final Map<String, Object> udp = 
-            ImmutableMap.<String,Object>of(PROTO, Long.valueOf(17));
-    
+public class L4Classifier extends Classifier {
+
+    public static final String SPORT = "sourceport";
+    public static final String SPORT_RANGE = "sourceport_range";
+    public static final String DPORT = "destport";
+    public static final String DPORT_RANGE = "destport_range";
+    public static final ClassifierDefinitionId ID = new ClassifierDefinitionId("4250ab32-e8b8-445a-aebb-e1bd2cdd291f");
+    private static final ClassifierDefinition DEF = new ClassifierDefinitionBuilder().setId(
+            new ClassifierDefinitionId("4250ab32-e8b8-445a-aebb-e1bd2cdd291f"))
+        .setParent(IpProtoClassifier.ID)
+        .setName(new ClassifierName("l4"))
+        .setDescription(new Description("Match on the port number of UDP or TCP traffic"))
+        .setParameter(
+                ImmutableList.of(
+                        new ParameterBuilder().setName(new ParameterName(SPORT))
+                            .setDescription(new Description("The source port number to match against"))
+                            .setType(Type.Int)
+                            .build(),
+                        new ParameterBuilder().setName(new ParameterName(SPORT_RANGE))
+                            .setDescription(new Description("The source port range to match against"))
+                            .setType(Type.Range)
+                            .build(),
+                        new ParameterBuilder().setName(new ParameterName(DPORT))
+                            .setDescription(new Description("The destination port number to match against"))
+                            .setType(Type.Int)
+                            .build(),
+                        new ParameterBuilder().setName(new ParameterName(DPORT_RANGE))
+                            .setDescription(new Description("The destination port range to match against"))
+                            .setType(Type.Range)
+                            .build()))
+        .build();
+
+    protected L4Classifier(Classifier parent) {
+        super(parent);
+    }
+
     @Override
     public ClassifierDefinitionId getId() {
         return ID;
@@ -100,108 +88,223 @@ public class L4Classifier extends IpProtoClassifier {
     }
 
     @Override
-    public List<MatchBuilder> updateMatch(List<MatchBuilder> matches,
-                                          Map<String, Object> params) {
-        Object param = params.get(TYPE);
-        // XXX TODO generate exception and fail the match
-        if (param == null || !(param instanceof String)) return matches;
-        String type = (String) param;
-
-        if ("UDP".equals(type))
-            matches = super.updateMatch(matches, udp);
-        else
-            matches = super.updateMatch(matches, tcp);
+    protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
+        if (params.get(SPORT) != null && params.get(SPORT_RANGE) != null) {
+            throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                    + "}+. Illegal source port parameters: 'int' and 'range' values are mutually exclusive.");
+        }
+        if (params.get(DPORT) != null && params.get(DPORT_RANGE) != null) {
+            throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                    + "}+. Illegal destination port parameters: 'int' and 'range' values are mutually exclusive.");
+        }
+        if (params.get(SPORT) != null) {
+            if (params.get(SPORT).getIntValue() == null) {
+                throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                        + "}+ Value of sourceport parameter is not present.");
+            }
+        }
+        if (params.get(SPORT_RANGE) != null) {
+            if (params.get(SPORT_RANGE) != null) {
+                validateRangeValue(params.get(SPORT_RANGE).getRangeValue());
+            }
+        }
+
+        if (params.get(DPORT) != null) {
+            if (params.get(DPORT).getIntValue() == null) {
+                throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                        + "}+ Value of destport parameter is not present.");
+            }
+        }
+        if (params.get(DPORT_RANGE) != null) {
+            if (params.get(DPORT_RANGE) != null) {
+                validateRangeValue(params.get(DPORT_RANGE).getRangeValue());
+            }
+        }
+    }
+
+    private void validateRangeValue(RangeValue rangeValueParam) {
+        if (rangeValueParam == null) {
+            throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
+                    + "}+ Range value is not present.");
+        }
+        final Long min = rangeValueParam.getMin();
+        final Long max = rangeValueParam.getMax();
+        if (min > max) {
+            throw new IllegalArgumentException("Range value mismatch. MIN {" + min + "} is greater than MAX {" + max
+                    + "}.");
+        }
+    }
 
+    @Override
+    public List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
         Set<Long> sPorts = new HashSet<>();
         Set<Long> dPorts = new HashSet<>();
-        // int-value and range parameters
-        param = params.get(SPORT);
-        if (param != null && (param instanceof Long))
-            sPorts.add((long) param);
-        param = params.get(DPORT);
-        if (param != null && (param instanceof Long))
-            dPorts.add((long) param);
-        param = params.get(SPORT_RANGE);
-        if (param != null && param instanceof RangeValue) {
-            sPorts.addAll(createSetFromRange((RangeValue) param));
-        }
-        param = params.get(DPORT_RANGE);
-        if (param != null && param instanceof RangeValue) {
-            dPorts.addAll(createSetFromRange((RangeValue) param));
-        }
-
-        Set<? extends Layer4Match> l4Matches = null;
-        if ("UDP".equals(type)) {
-            l4Matches = createUdpMatches(sPorts, dPorts);
-        } else {
-            l4Matches = createTcpMatches(sPorts, dPorts);
+        if (params.get(SPORT) != null) {
+            sPorts.add(params.get(SPORT).getIntValue());
+        } else if (params.get(SPORT_RANGE) != null) {
+            sPorts.addAll(createSetFromRange(params.get(SPORT_RANGE).getRangeValue()));
+        }
+        if (params.get(DPORT) != null) {
+            dPorts.add(params.get(DPORT).getIntValue());
+        } else if (params.get(DPORT_RANGE) != null) {
+            dPorts.addAll(createSetFromRange(params.get(DPORT_RANGE).getRangeValue()));
         }
+
         List<MatchBuilder> newMatches = new ArrayList<>();
         for (MatchBuilder matchBuilder : matches) {
-            Match baseMatch = matchBuilder.build();
-            for (Layer4Match l4Match : l4Matches) {
-                newMatches.add(new MatchBuilder(baseMatch).setLayer4Match(l4Match));
+            Layer4Match l4Match = matchBuilder.getLayer4Match();
+            Set<? extends Layer4Match> l4Matches = null;
+            if (l4Match == null) {
+                l4Match = resolveL4Match(params);
+            }
+            if (l4Match instanceof UdpMatch) {
+                l4Matches = createUdpMatches((UdpMatch) l4Match, sPorts, dPorts);
+            } else if (l4Match instanceof TcpMatch) {
+                l4Matches = createTcpMatches((TcpMatch) l4Match, sPorts, dPorts);
+            } else if (l4Match instanceof SctpMatch) {
+                l4Matches = createSctpMatches((SctpMatch) l4Match, sPorts, dPorts);
+            }
+            for (Layer4Match newL4Match : l4Matches) {
+                newMatches.add(new MatchBuilder(matchBuilder.build()).setLayer4Match(newL4Match));
             }
         }
         return newMatches;
     }
 
-    private Set<Long> createSetFromRange(RangeValue rangeValueParam){
+    private Layer4Match resolveL4Match(Map<String, ParameterValue> params) {
+        Long ipProto = IpProtoClassifier.getIpProtoValue(params);
+        if (ipProto == null) {
+            throw new IllegalArgumentException("Classifier-instance " + this.getClassDef().getName()
+                    + ": L4 protocol is null.");
+        }
+        if (IpProtoClassifier.UDP.equals(ipProto)) {
+            return new UdpMatchBuilder().build();
+        } else if (IpProtoClassifier.TCP.equals(ipProto)) {
+            return new TcpMatchBuilder().build();
+        } else if (IpProtoClassifier.SCTP.equals(ipProto)) {
+            return new SctpMatchBuilder().build();
+        }
+        throw new IllegalArgumentException("Unsupported L4 protocol.");
+    }
+
+    private Set<Long> createSetFromRange(RangeValue rangeValueParam) {
         Set<Long> res = new HashSet<>();
         if (rangeValueParam != null) {
             final Long min = rangeValueParam.getMin();
             final Long max = rangeValueParam.getMax();
-            if (min <= max) {
-                for (long val = min; val <= max; val++) {
-                    res.add(val);
-                }
-            } else {
-                LOG.warn("Range value mismatch. MIN {} is greater than MAX {}.", min, max);
+            for (long val = min; val <= max; val++) {
+                res.add(val);
             }
         }
         return res;
     }
 
-    private Set<UdpMatch> createUdpMatches(Set<Long> sPorts, Set<Long> dPorts) {
+    private Set<UdpMatch> createUdpMatches(UdpMatch udpMatch, Set<Long> sPorts, Set<Long> dPorts) {
         Set<UdpMatch> udpMatches = new HashSet<>();
         if (!sPorts.isEmpty() && dPorts.isEmpty()) {
             for (Long srcPort : sPorts) {
-                udpMatches.add(new UdpMatchBuilder().setUdpSourcePort(new PortNumber(srcPort.intValue())).build());
+                equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
+                udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue())).build());
             }
         } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
             for (Long dstPort : dPorts) {
-                udpMatches.add(new UdpMatchBuilder().setUdpDestinationPort(new PortNumber(dstPort.intValue())).build());
+                equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
+                udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpDestinationPort(new PortNumber(dstPort.intValue()))
+                    .build());
             }
         } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
             for (Long srcPort : sPorts) {
                 for (Long dstPort : dPorts) {
-                    udpMatches.add(new UdpMatchBuilder().setUdpSourcePort(new PortNumber(srcPort.intValue()))
-                            .setUdpDestinationPort(new PortNumber(dstPort.intValue())).build());
+                    equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
+                    equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
+                    udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue()))
+                        .setUdpDestinationPort(new PortNumber(dstPort.intValue()))
+                        .build());
                 }
             }
         }
         return udpMatches;
     }
 
-    private Set<TcpMatch> createTcpMatches(Set<Long> sPorts, Set<Long> dPorts) {
+    private Set<TcpMatch> createTcpMatches(TcpMatch tcpMatch, Set<Long> sPorts, Set<Long> dPorts) {
         Set<TcpMatch> tcpMatches = new HashSet<>();
         if (!sPorts.isEmpty() && dPorts.isEmpty()) {
             for (Long srcPort : sPorts) {
-                tcpMatches.add(new TcpMatchBuilder().setTcpSourcePort(new PortNumber(srcPort.intValue())).build());
+                equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
+                tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue())).build());
             }
         } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
             for (Long dstPort : dPorts) {
-                tcpMatches
-                        .add(new TcpMatchBuilder().setTcpDestinationPort(new PortNumber(dstPort.intValue())).build());
+                equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
+                tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpDestinationPort(new PortNumber(dstPort.intValue()))
+                    .build());
             }
         } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
             for (Long srcPort : sPorts) {
                 for (Long dstPort : dPorts) {
-                    tcpMatches.add(new TcpMatchBuilder().setTcpSourcePort(new PortNumber(srcPort.intValue()))
-                            .setTcpDestinationPort(new PortNumber(dstPort.intValue())).build());
+                    equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
+                    equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
+                    tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue()))
+                        .setTcpDestinationPort(new PortNumber(dstPort.intValue()))
+                        .build());
                 }
             }
         }
         return tcpMatches;
     }
+
+    private Set<SctpMatch> createSctpMatches(SctpMatch sctpMatch, Set<Long> sPorts, Set<Long> dPorts) {
+        Set<SctpMatch> sctpMatches = new HashSet<>();
+        if (!sPorts.isEmpty() && dPorts.isEmpty()) {
+            for (Long srcPort : sPorts) {
+                equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
+                sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
+                    .build());
+            }
+        } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
+            for (Long dstPort : dPorts) {
+                equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
+                sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpDestinationPort(new PortNumber(dstPort.intValue()))
+                    .build());
+            }
+        } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
+            for (Long srcPort : sPorts) {
+                for (Long dstPort : dPorts) {
+                    equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
+                    equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
+                    sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
+                        .setSctpDestinationPort(new PortNumber(dstPort.intValue()))
+                        .build());
+                }
+            }
+        }
+        return sctpMatches;
+    }
+
+    private void equalOrNotSetValidation(PortNumber portInMatch, long paramValue) {
+        if (portInMatch != null) {
+            if (paramValue != portInMatch.getValue().longValue()) {
+                throw new IllegalArgumentException("Classification conflict at " + this.getClassDef().getName()
+                        + ": Trying to override port value: " + portInMatch.getValue().longValue() + " by value "
+                        + paramValue);
+            }
+        }
+    }
+
+    @Override
+    public void checkPrereqs(List<MatchBuilder> matches) {
+        for (MatchBuilder match : matches) {
+            Long proto = null;
+            try {
+                proto = Long.valueOf(match.getIpMatch().getIpProtocol().longValue());
+            } catch (NullPointerException e) {
+                throw new IllegalArgumentException("Ip proto match is missing.");
+            }
+            if (!IpProtoClassifier.TCP.equals(proto) && !IpProtoClassifier.UDP.equals(proto)
+                    && !IpProtoClassifier.SCTP.equals(proto)) {
+                throw new IllegalArgumentException("Unsupported proto value.\n" + "Classifier: "
+                        + this.getClass().getName() + ", proto set: " + proto);
+            }
+        }
+    }
 }
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ParamDerivator.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ParamDerivator.java
new file mode 100644 (file)
index 0000000..99b60df
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
+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.ParameterValueBuilder;
+
+public abstract class ParamDerivator {
+
+    /**
+     * It is possible to derive missing parameters.
+     * <p>
+     * Examle:
+     * <p>
+     * Ether-type parameter is missing. Derivation policy might instruct: ipv4 and ipv6 flows need
+     * to be created if ether-type parameter is not present. In this case two derivations of
+     * {@code params} should be returned. One with ipv4 ether-type, the other with ipv6.
+     *
+     * @param params parameters inserted by user
+     * @return list of {@code params} updated with derived values
+     */
+    public abstract List<Map<String, ParameterValue>> deriveParameter(Map<String, ParameterValue> params);
+
+    public static final ParamDerivator ETHER_TYPE_DERIVATOR = new ParamDerivator() {
+
+        @Override
+        public List<Map<String, ParameterValue>> deriveParameter(Map<String, ParameterValue> params) {
+
+            if (!params.containsKey(EtherTypeClassifier.ETHER_TYPE)) {
+                Map<String, ParameterValue> ipv4Params = new HashMap<>(params);
+                Map<String, ParameterValue> ipv6Params = new HashMap<>(params);
+                ipv4Params.put(EtherTypeClassifier.ETHER_TYPE, new ParameterValueBuilder().setIntValue(FlowUtils.IPv4)
+                    .build());
+                ipv6Params.put(EtherTypeClassifier.ETHER_TYPE, new ParameterValueBuilder().setIntValue(FlowUtils.IPv6)
+                    .build());
+                List<Map<String, ParameterValue>> derivedParams = new ArrayList<>();
+                derivedParams.add(ipv4Params);
+                derivedParams.add(ipv6Params);
+                return derivedParams;
+            }
+            return Collections.singletonList(params);
+        }
+    };
+}
index 7ad60df97c32180eb6e5df9d0d151bfeb461140d..3840f3f8f34e3d7017ff12a5a9dc0ea4669eb017 100644 (file)
@@ -12,13 +12,10 @@ import java.util.List;
 import java.util.Map;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
-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.Description;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinitionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
 
 import com.google.common.base.Function;
@@ -32,12 +29,12 @@ import com.google.common.collect.ImmutableMap;
 public class SubjectFeatures {
     private static final Map<ClassifierDefinitionId, Classifier> classifiers =
             ImmutableMap.<ClassifierDefinitionId, Classifier>
-                of(EtherTypeClassifier.ID, new EtherTypeClassifier(),
-                   IpProtoClassifier.ID, new IpProtoClassifier(),
-                   L4Classifier.ID, new L4Classifier());
+                of(EtherTypeClassifier.ID, Classifier.ETHER_TYPE_CL,
+                   IpProtoClassifier.ID, Classifier.IP_PROTO_CL,
+                   L4Classifier.ID, Classifier.L4_CL);
 
     private static final List<ClassifierDefinition> classifierDefs =
-            ImmutableList.copyOf(Collections2.transform(classifiers.values(), 
+            ImmutableList.copyOf(Collections2.transform(classifiers.values(),
                 new Function<Classifier, ClassifierDefinition>() {
                     @Override
                     public ClassifierDefinition apply(Classifier input) {
@@ -45,7 +42,7 @@ public class SubjectFeatures {
                     }
                 }
             ));
-    
+
     private static final Map<ActionDefinitionId, Action> actions =
             ImmutableMap.<ActionDefinitionId, Action>
                 of(AllowAction.ID, new AllowAction());
@@ -60,7 +57,6 @@ public class SubjectFeatures {
                 }
              ));
 
-
     public static final SubjectFeatureDefinitions OF_OVERLAY_FEATURES =
             new SubjectFeatureDefinitionsBuilder()
                 .setActionDefinition(actionDefs)
@@ -68,10 +64,10 @@ public class SubjectFeatures {
                 .build();
 
     /**
-     * Get the {@link Classifier} associated with the given 
+     * Get the {@link Classifier} associated with the given
      * {@link ClassifierDefinitionId}
      * @param id the {@link ClassifierDefinitionId} to look up
-     * @return the {@link Classifier} if one exists, or <code>null</code> 
+     * @return the {@link Classifier} if one exists, or <code>null</code>
      * otherwise
      */
     public static Classifier getClassifier(ClassifierDefinitionId id) {
@@ -88,5 +84,4 @@ public class SubjectFeatures {
     public static Action getAction(ActionDefinitionId id) {
         return actions.get(id);
     }
-                                           
 }
index e0a5b2d83ba48b555aeb02c04a095b2ea34a46b0..b17756d267d6c222c34c2325ce1613054c865ebb 100644 (file)
@@ -61,19 +61,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import com.google.common.collect.ImmutableList;
 
 public class OfTableTest {
-       OfContext ctx;
+    OfContext ctx;
 
     MockEndpointManager endpointManager;
     MockPolicyResolver policyResolver;
     MockPolicyManager policyManager;
     MockSwitchManager switchManager;
-    
+
     NodeId nodeId = new NodeId("openflow:1");
     NodeId remoteNodeId = new NodeId("openflow:2");
-    NodeConnectorId nodeConnectorId = 
+    NodeConnectorId nodeConnectorId =
             new NodeConnectorId(nodeId.getValue() + ":4");
 
-    NodeConnectorId tunnelId = 
+    NodeConnectorId tunnelId =
             new NodeConnectorId(nodeId.getValue() + ":42");
 
     L3ContextId l3c = new L3ContextId("2cf51ee4-e996-467e-a277-2d380334a91d");
@@ -86,19 +86,19 @@ public class OfTableTest {
     EndpointGroupId eg = new EndpointGroupId("36dec84a-08c7-497b-80b6-a0035af72a12");
     EndpointGroupId eg2 = new EndpointGroupId("632e5e11-7988-4eb5-8fe6-6c182d890276");
     ContractId cid = new ContractId("a5874893-bcd5-46de-96af-3c8d99bedf9f");
-    
+
     protected void initCtx() {
         endpointManager = new MockEndpointManager();
         policyResolver = new MockPolicyResolver();
         policyManager = new MockPolicyManager(policyResolver, endpointManager);
         switchManager = new MockSwitchManager();
-        
+
         ctx = new OfContext(null,
-                             null, 
-                             policyManager, 
-                             policyResolver, 
-                             switchManager, 
-                             endpointManager, 
+                             null,
+                             policyManager,
+                             policyResolver,
+                             switchManager,
+                             endpointManager,
                              null);
     }
 
@@ -163,8 +163,8 @@ public class OfTableTest {
                               .setIntValue(Long.valueOf(80))
                               .build(),
                           new ParameterValueBuilder()
-                             .setName(new ParameterName("type"))
-                             .setStringValue("TCP")
+                             .setName(new ParameterName("proto"))
+                             .setIntValue(Long.valueOf(6))
                              .build()))
                      .build()))
                 .setActionInstance(ImmutableList.of(new ActionInstanceBuilder()
@@ -181,7 +181,7 @@ public class OfTableTest {
                      .build()))
                 .build()));
     }
-    
+
     protected SubjectBuilder baseSubject(Direction direction) {
         return new SubjectBuilder()
             .setName(new SubjectName("s1"))
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassifierTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassifierTest.java
new file mode 100644 (file)
index 0000000..d9d461c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import static org.junit.Assert.*;
+
+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.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ClassifierTest {
+
+    List<MatchBuilder> matches;
+    Map<String, ParameterValue> params;
+
+    @Before
+    public void setUp() {
+        matches = new ArrayList<>(Collections.singletonList(new MatchBuilder()));
+        params = new HashMap<>();
+    }
+
+    @Test
+    public void updateMatchTest() {
+
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createIntValueParam(EtherTypeClassifier.ETHER_TYPE, FlowUtils.IPv4));
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.SPORT, 80));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        ClassificationResult result = Classifier.L4_CL.updateMatch(matches, params);
+        assertEquals(true, result.isSuccessfull());
+        assertEquals(3, result.getMatchBuilders().size());
+        Set<Long> dstPorts = new HashSet<>();
+        for (MatchBuilder match : result.getMatchBuilders()) {
+            assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(match.getEthernetMatch().getEthernetType()));
+            assertEquals(true, new TcpMatchBuilder((TcpMatch) match.getLayer4Match()).getTcpSourcePort()
+                .getValue()
+                .intValue() == 80);
+            dstPorts.add(Long.valueOf(new TcpMatchBuilder((TcpMatch) match.getLayer4Match()).getTcpDestinationPort()
+                .getValue()
+                .longValue()));
+        }
+        for (Long i = dstRangeStart; i <= dstRangeEnd; i++) {
+            assertEquals(true, dstPorts.contains((i)));
+        }
+    }
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassifierTestUtils.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ClassifierTestUtils.java
new file mode 100644 (file)
index 0000000..0b8f4a7
--- /dev/null
@@ -0,0 +1,97 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import java.util.Map;
+
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
+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.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValueBuilder;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
+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.SctpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ClassifierTestUtils {
+
+    static final EthernetType IPV4_ETH_TYPE = new EthernetTypeBuilder().setType(new EtherType(FlowUtils.IPv4)).build();
+    static final EthernetType IPV6_ETH_TYPE = new EthernetTypeBuilder().setType(new EtherType(FlowUtils.IPv6)).build();
+
+    static final Long TCP = Long.valueOf(6);
+    static final Long UDP = Long.valueOf(17);
+    static final Long SCTP = Long.valueOf(132);
+
+    static Map<String, ParameterValue> createRangeValueParam(String paramName, long min, long max) {
+        return ImmutableMap.<String, ParameterValue> of(paramName,
+                new ParameterValueBuilder()
+                        .setRangeValue(new RangeValueBuilder()
+                                .setMin(min)
+                                .setMax(max)
+                                .build())
+                        .build());
+    }
+
+    static Map<String, ParameterValue> createIntValueParam(String paramName, long value) {
+        return ImmutableMap.<String, ParameterValue> of(paramName,
+                new ParameterValueBuilder()
+                        .setIntValue(value)
+                        .build());
+    }
+
+    static final EthernetMatch createEthernetMatch(EthernetType ethType) {
+        return new EthernetMatchBuilder()
+                .setEthernetType(ethType)
+                .build();
+    }
+
+    static final IpMatch createIpMatch(short ipProtoValue) {
+        return new IpMatchBuilder()
+        .setIpProtocol(ipProtoValue)
+        .build();
+    }
+
+    static final Layer4Match createUdpDstPort(int portNumber) {
+        return new UdpMatchBuilder()
+                .setUdpDestinationPort(new PortNumber(portNumber))
+                .build();
+    }
+
+    static final Layer4Match createUdpSrcPort(int portNumber) {
+        return new UdpMatchBuilder()
+                .setUdpSourcePort(new PortNumber(portNumber))
+                .build();
+    }
+
+    final Layer4Match createTcpDstPort(int portNumber) {
+        return new TcpMatchBuilder()
+                .setTcpDestinationPort(new PortNumber(portNumber))
+                .build();
+    }
+
+    final Layer4Match createTcpSrcPort(int portNumber) {
+        return new TcpMatchBuilder()
+                .setTcpSourcePort(new PortNumber(portNumber))
+                .build();
+    }
+
+    final static Layer4Match createSctpDstPort(int portNumber) {
+        return new SctpMatchBuilder()
+                .setSctpDestinationPort(new PortNumber(portNumber))
+                .build();
+    }
+
+    final static Layer4Match createSctpSrcPort(int portNumber) {
+        return new SctpMatchBuilder()
+                .setSctpSourcePort(new PortNumber(portNumber))
+                .build();
+    }
+}
\ No newline at end of file
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/EtherTypeClassifierTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/EtherTypeClassifierTest.java
new file mode 100644 (file)
index 0000000..7ccc63b
--- /dev/null
@@ -0,0 +1,83 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+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.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
+
+import com.google.common.collect.ImmutableMap;
+
+public class EtherTypeClassifierTest {
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    List<MatchBuilder> matches;
+    Map<String, ParameterValue> params;
+
+    @Before
+    public void setUp() {
+        matches = new ArrayList<>();
+        params = new HashMap<>();
+    }
+
+    @Test
+    public void setValueTest() {
+        matches.add(new MatchBuilder()
+                .setIpMatch(ClassifierTestUtils.createIpMatch(ClassifierTestUtils.TCP.shortValue())));
+        params.putAll(ClassifierTestUtils.createIntValueParam(EtherTypeClassifier.ETHER_TYPE, FlowUtils.IPv4));
+        matches = Classifier.ETHER_TYPE_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        assertEquals(true, ClassifierTestUtils.TCP.equals(matches.get(0).getIpMatch().getIpProtocol().longValue()));
+    }
+
+    @Test
+    public void overrideByTheSameValueTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV6_ETH_TYPE))
+                .setIpMatch(ClassifierTestUtils.createIpMatch(ClassifierTestUtils.UDP.shortValue())));
+        params.putAll(ClassifierTestUtils.createIntValueParam(EtherTypeClassifier.ETHER_TYPE, FlowUtils.IPv6));
+        matches = Classifier.ETHER_TYPE_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV6_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        assertEquals(true, ClassifierTestUtils.UDP.equals(matches.get(0).getIpMatch().getIpProtocol().longValue()));
+    }
+
+    @Test
+    public void overrideByDifferentValueTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE))
+                .setIpMatch(ClassifierTestUtils.createIpMatch(ClassifierTestUtils.SCTP.shortValue())));
+        params.putAll(ClassifierTestUtils.createIntValueParam(EtherTypeClassifier.ETHER_TYPE, FlowUtils.IPv6));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Trying to override ether-type value:");
+        matches = Classifier.ETHER_TYPE_CL.update(matches, params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters1Test() {
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Parameter ethertype not present");
+        Classifier.ETHER_TYPE_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters2Test() {
+        params.putAll(ImmutableMap.<String, ParameterValue> of(EtherTypeClassifier.ETHER_TYPE,
+                new ParameterValueBuilder().build()));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Value of ethertype parameter is not present");
+        Classifier.ETHER_TYPE_CL.checkPresenceOfRequiredParams(params);
+    }
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/IpProtoClassifierTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/IpProtoClassifierTest.java
new file mode 100644 (file)
index 0000000..d106fd6
--- /dev/null
@@ -0,0 +1,83 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+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.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
+
+import com.google.common.collect.ImmutableMap;
+
+public class IpProtoClassifierTest {
+
+    List<MatchBuilder> matches;
+    Map<String, ParameterValue> params;
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        matches = new ArrayList<>();
+        params = new HashMap<>();
+    }
+
+    @Test
+    public void setValueTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE)));
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        matches = Classifier.IP_PROTO_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        assertEquals(true, ClassifierTestUtils.TCP.equals(matches.get(0).getIpMatch().getIpProtocol().longValue()));
+    }
+
+    @Test
+    public void overrideByTheSameValueTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV6_ETH_TYPE))
+                .setIpMatch(ClassifierTestUtils.createIpMatch(ClassifierTestUtils.UDP.shortValue())));
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.UDP));
+        matches = Classifier.IP_PROTO_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV6_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        assertEquals(true, ClassifierTestUtils.UDP.equals(matches.get(0).getIpMatch().getIpProtocol().longValue()));
+    }
+
+    @Test
+    public void overrideByDifferentValueTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE))
+                .setIpMatch(ClassifierTestUtils.createIpMatch(ClassifierTestUtils.SCTP.shortValue())));
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Trying to override proto value");
+        matches = Classifier.IP_PROTO_CL.update(matches, params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters1Test() {
+        params.putAll(ClassifierTestUtils.createIntValueParam(EtherTypeClassifier.ETHER_TYPE, FlowUtils.IPv4));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Parameter proto not present");
+        Classifier.IP_PROTO_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters2Test() {
+        params.putAll(ImmutableMap.<String, ParameterValue> of(IpProtoClassifier.PROTO,
+                new ParameterValueBuilder().build()));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Value of proto parameter is not present");
+        Classifier.IP_PROTO_CL.checkPresenceOfRequiredParams(params);
+    }
+}
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/L4ClassifierTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/L4ClassifierTest.java
new file mode 100644 (file)
index 0000000..08d52df
--- /dev/null
@@ -0,0 +1,344 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+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.ParameterValueBuilder;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
+
+import com.google.common.collect.ImmutableMap;
+
+public class L4ClassifierTest {
+
+    List<MatchBuilder> matches;
+    Map<String, ParameterValue> params;
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        params = new HashMap<>();
+        matches = new ArrayList<>();
+    }
+
+    @Test
+    public void setTcpSrcPortTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE)));
+        Long sPort = Long.valueOf(80);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.SPORT, sPort));
+        matches = Classifier.L4_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        TcpMatch match = new TcpMatchBuilder((TcpMatch) matches.get(0).getLayer4Match()).build();
+        assertEquals(true, sPort.equals(match.getTcpSourcePort().getValue().longValue()));
+        assertEquals(true, match.getTcpDestinationPort() == null);
+    }
+
+    @Test
+    public void setTcpDstPortTest() {
+        Long dPort = Long.valueOf(80);
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV6_ETH_TYPE)));
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.DPORT, dPort));
+        matches = Classifier.L4_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV6_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        TcpMatch match = new TcpMatchBuilder((TcpMatch) matches.get(0).getLayer4Match()).build();
+        assertEquals(true, dPort.equals(match.getTcpDestinationPort().getValue().longValue()));
+        assertEquals(true, match.getTcpSourcePort() == null);
+    }
+
+    @Test
+    public void setTcpSrcPortDstPortRangeTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE)));
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        Long srcPort = Long.valueOf(80);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.SPORT, srcPort));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+        matches = Classifier.L4_CL.update(matches, params);
+        Set<Long> dstPorts = new HashSet<>();
+        for (MatchBuilder match : matches) {
+            assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(match.getEthernetMatch().getEthernetType()));
+            assertEquals(true,
+                    Long.valueOf(new TcpMatchBuilder((TcpMatch) match.getLayer4Match()).getTcpSourcePort().getValue())
+                            .equals(srcPort));
+            dstPorts.add(new TcpMatchBuilder((TcpMatch) match.getLayer4Match()).getTcpDestinationPort().getValue()
+                    .longValue());
+        }
+        for (Long i = dstRangeStart; i <= dstRangeEnd; i++) {
+            assertEquals(true, dstPorts.contains((i)));
+        }
+    }
+
+    @Test
+    public void overrideDstPortWithTheSameValueTest() {
+        Long dPort = Long.valueOf(80);
+        matches.add(new MatchBuilder()
+                .setLayer4Match(ClassifierTestUtils.createUdpDstPort(80))
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV6_ETH_TYPE)));
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.UDP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.DPORT, dPort));
+        matches = Classifier.L4_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV6_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        UdpMatch match = new UdpMatchBuilder((UdpMatch) matches.get(0).getLayer4Match()).build();
+        assertEquals(true, dPort.equals(match.getUdpDestinationPort().getValue().longValue()));
+        assertEquals(true, match.getUdpSourcePort() == null);
+    }
+
+    @Test
+    public void addUdpSrcPortRangeTest() {
+        matches.add(new MatchBuilder()
+                .setLayer4Match(ClassifierTestUtils.createUdpDstPort(80))
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE)));
+        Long srcRangeStart = Long.valueOf(8079);
+        Long srcRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.UDP));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.SPORT_RANGE, srcRangeStart, srcRangeEnd));
+        matches = Classifier.L4_CL.update(matches, params);
+        Set<Long> srcPorts = new HashSet<>();
+        for (MatchBuilder match : matches) {
+            assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(match.getEthernetMatch().getEthernetType()));
+            assertEquals(true, new UdpMatchBuilder((UdpMatch) match.getLayer4Match()).getUdpDestinationPort()
+                    .getValue().intValue() == 80);
+            assertEquals(true, new UdpMatchBuilder((UdpMatch) match.getLayer4Match()).getUdpDestinationPort()
+                    .getValue()
+                    .longValue() == 80);
+            srcPorts.add(new UdpMatchBuilder((UdpMatch) match.getLayer4Match()).getUdpSourcePort().getValue()
+                    .longValue());
+        }
+        for (Long i = srcRangeStart; i <= srcRangeEnd; i++) {
+            assertEquals(true, srcPorts.contains((i)));
+        }
+    }
+
+    @Test
+    public void setUdpSrcPortRangeDstPortTest() {
+        matches.add(new MatchBuilder()
+                .setLayer4Match(ClassifierTestUtils.createUdpDstPort(80))
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV6_ETH_TYPE)));
+        Long dPort = Long.valueOf(80);
+        Long srcRangeStart = Long.valueOf(8079);
+        Long srcRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.UDP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.DPORT, dPort));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.SPORT_RANGE, srcRangeStart, srcRangeEnd));
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+        matches = Classifier.L4_CL.update(matches, params);
+        Set<Long> srcPorts = new HashSet<>();
+        for (MatchBuilder match : matches) {
+            assertEquals(true, ClassifierTestUtils.IPV6_ETH_TYPE.equals(match.getEthernetMatch().getEthernetType()));
+            assertEquals(
+                    true,
+                    dPort.equals(new UdpMatchBuilder((UdpMatch) match.getLayer4Match()).getUdpDestinationPort()
+                            .getValue().longValue()));
+            srcPorts.add(Long.valueOf(new UdpMatchBuilder((UdpMatch) match.getLayer4Match()).getUdpSourcePort()
+                    .getValue().longValue()));
+        }
+        for (Long i = srcRangeStart; i <= srcRangeEnd; i++) {
+            assertEquals(true, srcPorts.contains((i)));
+        }
+    }
+
+    @Test
+    public void overrideSrcPortWithTheSameValueTest() {
+        Long sPort = Long.valueOf(80);
+        matches.add(new MatchBuilder()
+                .setLayer4Match(ClassifierTestUtils.createSctpSrcPort(sPort.intValue()))
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE)));
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.SCTP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.SPORT, sPort));
+        matches = Classifier.L4_CL.update(matches, params);
+        assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(matches.get(0).getEthernetMatch().getEthernetType()));
+        SctpMatch match = new SctpMatchBuilder((SctpMatch) matches.get(0).getLayer4Match()).build();
+        assertEquals(true, sPort.equals(match.getSctpSourcePort().getValue().longValue()));
+        assertEquals(true, match.getSctpDestinationPort() == null);
+    }
+
+    @Test
+    public void addSctpDstPortRangeTest() {
+        matches.add(new MatchBuilder()
+                .setLayer4Match(ClassifierTestUtils.createSctpSrcPort(80))
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE)));
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.SCTP));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        matches = Classifier.L4_CL.update(matches, params);
+        Set<Long> dstPorts = new HashSet<>();
+        for (MatchBuilder match : matches) {
+            assertEquals(true, ClassifierTestUtils.IPV4_ETH_TYPE.equals(match.getEthernetMatch().getEthernetType()));
+            assertEquals(true, new SctpMatchBuilder((SctpMatch) match.getLayer4Match()).getSctpSourcePort().getValue()
+                    .intValue() == 80);
+            dstPorts.add(Long.valueOf(new SctpMatchBuilder((SctpMatch) match.getLayer4Match()).getSctpDestinationPort()
+                    .getValue().longValue()));
+        }
+        for (Long i = dstRangeStart; i <= dstRangeEnd; i++) {
+            assertEquals(true, dstPorts.contains((i)));
+        }
+    }
+
+    @Test
+    public void setSctpSrcPortRangeDstPortRangeTest() {
+        matches.add(new MatchBuilder()
+                .setEthernetMatch(ClassifierTestUtils.createEthernetMatch(ClassifierTestUtils.IPV4_ETH_TYPE)));
+        Long srcRangeStart = Long.valueOf(79);
+        Long srcRangeEnd = Long.valueOf(81);
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.SCTP));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.SPORT_RANGE, srcRangeStart, srcRangeEnd));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+        matches = Classifier.L4_CL.update(matches, params);
+        Set<Pair<Long, Long>> set = new HashSet<>();
+        for (MatchBuilder match : matches) {
+            Long srcPort = Long.valueOf(new SctpMatchBuilder((SctpMatch) match.getLayer4Match()).getSctpSourcePort()
+                    .getValue().longValue());
+            Long dstPort = Long.valueOf(new SctpMatchBuilder((SctpMatch) match.getLayer4Match())
+                    .getSctpDestinationPort().getValue().longValue());
+            set.add(Pair.of(srcPort, dstPort));
+        }
+        for (Long i = srcRangeStart; i <= srcRangeEnd; i++) {
+            for (Long j = dstRangeStart; j <= dstRangeEnd; j++) {
+                assertEquals(true, set.contains(Pair.of(i, j)));
+            }
+        }
+    }
+
+    @Test
+    public void srcPortSrtPortRangeMutualExclusionTest() {
+        matches.add(new MatchBuilder());
+        Long srcRangeStart = Long.valueOf(8079);
+        Long srcRangeEnd = Long.valueOf(8081);
+        Long srcPort = Long.valueOf(80);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.SCTP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.SPORT, srcPort));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.SPORT_RANGE, srcRangeStart, srcRangeEnd));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Illegal source port parameters");
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void dstPortSrtPortRangeMutualExclusionTest() {
+        matches.add(new MatchBuilder());
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        Long dstPort = Long.valueOf(80);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.UDP));
+        params.putAll(ClassifierTestUtils.createIntValueParam(L4Classifier.DPORT, dstPort));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Illegal destination port parameters");
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void rangeValueMismatchTest() {
+        matches.add(new MatchBuilder());
+        Long dstRangeStart = Long.valueOf(8081);
+        Long dstRangeEnd = Long.valueOf(8079);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.TCP));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Range value mismatch");
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void unsupportedProtocolTest() {
+        matches.add(new MatchBuilder());
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, 136));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Unsupported L4 protocol.");
+        matches = Classifier.L4_CL.update(matches, params);
+    }
+
+    @Test
+    public void classificationConflictTest() {
+        matches.add(new MatchBuilder()
+                .setLayer4Match(ClassifierTestUtils.createSctpDstPort(80)));
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createIntValueParam(IpProtoClassifier.PROTO, ClassifierTestUtils.UDP));
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Classification conflict");
+        matches = Classifier.L4_CL.update(matches, params);
+    }
+
+    @Test
+    public void noProtoTest() {
+        matches.add(new MatchBuilder());
+        Long dstRangeStart = Long.valueOf(8079);
+        Long dstRangeEnd = Long.valueOf(8081);
+        params.putAll(ClassifierTestUtils.createRangeValueParam(L4Classifier.DPORT_RANGE, dstRangeStart, dstRangeEnd));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("L4 protocol is null.");
+        matches = Classifier.L4_CL.update(matches, params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters1Test() {
+        params.putAll(ImmutableMap.<String, ParameterValue> of(L4Classifier.SPORT,
+                new ParameterValueBuilder().build()));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Value of sourceport parameter is not present");
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters2Test() {
+        params.putAll(ImmutableMap.<String, ParameterValue> of(L4Classifier.DPORT,
+                new ParameterValueBuilder().build()));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Value of destport parameter is not present");
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters3Test() {
+        params.putAll(ImmutableMap.<String, ParameterValue> of(L4Classifier.SPORT_RANGE,
+                new ParameterValueBuilder().build()));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Range value is not present");
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+    }
+
+    @Test
+    public void checkPresenceOfRequiredParameters4Test() {
+        params.putAll(ImmutableMap.<String, ParameterValue> of(L4Classifier.DPORT_RANGE,
+                new ParameterValueBuilder().build()));
+        thrown.expect(IllegalArgumentException.class);
+        thrown.expectMessage("Range value is not present");
+        Classifier.L4_CL.checkPresenceOfRequiredParams(params);
+    }
+
+}
index 31436a973fd66b0205bea23ecffdf5f41eb8e945..32c99aa9e3927896fd84d289cfa22deda3cda4ed 100644 (file)
@@ -10,16 +10,16 @@ tenants = [
                 {'name': 'http-dest',
                 'classifier-definition-id': '4250ab32-e8b8-445a-aebb-e1bd2cdd291f',
                 'parameter-value': [
-                    {'name': 'type',
-                     'string-value': 'TCP'},
+                    {'name': 'proto',
+                     'int-value': '6'},
                     {'name': 'destport',
                      'int-value': '80'}
                 ]},
                 {'name': 'http-src',
                 'classifier-definition-id': '4250ab32-e8b8-445a-aebb-e1bd2cdd291f',
                 'parameter-value': [
-                    {'name': 'type',
-                     'string-value': 'TCP'},
+                    {'name': 'proto',
+                     'int-value': '6'},
                     {'name': 'sourceport',
                      'int-value': '80'}
                 ]},