2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
13 import java.util.ArrayList;
14 import java.util.HashSet;
15 import java.util.List;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.Type;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.ParameterBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinition;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ClassifierDefinitionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValue;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
39 import com.google.common.collect.ImmutableList;
42 * Match against TCP or UDP, and source and/or destination ports
44 public class L4Classifier extends Classifier {
47 * Source port parameter name
49 public static final String SRC_PORT_PARAM = "sourceport";
51 * Source port range parameter name
53 public static final String SRC_PORT_RANGE_PARAM = "sourceport_range";
55 * Destination port parameter name
57 public static final String DST_PORT_PARAM = "destport";
59 * Destination port range parameter name
61 public static final String DST_PORT_RANGE_PARAM = "destport_range";
63 protected static final ClassifierDefinitionId ID = new ClassifierDefinitionId(
64 "4250ab32-e8b8-445a-aebb-e1bd2cdd291f");
66 * Layer 4 classifier-definition
68 public static final ClassifierDefinition DEFINITION = new ClassifierDefinitionBuilder().setId(
69 new ClassifierDefinitionId("4250ab32-e8b8-445a-aebb-e1bd2cdd291f"))
70 .setParent(IpProtoClassifier.ID)
71 .setName(new ClassifierName("l4"))
72 .setDescription(new Description("Match on the port number of UDP or TCP traffic"))
75 new ParameterBuilder().setName(new ParameterName(SRC_PORT_PARAM))
76 .setDescription(new Description("The source port number to match against"))
79 new ParameterBuilder().setName(new ParameterName(SRC_PORT_RANGE_PARAM))
80 .setDescription(new Description("The source port range to match against"))
83 new ParameterBuilder().setName(new ParameterName(DST_PORT_PARAM))
84 .setDescription(new Description("The destination port number to match against"))
86 .build(), new ParameterBuilder().setName(new ParameterName(DST_PORT_RANGE_PARAM))
87 .setDescription(new Description("The destination port range to match against"))
92 protected L4Classifier(Classifier parent) {
97 public ClassifierDefinitionId getId() {
102 public ClassifierDefinition getClassDef() {
107 protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
108 if (params.get(SRC_PORT_PARAM) != null && params.get(SRC_PORT_RANGE_PARAM) != null) {
109 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
110 + "}+. Illegal source port parameters: 'int' and 'range' values are mutually exclusive.");
112 if (params.get(DST_PORT_PARAM) != null && params.get(DST_PORT_RANGE_PARAM) != null) {
113 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
114 + "}+. Illegal destination port parameters: 'int' and 'range' values are mutually exclusive.");
116 if (params.get(SRC_PORT_PARAM) != null) {
117 if (params.get(SRC_PORT_PARAM).getIntValue() == null) {
118 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
119 + "}+ Value of sourceport parameter is not present.");
122 if (params.get(SRC_PORT_RANGE_PARAM) != null) {
123 if (params.get(SRC_PORT_RANGE_PARAM) != null) {
124 validateRangeValue(params.get(SRC_PORT_RANGE_PARAM).getRangeValue());
128 if (params.get(DST_PORT_PARAM) != null) {
129 if (params.get(DST_PORT_PARAM).getIntValue() == null) {
130 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
131 + "}+ Value of destport parameter is not present.");
134 if (params.get(DST_PORT_RANGE_PARAM) != null) {
135 if (params.get(DST_PORT_RANGE_PARAM) != null) {
136 validateRangeValue(params.get(DST_PORT_RANGE_PARAM).getRangeValue());
141 private void validateRangeValue(RangeValue rangeValueParam) {
142 if (rangeValueParam == null) {
143 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
144 + "}+ Range value is not present.");
146 final Long min = rangeValueParam.getMin();
147 final Long max = rangeValueParam.getMax();
149 throw new IllegalArgumentException("Range value mismatch. MIN {" + min + "} is greater than MAX {" + max
155 public List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
156 Set<Long> sPorts = new HashSet<>();
157 Set<Long> dPorts = new HashSet<>();
158 if (params.get(SRC_PORT_PARAM) != null) {
159 sPorts.add(params.get(SRC_PORT_PARAM).getIntValue());
160 } else if (params.get(SRC_PORT_RANGE_PARAM) != null) {
161 sPorts.addAll(createSetFromRange(params.get(SRC_PORT_RANGE_PARAM).getRangeValue()));
163 if (params.get(DST_PORT_PARAM) != null) {
164 dPorts.add(params.get(DST_PORT_PARAM).getIntValue());
165 } else if (params.get(DST_PORT_RANGE_PARAM) != null) {
166 dPorts.addAll(createSetFromRange(params.get(DST_PORT_RANGE_PARAM).getRangeValue()));
169 List<MatchBuilder> newMatches = new ArrayList<>();
170 for (MatchBuilder matchBuilder : matches) {
171 Layer4Match l4Match = matchBuilder.getLayer4Match();
172 Set<? extends Layer4Match> l4Matches = null;
173 if (l4Match == null) {
174 l4Match = resolveL4Match(params);
176 if (l4Match instanceof UdpMatch) {
177 l4Matches = createUdpMatches((UdpMatch) l4Match, sPorts, dPorts);
178 } else if (l4Match instanceof TcpMatch) {
179 l4Matches = createTcpMatches((TcpMatch) l4Match, sPorts, dPorts);
180 } else if (l4Match instanceof SctpMatch) {
181 l4Matches = createSctpMatches((SctpMatch) l4Match, sPorts, dPorts);
183 for (Layer4Match newL4Match : l4Matches) {
184 newMatches.add(new MatchBuilder(matchBuilder.build()).setLayer4Match(newL4Match));
190 private Layer4Match resolveL4Match(Map<String, ParameterValue> params) {
191 Long ipProto = IpProtoClassifier.getIpProtoValue(params);
192 if (ipProto == null) {
193 throw new IllegalArgumentException("Classifier-instance " + this.getClassDef().getName()
194 + ": L4 protocol is null.");
196 if (IpProtoClassifier.UDP_VALUE.equals(ipProto)) {
197 return new UdpMatchBuilder().build();
198 } else if (IpProtoClassifier.TCP_VALUE.equals(ipProto)) {
199 return new TcpMatchBuilder().build();
200 } else if (IpProtoClassifier.SCTP_VALUE.equals(ipProto)) {
201 return new SctpMatchBuilder().build();
203 throw new IllegalArgumentException("Unsupported L4 protocol.");
206 private Set<Long> createSetFromRange(RangeValue rangeValueParam) {
207 Set<Long> res = new HashSet<>();
208 if (rangeValueParam != null) {
209 final Long min = rangeValueParam.getMin();
210 final Long max = rangeValueParam.getMax();
211 for (long val = min; val <= max; val++) {
218 private Set<UdpMatch> createUdpMatches(UdpMatch udpMatch, Set<Long> sPorts, Set<Long> dPorts) {
219 Set<UdpMatch> udpMatches = new HashSet<>();
220 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
221 for (Long srcPort : sPorts) {
222 equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
223 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue())).build());
225 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
226 for (Long dstPort : dPorts) {
227 equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
228 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpDestinationPort(new PortNumber(dstPort.intValue()))
231 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
232 for (Long srcPort : sPorts) {
233 for (Long dstPort : dPorts) {
234 equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
235 equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
236 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue()))
237 .setUdpDestinationPort(new PortNumber(dstPort.intValue()))
245 private Set<TcpMatch> createTcpMatches(TcpMatch tcpMatch, Set<Long> sPorts, Set<Long> dPorts) {
246 Set<TcpMatch> tcpMatches = new HashSet<>();
247 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
248 for (Long srcPort : sPorts) {
249 equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
250 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue())).build());
252 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
253 for (Long dstPort : dPorts) {
254 equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
255 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpDestinationPort(new PortNumber(dstPort.intValue()))
258 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
259 for (Long srcPort : sPorts) {
260 for (Long dstPort : dPorts) {
261 equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
262 equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
263 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue()))
264 .setTcpDestinationPort(new PortNumber(dstPort.intValue()))
272 private Set<SctpMatch> createSctpMatches(SctpMatch sctpMatch, Set<Long> sPorts, Set<Long> dPorts) {
273 Set<SctpMatch> sctpMatches = new HashSet<>();
274 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
275 for (Long srcPort : sPorts) {
276 equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
277 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
280 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
281 for (Long dstPort : dPorts) {
282 equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
283 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpDestinationPort(new PortNumber(dstPort.intValue()))
286 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
287 for (Long srcPort : sPorts) {
288 for (Long dstPort : dPorts) {
289 equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
290 equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
291 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
292 .setSctpDestinationPort(new PortNumber(dstPort.intValue()))
300 private void equalOrNotSetValidation(PortNumber portInMatch, long paramValue) {
301 if (portInMatch != null) {
302 if (paramValue != portInMatch.getValue().longValue()) {
303 throw new IllegalArgumentException("Classification conflict at " + this.getClassDef().getName()
304 + ": Trying to override port value: " + portInMatch.getValue().longValue() + " by value "
311 public void checkPrereqs(List<MatchBuilder> matches) {
312 for (MatchBuilder match : matches) {
315 proto = Long.valueOf(match.getIpMatch().getIpProtocol().longValue());
316 } catch (NullPointerException e) {
317 throw new IllegalArgumentException("Ip proto match is missing.");
319 if (!IpProtoClassifier.TCP_VALUE.equals(proto) && !IpProtoClassifier.UDP_VALUE.equals(proto)
320 && !IpProtoClassifier.SCTP_VALUE.equals(proto)) {
321 throw new IllegalArgumentException("Unsupported proto value.\n" + "Classifier: "
322 + this.getClass().getName() + ", proto set: " + proto);