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 {
46 public static final String SPORT = "sourceport";
47 public static final String SPORT_RANGE = "sourceport_range";
48 public static final String DPORT = "destport";
49 public static final String DPORT_RANGE = "destport_range";
50 public static final ClassifierDefinitionId ID = new ClassifierDefinitionId("4250ab32-e8b8-445a-aebb-e1bd2cdd291f");
51 private static final ClassifierDefinition DEF = new ClassifierDefinitionBuilder().setId(
52 new ClassifierDefinitionId("4250ab32-e8b8-445a-aebb-e1bd2cdd291f"))
53 .setParent(IpProtoClassifier.ID)
54 .setName(new ClassifierName("l4"))
55 .setDescription(new Description("Match on the port number of UDP or TCP traffic"))
58 new ParameterBuilder().setName(new ParameterName(SPORT))
59 .setDescription(new Description("The source port number to match against"))
62 new ParameterBuilder().setName(new ParameterName(SPORT_RANGE))
63 .setDescription(new Description("The source port range to match against"))
66 new ParameterBuilder().setName(new ParameterName(DPORT))
67 .setDescription(new Description("The destination port number to match against"))
70 new ParameterBuilder().setName(new ParameterName(DPORT_RANGE))
71 .setDescription(new Description("The destination port range to match against"))
76 protected L4Classifier(Classifier parent) {
81 public ClassifierDefinitionId getId() {
86 public ClassifierDefinition getClassDef() {
91 protected void checkPresenceOfRequiredParams(Map<String, ParameterValue> params) {
92 if (params.get(SPORT) != null && params.get(SPORT_RANGE) != null) {
93 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
94 + "}+. Illegal source port parameters: 'int' and 'range' values are mutually exclusive.");
96 if (params.get(DPORT) != null && params.get(DPORT_RANGE) != null) {
97 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
98 + "}+. Illegal destination port parameters: 'int' and 'range' values are mutually exclusive.");
100 if (params.get(SPORT) != null) {
101 if (params.get(SPORT).getIntValue() == null) {
102 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
103 + "}+ Value of sourceport parameter is not present.");
106 if (params.get(SPORT_RANGE) != null) {
107 if (params.get(SPORT_RANGE) != null) {
108 validateRangeValue(params.get(SPORT_RANGE).getRangeValue());
112 if (params.get(DPORT) != null) {
113 if (params.get(DPORT).getIntValue() == null) {
114 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
115 + "}+ Value of destport parameter is not present.");
118 if (params.get(DPORT_RANGE) != null) {
119 if (params.get(DPORT_RANGE) != null) {
120 validateRangeValue(params.get(DPORT_RANGE).getRangeValue());
125 private void validateRangeValue(RangeValue rangeValueParam) {
126 if (rangeValueParam == null) {
127 throw new IllegalArgumentException("Classifier: {" + this.getClassDef().getName()
128 + "}+ Range value is not present.");
130 final Long min = rangeValueParam.getMin();
131 final Long max = rangeValueParam.getMax();
133 throw new IllegalArgumentException("Range value mismatch. MIN {" + min + "} is greater than MAX {" + max
139 public List<MatchBuilder> update(List<MatchBuilder> matches, Map<String, ParameterValue> params) {
140 Set<Long> sPorts = new HashSet<>();
141 Set<Long> dPorts = new HashSet<>();
142 if (params.get(SPORT) != null) {
143 sPorts.add(params.get(SPORT).getIntValue());
144 } else if (params.get(SPORT_RANGE) != null) {
145 sPorts.addAll(createSetFromRange(params.get(SPORT_RANGE).getRangeValue()));
147 if (params.get(DPORT) != null) {
148 dPorts.add(params.get(DPORT).getIntValue());
149 } else if (params.get(DPORT_RANGE) != null) {
150 dPorts.addAll(createSetFromRange(params.get(DPORT_RANGE).getRangeValue()));
153 List<MatchBuilder> newMatches = new ArrayList<>();
154 for (MatchBuilder matchBuilder : matches) {
155 Layer4Match l4Match = matchBuilder.getLayer4Match();
156 Set<? extends Layer4Match> l4Matches = null;
157 if (l4Match == null) {
158 l4Match = resolveL4Match(params);
160 if (l4Match instanceof UdpMatch) {
161 l4Matches = createUdpMatches((UdpMatch) l4Match, sPorts, dPorts);
162 } else if (l4Match instanceof TcpMatch) {
163 l4Matches = createTcpMatches((TcpMatch) l4Match, sPorts, dPorts);
164 } else if (l4Match instanceof SctpMatch) {
165 l4Matches = createSctpMatches((SctpMatch) l4Match, sPorts, dPorts);
167 for (Layer4Match newL4Match : l4Matches) {
168 newMatches.add(new MatchBuilder(matchBuilder.build()).setLayer4Match(newL4Match));
174 private Layer4Match resolveL4Match(Map<String, ParameterValue> params) {
175 Long ipProto = IpProtoClassifier.getIpProtoValue(params);
176 if (ipProto == null) {
177 throw new IllegalArgumentException("Classifier-instance " + this.getClassDef().getName()
178 + ": L4 protocol is null.");
180 if (IpProtoClassifier.UDP.equals(ipProto)) {
181 return new UdpMatchBuilder().build();
182 } else if (IpProtoClassifier.TCP.equals(ipProto)) {
183 return new TcpMatchBuilder().build();
184 } else if (IpProtoClassifier.SCTP.equals(ipProto)) {
185 return new SctpMatchBuilder().build();
187 throw new IllegalArgumentException("Unsupported L4 protocol.");
190 private Set<Long> createSetFromRange(RangeValue rangeValueParam) {
191 Set<Long> res = new HashSet<>();
192 if (rangeValueParam != null) {
193 final Long min = rangeValueParam.getMin();
194 final Long max = rangeValueParam.getMax();
195 for (long val = min; val <= max; val++) {
202 private Set<UdpMatch> createUdpMatches(UdpMatch udpMatch, Set<Long> sPorts, Set<Long> dPorts) {
203 Set<UdpMatch> udpMatches = new HashSet<>();
204 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
205 for (Long srcPort : sPorts) {
206 equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
207 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue())).build());
209 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
210 for (Long dstPort : dPorts) {
211 equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
212 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpDestinationPort(new PortNumber(dstPort.intValue()))
215 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
216 for (Long srcPort : sPorts) {
217 for (Long dstPort : dPorts) {
218 equalOrNotSetValidation(udpMatch.getUdpSourcePort(), srcPort.longValue());
219 equalOrNotSetValidation(udpMatch.getUdpDestinationPort(), dstPort.longValue());
220 udpMatches.add(new UdpMatchBuilder(udpMatch).setUdpSourcePort(new PortNumber(srcPort.intValue()))
221 .setUdpDestinationPort(new PortNumber(dstPort.intValue()))
229 private Set<TcpMatch> createTcpMatches(TcpMatch tcpMatch, Set<Long> sPorts, Set<Long> dPorts) {
230 Set<TcpMatch> tcpMatches = new HashSet<>();
231 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
232 for (Long srcPort : sPorts) {
233 equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
234 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue())).build());
236 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
237 for (Long dstPort : dPorts) {
238 equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
239 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpDestinationPort(new PortNumber(dstPort.intValue()))
242 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
243 for (Long srcPort : sPorts) {
244 for (Long dstPort : dPorts) {
245 equalOrNotSetValidation(tcpMatch.getTcpSourcePort(), srcPort.longValue());
246 equalOrNotSetValidation(tcpMatch.getTcpDestinationPort(), dstPort.longValue());
247 tcpMatches.add(new TcpMatchBuilder(tcpMatch).setTcpSourcePort(new PortNumber(srcPort.intValue()))
248 .setTcpDestinationPort(new PortNumber(dstPort.intValue()))
256 private Set<SctpMatch> createSctpMatches(SctpMatch sctpMatch, Set<Long> sPorts, Set<Long> dPorts) {
257 Set<SctpMatch> sctpMatches = new HashSet<>();
258 if (!sPorts.isEmpty() && dPorts.isEmpty()) {
259 for (Long srcPort : sPorts) {
260 equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
261 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
264 } else if (sPorts.isEmpty() && !dPorts.isEmpty()) {
265 for (Long dstPort : dPorts) {
266 equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
267 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpDestinationPort(new PortNumber(dstPort.intValue()))
270 } else if (!sPorts.isEmpty() && !dPorts.isEmpty()) {
271 for (Long srcPort : sPorts) {
272 for (Long dstPort : dPorts) {
273 equalOrNotSetValidation(sctpMatch.getSctpSourcePort(), srcPort.longValue());
274 equalOrNotSetValidation(sctpMatch.getSctpDestinationPort(), dstPort.longValue());
275 sctpMatches.add(new SctpMatchBuilder(sctpMatch).setSctpSourcePort(new PortNumber(srcPort.intValue()))
276 .setSctpDestinationPort(new PortNumber(dstPort.intValue()))
284 private void equalOrNotSetValidation(PortNumber portInMatch, long paramValue) {
285 if (portInMatch != null) {
286 if (paramValue != portInMatch.getValue().longValue()) {
287 throw new IllegalArgumentException("Classification conflict at " + this.getClassDef().getName()
288 + ": Trying to override port value: " + portInMatch.getValue().longValue() + " by value "
295 public void checkPrereqs(List<MatchBuilder> matches) {
296 for (MatchBuilder match : matches) {
299 proto = Long.valueOf(match.getIpMatch().getIpProtocol().longValue());
300 } catch (NullPointerException e) {
301 throw new IllegalArgumentException("Ip proto match is missing.");
303 if (!IpProtoClassifier.TCP.equals(proto) && !IpProtoClassifier.UDP.equals(proto)
304 && !IpProtoClassifier.SCTP.equals(proto)) {
305 throw new IllegalArgumentException("Unsupported proto value.\n" + "Classifier: "
306 + this.getClass().getName() + ", proto set: " + proto);