Implementing portrange in L4Classifier.
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / sf / L4Classifier.java
index da8b8f8934a7ef6599900b4133adc8b10e4db1db..4f32e54dbc20520291a83c3a3d4ffdbf8dad6edb 100755 (executable)
@@ -8,10 +8,15 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
 
+
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 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;
@@ -22,17 +27,23 @@ 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.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.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.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
- * @author readams
  */
 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";
@@ -91,42 +102,106 @@ public class L4Classifier extends IpProtoClassifier {
     @Override
     public List<MatchBuilder> updateMatch(List<MatchBuilder> matches,
                                           Map<String, Object> params) {
-        Object t = params.get(TYPE);
+        Object param = params.get(TYPE);
         // XXX TODO generate exception and fail the match
-        if (t == null || !(t instanceof String)) return matches;
-        String type = (String)t;
-        
+        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);            
+            matches = super.updateMatch(matches, tcp);
 
-        Long sport = null;
-        Long dport = null;
-        t = params.get(SPORT);
-        if (t != null && (t instanceof Long))
-            sport = (Long)t;
-        t = params.get(DPORT);
-        if (t != null && (t instanceof Long))
-            dport = (Long)t;
+        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));
+        }
 
-        for (MatchBuilder b : matches) {
-            if ("UDP".equals(type)) {
-                UdpMatchBuilder m = new UdpMatchBuilder();
-                if (sport != null)
-                    m.setUdpSourcePort(new PortNumber(sport.intValue()));
-                if (dport != null)
-                    m.setUdpDestinationPort(new PortNumber(dport.intValue()));
-                b.setLayer4Match(m.build());
+        Set<? extends Layer4Match> l4Matches = null;
+        if ("UDP".equals(type)) {
+            l4Matches = createUdpMatches(sPorts, dPorts);
+        } else {
+            l4Matches = createTcpMatches(sPorts, dPorts);
+        }
+        List<MatchBuilder> newMatches = new ArrayList<>();
+        for (MatchBuilder matchBuilder : matches) {
+            Match baseMatch = matchBuilder.build();
+            for (Layer4Match l4Match : l4Matches) {
+                newMatches.add(new MatchBuilder(baseMatch).setLayer4Match(l4Match));
+            }
+        }
+        return newMatches;
+    }
+
+    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 {
-                TcpMatchBuilder m = new TcpMatchBuilder();
-                if (sport != null)
-                    m.setTcpSourcePort(new PortNumber(sport.intValue()));
-                if (dport != null)
-                    m.setTcpDestinationPort(new PortNumber(dport.intValue()));
-                b.setLayer4Match(m.build());
+                LOG.warn("Range value mismatch. MIN {} is greater than MAX {}.", min, max);
+            }
+        }
+        return res;
+    }
+
+    private Set<UdpMatch> createUdpMatches(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());
+            }
+        } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
+            for (Long dstPort : dPorts) {
+                udpMatches.add(new UdpMatchBuilder().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());
+                }
+            }
+        }
+        return udpMatches;
+    }
+
+    private Set<TcpMatch> createTcpMatches(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());
+            }
+        } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
+            for (Long dstPort : dPorts) {
+                tcpMatches
+                        .add(new TcpMatchBuilder().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());
+                }
             }
         }
-        return matches;
+        return tcpMatches;
     }
 }