Bug 2814 - logical OR to AND in classifier
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / sf / IpProtoClassifier.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
10
11 import java.util.List;
12 import java.util.Map;
13
14 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.IsRequired;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.Type;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.ParameterBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
27
28 import com.google.common.collect.ImmutableList;
29
30 /**
31  * Match on the IP protocol of IP traffic
32  */
33 public class IpProtoClassifier extends Classifier {
34
35     /**
36      * Protocol parameter name
37      */
38     public static final String PROTO_PARAM = "proto";
39     /**
40      * TCP protocol value
41      */
42     public static final Long TCP_VALUE = Long.valueOf(6);
43     /**
44      * UDP protocol value
45      */
46     public static final Long UDP_VALUE = Long.valueOf(17);
47     /**
48      * ICMP protocol value
49      */
50     public static final Long ICMP_VALUE = Long.valueOf(1);
51     /**
52      * SCTP protocol value
53      */
54     public static final Long SCTP_VALUE = Long.valueOf(132);
55
56     protected static final ClassifierDefinitionId ID = new ClassifierDefinitionId(
57             "79c6fdb2-1e1a-4832-af57-c65baf5c2335");
58     /**
59      * Protocol classifier-definition
60      */
61     public static final ClassifierDefinition DEFINITION = new ClassifierDefinitionBuilder().setId(ID)
62         .setParent(EtherTypeClassifier.ID)
63         .setName(new ClassifierName("ip_proto"))
64         .setDescription(new Description("Match on the IP protocol of IP traffic"))
65         .setParameter(
66                 ImmutableList.of(new ParameterBuilder().setName(new ParameterName(PROTO_PARAM))
67                     .setDescription(new Description("The IP protocol to match against"))
68                     .setIsRequired(IsRequired.Required)
69                     .setType(Type.Int)
70                     .build()))
71         .build();
72
73     protected IpProtoClassifier(Classifier parent) {
74         super(parent);
75     }
76
77     @Override
78     public ClassifierDefinitionId getId() {
79         return ID;
80     }
81
82     @Override
83     public ClassifierDefinition getClassDef() {
84         return DEFINITION;
85     }
86
87     @Override
88     protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
89         if (params.get(PROTO_PARAM) == null) {
90             throw new IllegalArgumentException("Parameter " + PROTO_PARAM + " not specified.");
91         }
92         if (params.get(PROTO_PARAM).getIntValue() == null) {
93             throw new IllegalArgumentException("Value of " + PROTO_PARAM + " parameter is not present.");
94         }
95     }
96
97     @Override
98     protected List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
99         Long proto = params.get(PROTO_PARAM).getIntValue();
100         for (MatchBuilder match : matches) {
101             IpMatchBuilder imb;
102             if (match.getIpMatch() != null) {
103                 equalOrNotSetValidation(match.getIpMatch().getIpProtocol(), proto);
104                 continue;
105             } else {
106                 imb = new IpMatchBuilder();
107             }
108             imb.setIpProtocol(proto.shortValue());
109             match.setIpMatch(imb.build());
110         }
111         return matches;
112     }
113
114     private void equalOrNotSetValidation(Short protoInMatch, long paramValue) {
115         if (protoInMatch != null) {
116             if (paramValue != protoInMatch.longValue()) {
117                 throw new IllegalArgumentException("Classification conflict detected at " + PROTO_PARAM
118                         + " parameter for values " + protoInMatch.shortValue() + " and " + paramValue
119                         + ". It is not allowed "
120                         + "to assign different values to the same parameter among all the classifiers within one rule.");
121             }
122         }
123     }
124
125     @Override
126     protected void checkPrereqs(List<MatchBuilder> matches) {
127         for (MatchBuilder match : matches) {
128             Long readEthType = null;
129             try {
130                 readEthType = match.getEthernetMatch().getEthernetType().getType().getValue();
131             } catch (NullPointerException e) {
132                 throw new IllegalArgumentException("Parameter " + EtherTypeClassifier.ETHERTYPE_PARAM + " is missing.");
133             }
134             if (!FlowUtils.IPv4.equals(readEthType) && !FlowUtils.IPv6.equals(readEthType)) {
135                 throw new IllegalArgumentException("Parameter " + EtherTypeClassifier.ETHERTYPE_PARAM + " must have value "
136                         + FlowUtils.IPv4 + " or " + FlowUtils.IPv6 + ".");
137             }
138         }
139     }
140
141     /**
142      * May return null.
143      */
144     public static Long getIpProtoValue(Map<String, ParameterValue> params) {
145         if (params == null) {
146             return null;
147         }
148         if (params.get(PROTO_PARAM) == null) {
149             return null;
150         }
151         Long proto = params.get(PROTO_PARAM).getIntValue();
152         if (proto != null) {
153             return proto;
154         }
155         return null;
156     }
157 }