Implementation of IP address classifier. 64/16764/5
authorTomas Cechvala <tcechval@cisco.com>
Wed, 18 Mar 2015 12:54:02 +0000 (13:54 +0100)
committerKeith Burns (alagalah) <alagalah@gmail.com>
Mon, 23 Mar 2015 17:28:41 +0000 (10:28 -0700)
Functionality is blocked by bug 2866.

Change-Id: Iec272e5422c9f4002064c04446f2ec1cd99752e9
Signed-off-by: Tomas Cechvala <tcechval@cisco.com>
Signed-off-by: Keith Burns (alagalah) <alagalah@gmail.com>
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/IpAddressClassifier.java [new file with mode: 0644]
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/SubjectFeatures.java

diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/IpAddressClassifier.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/IpAddressClassifier.java
new file mode 100644 (file)
index 0000000..9bd8e91
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * 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.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+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.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+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.ParameterBuilder;
+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.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.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.net.InetAddresses;
+
+/**
+ * Match on the IP address of IP traffic
+ */
+public class IpAddressClassifier extends EtherTypeClassifier {
+    public static final ClassifierDefinitionId ID = new ClassifierDefinitionId("55b83ba4-a741-4d26-91ca-7cd197750a3f");
+
+    protected static final String SRC_ADDR = "src_addr";
+    protected static final String DST_ADDR = "dst_addr";
+    protected static final ClassifierDefinition DEF = new ClassifierDefinitionBuilder()
+            .setId(ID)
+            .setParent(EtherTypeClassifier.ID)
+            .setName(new ClassifierName("ip_address"))
+            .setDescription(new Description("Match on the IP address of IP traffic"))
+            .setParameter(
+                    ImmutableList.of(
+                            new ParameterBuilder()
+                                    .setName(new ParameterName(SRC_ADDR))
+                                    .setDescription(new Description("Source IP prefix to match against."))
+                                    .setIsRequired(IsRequired.Optional)
+                                    .setType(Type.String)
+                                    .build(),
+                            new ParameterBuilder()
+                                    .setName(new ParameterName(DST_ADDR))
+                                    .setDescription(new Description("Destination IP prefix to match against."))
+                                    .setIsRequired(IsRequired.Optional)
+                                    .setType(Type.String).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);
+
+    private enum IpAddressContext {
+        SRC, DST
+    }
+
+    @Override
+    public ClassifierDefinitionId getId() {
+        return ID;
+    }
+
+    @Override
+    public ClassifierDefinition getClassDef() {
+        return DEF;
+    }
+
+    @Override
+    public List<MatchBuilder> updateMatch(List<MatchBuilder> matches, Map<String, Object> params) {
+        Object t = params.get(SRC_ADDR);
+        String srcAddr = null;
+        if (t instanceof String) {
+            srcAddr = (String) t;
+        }
+        t = params.get(DST_ADDR);
+        String dstAddr = null;
+        if (t instanceof String) {
+            dstAddr = (String) t;
+        }
+        List<MatchBuilder> r = new ArrayList<>();
+        for (MatchBuilder b : matches) {
+            if (srcAddr != null && dstAddr != null) {
+                boolean isSrcIpv4Addr = isIpv4Address(srcAddr);
+                boolean isDstIpv4Addr = isIpv4Address(dstAddr);
+                if (isSrcIpv4Addr != isDstIpv4Addr) {
+                    throw new IllegalArgumentException("Ip address [" + srcAddr + "] is not the same version as ["
+                            + dstAddr + "].");
+                }
+                r.addAll(updateMatch(b, srcAddr, dstAddr, getIpVersion(isSrcIpv4Addr)));
+            } else if (srcAddr == null && dstAddr == null) {
+                r.addAll(super.updateMatch(Collections.singletonList(new MatchBuilder(b.build())), ipv4));
+                r.addAll(super.updateMatch(Collections.singletonList(new MatchBuilder(b.build())), ipv6));
+            } else {
+                if (srcAddr != null) {
+                    r.addAll(updateMatch(new MatchBuilder(b.build()), srcAddr, null,
+                            getIpVersion(isIpv4Address(srcAddr))));
+                } else {
+                    r.addAll(updateMatch(new MatchBuilder(b.build()), null, dstAddr,
+                            getIpVersion(isIpv4Address(dstAddr))));
+                }
+            }
+        }
+        return r;
+    }
+
+    private List<MatchBuilder> updateMatch(MatchBuilder matchBuilder, String srcAddr, String dstAddr,
+            Map<String, Object> params) {
+        List<MatchBuilder> r = super.updateMatch(Collections.singletonList(matchBuilder), params);
+        Long ipVersion = (Long) params.get(TYPE);
+        for (MatchBuilder mb : r) {
+            Layer3Match l3m = mb.getLayer3Match();
+            l3m = updateIpAddressField(ipVersion, srcAddr, IpAddressContext.SRC, l3m);
+            l3m = updateIpAddressField(ipVersion, dstAddr, IpAddressContext.DST, l3m);
+            mb.setLayer3Match(l3m);
+        }
+        return r;
+    }
+
+    private Map<String, Object> getIpVersion(boolean isIpv4) {
+        if (isIpv4 == true) {
+            return ipv4;
+        }
+        return ipv6;
+    }
+
+    private boolean isIpv4Address(String cidr) {
+        String[] ipAndPrefix = cidr.split("/");
+        if (ipAndPrefix.length != 2) {
+            throw new IllegalStateException(cidr + " does not match CIDR format.");
+        }
+        InetAddress ip = InetAddresses.forString(ipAndPrefix[0]);
+        if (ip instanceof Inet4Address) {
+            return true;
+        }
+        return false;
+    }
+
+    private Layer3Match updateIpAddressField(Long ipVersion, String ipAddr, IpAddressContext ctx, Layer3Match l3m) {
+        if (Strings.isNullOrEmpty(ipAddr)) {
+            return l3m;
+        }
+        if (ipVersion.equals(FlowUtils.IPv4)) {
+            l3m = updateIpv4AddressField(ipAddr, ctx, l3m);
+        } else if (ipVersion.equals(FlowUtils.IPv6)) {
+            l3m = updateIpv6AddressField(ipAddr, ctx, l3m);
+        }
+        return l3m;
+    }
+
+    private Layer3Match updateIpv4AddressField(String ipAddr, IpAddressContext ctx, Layer3Match l3match) {
+        Ipv4MatchBuilder ipv4mb;
+        if (l3match == null) {
+            ipv4mb = new Ipv4MatchBuilder();
+        } else {
+            ipv4mb = new Ipv4MatchBuilder((Ipv4Match) l3match);
+        }
+        if (ctx.equals(IpAddressContext.SRC)) {
+            return ipv4mb.setIpv4Source(new Ipv4Prefix(ipAddr)).build();
+        }
+        return ipv4mb.setIpv4Destination(new Ipv4Prefix(ipAddr)).build();
+    }
+
+    private Layer3Match updateIpv6AddressField(String ipAddr, IpAddressContext ctx, Layer3Match l3match) {
+        Ipv6MatchBuilder ipv6mb;
+        if (l3match == null) {
+            ipv6mb = new Ipv6MatchBuilder();
+        } else {
+            ipv6mb = new Ipv6MatchBuilder((Ipv6Match) l3match);
+        }
+        if (ctx.equals(IpAddressContext.SRC)) {
+            return ipv6mb.setIpv6Source(new Ipv6Prefix(ipAddr)).build();
+        }
+        return ipv6mb.setIpv6Destination(new Ipv6Prefix(ipAddr)).build();
+    }
+}
index e105bc76bf8f37fdbd94befa1b29d914c4f8fa43..cf175f594e6786d92b580e484a985b5af4768f3c 100644 (file)
@@ -32,7 +32,7 @@ import com.google.common.collect.ImmutableMap;
 /**
  * Match on the IP protocol of IP traffic
  */
-public class IpProtoClassifier extends EtherTypeClassifier {
+public class IpProtoClassifier extends IpAddressClassifier {
     public static final ClassifierDefinitionId ID = 
             new ClassifierDefinitionId("79c6fdb2-1e1a-4832-af57-c65baf5c2335");
     protected static final String PROTO = "proto";
@@ -50,11 +50,6 @@ public class IpProtoClassifier extends EtherTypeClassifier {
                     .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);
-
     @Override
     public ClassifierDefinitionId getId() {
         return ID;
@@ -75,8 +70,7 @@ public class IpProtoClassifier extends EtherTypeClassifier {
         
         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));
+            r.addAll(updateMatch(new MatchBuilder(b.build()), proto, params));
         }
         return r;
     }
index da8b8f8934a7ef6599900b4133adc8b10e4db1db..7b30239c4e6f1b8755b18c4d5553a8d0fcde0829 100755 (executable)
@@ -95,11 +95,13 @@ public class L4Classifier extends IpProtoClassifier {
         // XXX TODO generate exception and fail the match
         if (t == null || !(t instanceof String)) return matches;
         String type = (String)t;
-        
-        if ("UDP".equals(type))
-            matches = super.updateMatch(matches, udp);
-        else
-            matches = super.updateMatch(matches, tcp);            
+
+        if ("UDP".equals(type)){
+            params.putAll(udp);
+        } else {
+            params.putAll(tcp);
+        }
+        matches = super.updateMatch(matches, params);
 
         Long sport = null;
         Long dport = null;
index 7ad60df97c32180eb6e5df9d0d151bfeb461140d..e092df4836cddcf7930ee2b8f70ca42b4b67c8d1 100644 (file)
@@ -34,7 +34,8 @@ public class SubjectFeatures {
             ImmutableMap.<ClassifierDefinitionId, Classifier>
                 of(EtherTypeClassifier.ID, new EtherTypeClassifier(),
                    IpProtoClassifier.ID, new IpProtoClassifier(),
-                   L4Classifier.ID, new L4Classifier());
+                   L4Classifier.ID, new L4Classifier(),
+                   IpAddressClassifier.ID, new IpAddressClassifier());
 
     private static final List<ClassifierDefinition> classifierDefs =
             ImmutableList.copyOf(Collections2.transform(classifiers.values(), 
@@ -78,6 +79,7 @@ public class SubjectFeatures {
         return classifiers.get(id);
     }
 
+
     /**
      * Get the {@link Action} associated with the given
      * {@link ActionDefinitionId}
@@ -88,5 +90,4 @@ public class SubjectFeatures {
     public static Action getAction(ActionDefinitionId id) {
         return actions.get(id);
     }
-                                           
 }